Skip to content

Commit b9e9355

Browse files
author
Milanez, Pedro
committed
small fixes and update CITATION.
1 parent bf1e464 commit b9e9355

6 files changed

Lines changed: 82 additions & 50 deletions

File tree

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ po/*~
4747

4848
# RStudio Connect folder
4949
rsconnect/
50+
51+
# RStudio Project
5052
tinydenseR.Rproj
5153

5254
# macOS

‎R/lm.graph.embed.R‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,12 +1068,12 @@ get.map <-
10681068
)() |>
10691069
unique()
10701070

1071-
.lm.obj$graph$celltyping$mean.exprs <-
1071+
.lm.obj$graph$celltyping$median.exprs <-
10721072
(if(.lm.obj$assay.type == "RNA") .lm.obj$scaled.lm[,top] else .lm.obj$lm) |>
10731073
dplyr::as_tibble() |>
10741074
cbind(cell.pop = as.character(x = .lm.obj$graph$celltyping$ids)) |>
10751075
dplyr::group_by(cell.pop) |>
1076-
dplyr::summarize_all(.funs = mean) |>
1076+
dplyr::summarize_all(.funs = stats::median) |>
10771077
as.data.frame() |>
10781078
(\(x)
10791079
`rownames<-`(x = x[,colnames(x = x) != "cell.pop"],
@@ -1082,7 +1082,7 @@ get.map <-
10821082
as.matrix()
10831083

10841084
.lm.obj$graph$celltyping$pheatmap <-
1085-
pheatmap::pheatmap(mat = .lm.obj$graph$celltyping$mean.exprs,
1085+
pheatmap::pheatmap(mat = .lm.obj$graph$celltyping$median.exprs,
10861086
color = grDevices::colorRampPalette(
10871087
unname(obj =
10881088
Color.Palette[1,c(1,6,2)]))(100),
@@ -1386,13 +1386,13 @@ lm.cluster <-
13861386

13871387
}
13881388

1389-
# Compute mean expression per cluster
1390-
.lm.obj$graph$clustering$mean.exprs <-
1389+
# Compute median expression per cluster
1390+
.lm.obj$graph$clustering$median.exprs <-
13911391
(if(.lm.obj$assay.type == "RNA") .lm.obj$scaled.lm[,top] else .lm.obj$lm) |>
13921392
dplyr::as_tibble() |>
13931393
cbind(cell.pop = as.character(x = .lm.obj$graph$clustering$ids)) |>
13941394
dplyr::group_by(cell.pop) |>
1395-
dplyr::summarize_all(.funs = mean) |>
1395+
dplyr::summarize_all(.funs = stats::median) |>
13961396
as.data.frame() |>
13971397
(\(x)
13981398
`rownames<-`(x = x[,colnames(x = x) != "cell.pop"],
@@ -1402,7 +1402,7 @@ lm.cluster <-
14021402

14031403
# Generate heatmap of cluster profiles
14041404
.lm.obj$graph$clustering$pheatmap <-
1405-
pheatmap::pheatmap(mat = .lm.obj$graph$clustering$mean.exprs,
1405+
pheatmap::pheatmap(mat = .lm.obj$graph$clustering$median.exprs,
14061406
color = grDevices::colorRampPalette(
14071407
unname(obj =
14081408
Color.Palette[1,c(1,6,2)]))(100),
@@ -1411,7 +1411,7 @@ lm.cluster <-
14111411
border_color = NA,
14121412
scale = "none",
14131413
angle_col = 90,
1414-
cluster_rows = if(nrow(x = .lm.obj$graph$clustering$mean.exprs) > 1) TRUE else FALSE,
1414+
cluster_rows = if(nrow(x = .lm.obj$graph$clustering$median.exprs) > 1) TRUE else FALSE,
14151415
cluster_cols = TRUE,
14161416
cellwidth = 20,
14171417
cellheight = 20,

‎R/plot.R‎

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -570,12 +570,7 @@ plotBeeswarm <-
570570
y = "",
571571
size = "%") +
572572
ggplot2::scale_x_discrete(labels = "mean % across\nall samples") +
573-
{
574-
if(isFALSE(x = .order.ids)){
575-
ggplot2::scale_y_discrete(limits = rev)
576-
}
577-
578-
} +
573+
ggplot2::scale_y_discrete(limits = rev) +
579574
ggplot2::scale_size_continuous(range = log2(x = x$cell.perc + 1) |>
580575
range() |>
581576
I()) +
@@ -736,12 +731,7 @@ plotBeeswarm <-
736731
scales = .facet.scales)
737732
}
738733
} +
739-
{
740-
if(isFALSE(x = .order.ids)){
741-
ggplot2::scale_y_discrete(limits = rev)
742-
}
743-
744-
} +
734+
ggplot2::scale_y_discrete(limits = rev) +
745735
ggplot2::geom_point(position = ggplot2::position_jitter(width = 0,
746736
height = 0.25),
747737
size = I(x = .point.size)) +
@@ -898,7 +888,7 @@ plot2Markers <-
898888

899889
dat.df <-
900890
(.lm.obj$lm[if(!is.null(x = .id)) .id else 1:nrow(x = .lm.obj$lm),
901-
colnames(x = .lm.obj$lm) %in% c(.x.feature,.y.feature)]/50) |>
891+
colnames(x = .lm.obj$lm) %in% c(.x.feature,.y.feature)]) |>
902892
as.data.frame()
903893

904894
}
@@ -936,7 +926,7 @@ plot2Markers <-
936926

937927
p <-
938928
p +
939-
ggplot2::stat_density_2d(data = as.data.frame(x = .lm.obj$lm / (if(.lm.obj$assay.type == "RNA") 1 else 50)),
929+
ggplot2::stat_density_2d(data = as.data.frame(x = .lm.obj$lm),
940930
mapping = ggplot2::aes(fill = ggplot2::after_stat(x = log2(x = level))),
941931
geom = "polygon",
942932
bins = .density.bins) +
@@ -1197,12 +1187,7 @@ plotTradStats <-
11971187
y = "",
11981188
size = "%") +
11991189
ggplot2::scale_x_discrete(labels = "mean % across\nall samples") +
1200-
{
1201-
if(isFALSE(x = .order.ids)){
1202-
ggplot2::scale_y_discrete(limits = rev)
1203-
}
1204-
1205-
} +
1190+
ggplot2::scale_y_discrete(limits = rev) +
12061191
ggplot2::scale_size_continuous(range = log2(x = x$cell.perc + 1) |>
12071192
range()) +
12081193
ggplot2::geom_point() +
@@ -1296,23 +1281,13 @@ plotTradStats <-
12961281
ggplot2::scale_fill_gradient2(low = unname(obj = Color.Palette[1,1]),
12971282
mid = unname(obj = Color.Palette[1,6]),
12981283
high = unname(obj = Color.Palette[1,2]),
1299-
midpoint = 0#,
1300-
#labels = ~ ifelse(test = .x >= 0,
1301-
# yes = round(x = 2^.x,
1302-
# digits = 1),
1303-
# no = -round(x = 1 / 2^.x,
1304-
# digits = 1))
1284+
midpoint = 0
13051285
) +
13061286
ggplot2::scale_size_continuous(labels = ~ formatC(x = 10^(-(.x)),
13071287
format = "g",
13081288
digits = 1),
13091289
range = I(x = c(3,6))) +
1310-
{
1311-
if(isFALSE(x = .order.ids)){
1312-
ggplot2::scale_y_discrete(limits = rev)
1313-
}
1314-
1315-
} +
1290+
ggplot2::scale_y_discrete(limits = rev) +
13161291
ggplot2::geom_point(shape = 21,
13171292
mapping = ggplot2::aes(size = -log10(x = adj.p)),
13181293
color = "black",
@@ -1360,10 +1335,12 @@ plotTradStats <-
13601335
#'
13611336
#' @param .lm.obj A tinydenseR object processed through \code{get.map()}.
13621337
#' @param .x.split Character specifying metadata column for x-axis grouping. Defaults to first
1363-
#' column (often "Condition").
1338+
#' column.
1339+
#' @param .x.split.subset Optional character vector to subset \code{.x.split} categories. Default NULL.
13641340
#' @param .pop Character vector of population names to plot. If NULL, plots all populations from
13651341
#' \code{.pop.from}.
13661342
#' @param .pop.from Character: "clustering" (default) or "celltyping" - which grouping to plot.
1343+
#' @param .order.pop Logical whether to order populations based on dendrogram order (default FALSE).
13671344
#' @param .line.by Character metadata column for connecting paired samples with lines (e.g.,
13681345
#' "Subject" for longitudinal data). Default NULL (no lines).
13691346
#' @param .dodge.by Character metadata column for coloring/dodging points. Default NULL (all black).
@@ -1373,6 +1350,7 @@ plotTradStats <-
13731350
#' \code{Color.Palette[1,1:5]}).
13741351
#' @param .seed Integer random seed for x-axis jitter (default 123).
13751352
#' @param .orientation Character: "wide" (default, all populations in one row) or "square" (facet grid).
1353+
#' @param .log2.y Logical whether to log2-transform y-axis percentages (default FALSE).
13761354
#'
13771355
#' @return A \code{ggplot} object showing cell percentages with optional paired connections.
13781356
#'
@@ -1413,15 +1391,18 @@ plotTradPerc <-
14131391
function(
14141392
.lm.obj,
14151393
.x.split = colnames(x = .lm.obj$metadata)[1],
1394+
.x.split.subset = NULL,
14161395
.pop = NULL,
14171396
.pop.from = "clustering",
1397+
.order.pop = FALSE,
14181398
.line.by = NULL,
14191399
.dodge.by = NULL,
14201400
.x.space.scaler = 0.25,
14211401
.height = 1.5,
14221402
.cat.feature.color = Color.Palette[1,1:5],
14231403
.seed = 123,
1424-
.orientation = "wide"
1404+
.orientation = "wide",
1405+
.log2.y = FALSE
14251406
){
14261407

14271408
dodge <- value <- name <- color <- group <- x <- y <- NULL
@@ -1436,6 +1417,14 @@ plotTradPerc <-
14361417
collapse = ", ")))
14371418
}
14381419

1420+
if(!is.null(x = .x.split.subset)){
1421+
if(!all(.x.split.subset %in% .lm.obj$metadata[[.x.split]])){
1422+
stop(paste0(".x.split.subset must within the following: ",
1423+
paste(x = unique(x = .lm.obj$metadata[[.x.split]]),
1424+
collapse = ", ")))
1425+
}
1426+
}
1427+
14391428
if(!is.null(x = .dodge.by)){
14401429
if(length(x = .dodge.by) != 1){
14411430
stop(".dodge.by must be length 1")
@@ -1506,6 +1495,23 @@ plotTradPerc <-
15061495

15071496
}
15081497

1498+
if(!is.null(x = .x.split.subset)){
1499+
1500+
dat.df <-
1501+
droplevels(x = dat.df[dat.df$x %in% .x.split.subset,])
1502+
1503+
}
1504+
1505+
if(isTRUE(x = .order.pop)){
1506+
1507+
dat.df$name <-
1508+
as.character(x = dat.df$name) |>
1509+
factor(levels = .lm.obj$graph[[.pop.from]]$pheatmap$tree_row$labels[
1510+
.lm.obj$graph[[.pop.from]]$pheatmap$tree_row$order
1511+
])
1512+
1513+
}
1514+
15091515
p <-
15101516
ggplot2::ggplot(data = dat.df,
15111517
mapping = ggplot2::aes(x = x,
@@ -1579,6 +1585,12 @@ plotTradPerc <-
15791585
seed = .seed))
15801586
}
15811587

1588+
if(isTRUE(x = .log2.y)){
1589+
p <-
1590+
p +
1591+
ggplot2::scale_y_continuous(transform = "log2")
1592+
}
1593+
15821594
p
15831595

15841596
}

‎R/stats.model.R‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,11 @@ get.stats <-
308308
}
309309
return(adjp)
310310

311-
})
311+
}) |>
312+
(\(x)
313+
`dimnames<-`(x = x,
314+
value = dimnames(x = stats$fit$p.value))
315+
)()
312316

313317
if(isTRUE(x = .verbose)){
314318
message("\nretrieving PCA-weighted q-values")
@@ -388,6 +392,11 @@ get.stats <-
388392
MARGIN = 2,
389393
FUN = function(pvalues){
390394

395+
if((is.na(x = pvalues) |> mean()) == 1){
396+
return(rep(x = NA_real_,
397+
length.out = length(x = pvalues)))
398+
}
399+
391400
if(length(x = pvalues) < 100){
392401

393402
res <-

‎inst/CITATION‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ citHeader("To cite tinydenseR in publications use:")
22

33
citEntry(
44
entry = "Manual",
5-
title = "tinydenseR: Linking Cell-To-Cell Variation to Sample-to-Sample Variation",
5+
title = "Sample-level modeling of single-cell data at scale with tinydenseR",
66
author = c(
77
person("Pedro", "Milanez-Almeida", email = "Pedro.Milanez@Novartis.com"),
88
person("Daniela", "Schildknecht"),
@@ -24,11 +24,11 @@ citEntry(
2424
),
2525
year = "2025",
2626
note = "R package version 0.0.1.0008",
27-
url = "https://github.com/Novartis/tinydenseR",
27+
url = "https://www.biorxiv.org/content/10.1101/2025.11.26.690752v1",
28+
doi = "https://doi.org/10.1101/2025.11.26.690752",
2829
textVersion = paste(
2930
"Milanez-Almeida, P. et al. (2025).",
30-
"tinydenseR: Linking Cell-To-Cell Variation to Sample-to-Sample Variation.",
31-
"R package version 0.0.1.0008.",
32-
"URL https://github.com/Novartis/tinydenseR"
31+
"Sample-level modeling of single-cell data at scale with tinydenseR.",
32+
"bioRxiv https://doi.org/10.1101/2025.11.26.690752"
3333
)
3434
)

‎man/plotTradPerc.Rd‎

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)