I am trying to make a custom function based on the CellChat v1.6.1 function netVisual_heatmap(). I wanted to make the font size of the legend editable as is the case for the other text. I only made a small modification in the function and set environment(netVisual_heatmapCustom) <- asNamespace(“CellChat”) but it now keeps throwing the error: Error in grDevices::col2rgb(colors) : invalid color name ‘Reds’.
This is the source code of the function:
function (object, comparison = c(1, 2), measure = c("count",
"weight"), signaling = NULL, slot.name = c("netP", "net"),
color.use = NULL, color.heatmap = c("Reds"), title.name = NULL,
width = NULL, height = NULL, font.size = 8, font.size.title = 10,
cluster.rows = FALSE, cluster.cols = FALSE, sources.use = NULL,
targets.use = NULL, remove.isolate = FALSE, row.show = NULL,
col.show = NULL)
{
if (!is.null(measure)) {
measure <- match.arg(measure)
}
slot.name <- match.arg(slot.name)
if (is.list(object@net[[1]])) {
message("Do heatmap based on a merged object n")
obj1 <- object@net[[comparison[1]]][[measure]]
obj2 <- object@net[[comparison[2]]][[measure]]
net.diff <- obj2 - obj1
if (measure == "count") {
if (is.null(title.name)) {
title.name = "Differential number of interactions"
}
}
else if (measure == "weight") {
if (is.null(title.name)) {
title.name = "Differential interaction strength"
}
}
legend.name = "Relative values"
}
else {
message("Do heatmap based on a single object n")
if (!is.null(signaling)) {
net.diff <- slot(object, slot.name)$prob[, , signaling]
if (is.null(title.name)) {
title.name = paste0(signaling, " signaling network")
}
legend.name <- "Communication Prob."
}
else if (!is.null(measure)) {
net.diff <- object@net[[measure]]
if (measure == "count") {
if (is.null(title.name)) {
title.name = "Number of interactions"
}
}
else if (measure == "weight") {
if (is.null(title.name)) {
title.name = "Interaction strength"
}
}
legend.name <- title.name
}
}
net <- net.diff
if ((!is.null(sources.use)) | (!is.null(targets.use))) {
df.net <- reshape2::melt(net, value.name = "value")
colnames(df.net)[1:2] <- c("source", "target")
if (!is.null(sources.use)) {
if (is.numeric(sources.use)) {
sources.use <- rownames(net.diff)[sources.use]
}
df.net <- subset(df.net, source %in% sources.use)
}
if (!is.null(targets.use)) {
if (is.numeric(targets.use)) {
targets.use <- rownames(net.diff)[targets.use]
}
df.net <- subset(df.net, target %in% targets.use)
}
cells.level <- rownames(net.diff)
df.net$source <- factor(df.net$source, levels = cells.level)
df.net$target <- factor(df.net$target, levels = cells.level)
df.net$value[is.na(df.net$value)] <- 0
net <- tapply(df.net[["value"]], list(df.net[["source"]],
df.net[["target"]]), sum)
}
net[is.na(net)] <- 0
if (is.null(color.use)) {
color.use <- scPalette(ncol(net))
}
names(color.use) <- colnames(net)
color.use.row <- color.use
color.use.col <- color.use
if (remove.isolate) {
idx1 <- which(Matrix::rowSums(net) == 0)
idx2 <- which(Matrix::colSums(net) == 0)
if (length(idx1) > 0) {
net <- net[-idx1, ]
color.use.row <- color.use.row[-idx1]
}
if (length(idx2) > 0) {
net <- net[, -idx2]
color.use.col <- color.use.col[-idx2]
}
}
mat <- net
if (!is.null(row.show)) {
mat <- mat[row.show, ]
color.use.row <- color.use.row[row.show]
}
if (!is.null(col.show)) {
mat <- mat[, col.show]
color.use.col <- color.use.col[col.show]
}
if (min(mat) < 0) {
color.heatmap.use = colorRamp3(c(min(mat), 0, max(mat)),
c(color.heatmap[1], "#f7f7f7", color.heatmap[2]))
colorbar.break <- c(round(min(mat, na.rm = T), digits = nchar(sub(".*\.(0*).*",
"\1", min(mat, na.rm = T))) + 1), 0, round(max(mat,
na.rm = T), digits = nchar(sub(".*\.(0*).*", "\1",
max(mat, na.rm = T))) + 1))
}
else {
if (length(color.heatmap) == 3) {
color.heatmap.use = colorRamp3(c(0, min(mat), max(mat)),
color.heatmap)
}
else if (length(color.heatmap) == 2) {
color.heatmap.use = colorRamp3(c(min(mat), max(mat)),
color.heatmap)
}
else if (length(color.heatmap) == 1) {
color.heatmap.use = (grDevices::colorRampPalette((RColorBrewer::brewer.pal(n = 9,
name = color.heatmap))))(100)
}
colorbar.break <- c(round(min(mat, na.rm = T), digits = nchar(sub(".*\.(0*).*",
"\1", min(mat, na.rm = T))) + 1), round(max(mat,
na.rm = T), digits = nchar(sub(".*\.(0*).*", "\1",
max(mat, na.rm = T))) + 1))
}
df.col <- data.frame(group = colnames(mat))
rownames(df.col) <- colnames(mat)
df.row <- data.frame(group = rownames(mat))
rownames(df.row) <- rownames(mat)
col_annotation <- HeatmapAnnotation(df = df.col, col = list(group = color.use.col),
which = "column", show_legend = FALSE, show_annotation_name = FALSE,
simple_anno_size = grid::unit(0.2, "cm"))
row_annotation <- HeatmapAnnotation(df = df.row, col = list(group = color.use.row),
which = "row", show_legend = FALSE, show_annotation_name = FALSE,
simple_anno_size = grid::unit(0.2, "cm"))
ha1 = rowAnnotation(Strength = anno_barplot(rowSums(abs(mat)),
border = FALSE, gp = gpar(fill = color.use.row, col = color.use.row)),
show_annotation_name = FALSE)
ha2 = HeatmapAnnotation(Strength = anno_barplot(colSums(abs(mat)),
border = FALSE, gp = gpar(fill = color.use.col, col = color.use.col)),
show_annotation_name = FALSE)
if (sum(abs(mat) > 0) == 1) {
color.heatmap.use = c("white", color.heatmap.use)
}
else {
mat[mat == 0] <- NA
}
ht1 = Heatmap(mat, col = color.heatmap.use, na_col = "white",
name = legend.name, bottom_annotation = col_annotation,
left_annotation = row_annotation, top_annotation = ha2,
right_annotation = ha1, cluster_rows = cluster.rows,
cluster_columns = cluster.rows, row_names_side = "left",
row_names_rot = 0, row_names_gp = gpar(fontsize = font.size),
column_names_gp = gpar(fontsize = font.size), column_title = title.name,
column_title_gp = gpar(fontsize = font.size.title),
column_names_rot = 90, row_title = "Sources (Sender)",
row_title_gp = gpar(fontsize = font.size.title), row_title_rot = 90,
heatmap_legend_param = list(title_gp = gpar(fontsize = 8,
fontface = "plain"), title_position = "leftcenter-rot",
border = NA, legend_height = unit(20, "mm"), labels_gp = gpar(fontsize = 8),
grid_width = unit(2, "mm")))
return(ht1)
}
And this is what I changed it to. Note the only modification is in heatmap_legend_param where I changed fontsize = 8 to fontsize = font.size for title_gp and labels_gp.
netVisual_heatmapCustom <- function (object, comparison = c(1, 2), measure = c("count",
"weight"), signaling = NULL, slot.name = c("netP", "net"),
color.use = NULL, color.heatmap = c("Reds"), title.name = NULL,
width = NULL, height = NULL, font.size = 8, font.size.title = 10,
cluster.rows = FALSE, cluster.cols = FALSE, sources.use = NULL,
targets.use = NULL, remove.isolate = FALSE, row.show = NULL,
col.show = NULL)
{
if (!is.null(measure)) {
measure <- match.arg(measure)
}
slot.name <- match.arg(slot.name)
if (is.list(object@net[[1]])) {
message("Do heatmap based on a merged object n")
obj1 <- object@net[[comparison[1]]][[measure]]
obj2 <- object@net[[comparison[2]]][[measure]]
net.diff <- obj2 - obj1
if (measure == "count") {
if (is.null(title.name)) {
title.name = "Differential number of interactions"
}
}
else if (measure == "weight") {
if (is.null(title.name)) {
title.name = "Differential interaction strength"
}
}
legend.name = "Relative values"
}
else {
message("Do heatmap based on a single object n")
if (!is.null(signaling)) {
net.diff <- slot(object, slot.name)$prob[, , signaling]
if (is.null(title.name)) {
title.name = paste0(signaling, " signaling network")
}
legend.name <- "Communication Prob."
}
else if (!is.null(measure)) {
net.diff <- object@net[[measure]]
if (measure == "count") {
if (is.null(title.name)) {
title.name = "Number of interactions"
}
}
else if (measure == "weight") {
if (is.null(title.name)) {
title.name = "Interaction strength"
}
}
legend.name <- title.name
}
}
net <- net.diff
if ((!is.null(sources.use)) | (!is.null(targets.use))) {
df.net <- reshape2::melt(net, value.name = "value")
colnames(df.net)[1:2] <- c("source", "target")
if (!is.null(sources.use)) {
if (is.numeric(sources.use)) {
sources.use <- rownames(net.diff)[sources.use]
}
df.net <- subset(df.net, source %in% sources.use)
}
if (!is.null(targets.use)) {
if (is.numeric(targets.use)) {
targets.use <- rownames(net.diff)[targets.use]
}
df.net <- subset(df.net, target %in% targets.use)
}
cells.level <- rownames(net.diff)
df.net$source <- factor(df.net$source, levels = cells.level)
df.net$target <- factor(df.net$target, levels = cells.level)
df.net$value[is.na(df.net$value)] <- 0
net <- tapply(df.net[["value"]], list(df.net[["source"]],
df.net[["target"]]), sum)
}
net[is.na(net)] <- 0
if (is.null(color.use)) {
color.use <- scPalette(ncol(net))
}
names(color.use) <- colnames(net)
color.use.row <- color.use
color.use.col <- color.use
if (remove.isolate) {
idx1 <- which(Matrix::rowSums(net) == 0)
idx2 <- which(Matrix::colSums(net) == 0)
if (length(idx1) > 0) {
net <- net[-idx1, ]
color.use.row <- color.use.row[-idx1]
}
if (length(idx2) > 0) {
net <- net[, -idx2]
color.use.col <- color.use.col[-idx2]
}
}
mat <- net
if (!is.null(row.show)) {
mat <- mat[row.show, ]
color.use.row <- color.use.row[row.show]
}
if (!is.null(col.show)) {
mat <- mat[, col.show]
color.use.col <- color.use.col[col.show]
}
if (min(mat) < 0) {
color.heatmap.use = colorRamp3(c(min(mat), 0, max(mat)),
c(color.heatmap[1], "#f7f7f7", color.heatmap[2]))
colorbar.break <- c(round(min(mat, na.rm = T), digits = nchar(sub(".*\.(0*).*",
"\1", min(mat, na.rm = T))) + 1), 0, round(max(mat,
na.rm = T), digits = nchar(sub(".*\.(0*).*", "\1",
max(mat, na.rm = T))) + 1))
}
else {
if (length(color.heatmap) == 3) {
color.heatmap.use = colorRamp3(c(0, min(mat), max(mat)),
color.heatmap)
}
else if (length(color.heatmap) == 2) {
color.heatmap.use = colorRamp3(c(min(mat), max(mat)),
color.heatmap)
}
else if (length(color.heatmap) == 1) {
color.heatmap.use = (grDevices::colorRampPalette((RColorBrewer::brewer.pal(n = 9,
name = color.heatmap))))(100)
}
colorbar.break <- c(round(min(mat, na.rm = T), digits = nchar(sub(".*\.(0*).*",
"\1", min(mat, na.rm = T))) + 1), round(max(mat,
na.rm = T), digits = nchar(sub(".*\.(0*).*", "\1",
max(mat, na.rm = T))) + 1))
}
df.col <- data.frame(group = colnames(mat))
rownames(df.col) <- colnames(mat)
df.row <- data.frame(group = rownames(mat))
rownames(df.row) <- rownames(mat)
col_annotation <- HeatmapAnnotation(df = df.col, col = list(group = color.use.col),
which = "column", show_legend = FALSE, show_annotation_name = FALSE,
simple_anno_size = grid::unit(0.2, "cm"))
row_annotation <- HeatmapAnnotation(df = df.row, col = list(group = color.use.row),
which = "row", show_legend = FALSE, show_annotation_name = FALSE,
simple_anno_size = grid::unit(0.2, "cm"))
ha1 = rowAnnotation(Strength = anno_barplot(rowSums(abs(mat)),
border = FALSE, gp = gpar(fill = color.use.row, col = color.use.row)),
show_annotation_name = FALSE)
ha2 = HeatmapAnnotation(Strength = anno_barplot(colSums(abs(mat)),
border = FALSE, gp = gpar(fill = color.use.col, col = color.use.col)),
show_annotation_name = FALSE)
if (sum(abs(mat) > 0) == 1) {
color.heatmap.use = c("white", color.heatmap.use)
}
else {
mat[mat == 0] <- NA
}
ht1 = Heatmap(mat, col = color.heatmap.use, na_col = "white",
name = legend.name, bottom_annotation = col_annotation,
left_annotation = row_annotation, top_annotation = ha2,
right_annotation = ha1, cluster_rows = cluster.rows,
cluster_columns = cluster.rows, row_names_side = "left",
row_names_rot = 0, row_names_gp = gpar(fontsize = font.size),
column_names_gp = gpar(fontsize = font.size), column_title = title.name,
column_title_gp = gpar(fontsize = font.size.title),
column_names_rot = 90, row_title = "Sources (Sender)",
row_title_gp = gpar(fontsize = font.size.title), row_title_rot = 90,
heatmap_legend_param = list(title_gp = gpar(fontsize = font.size,
fontface = "plain"), title_position = "leftcenter-rot",
border = NA, legend_height = unit(20, "mm"), labels_gp = gpar(fontsize = font.size),
grid_width = unit(2, "mm")))
return(ht1)
}
environment(netVisual_heatmapCustom) <- asNamespace('CellChat')
I then try running this and it gives the error Error in grDevices::col2rgb(colors) : invalid color name ‘Reds’.
p1 <- netVisual_heatmapCustom(cellchat, comparison = c(1,2), font.size=3, font.size.title=4)
p2 <- netVisual_heatmapCustom(cellchat, comparison = c(1,2), measure = "weight",font.size=3,font.size.title=4)
p <- p1 + p2
pdf(file=paste(exDir, "/",today,"heatmap.pdf",sep=""), width=5.25, height=2.75)
plot(p)
dev.off()
Even when I create the custom function without changing anything in the source code the error persists. Suggestions for how to fix would be appreciated. If I check whether “Reds” is recognized outside of this function, it works.
grDevices::colorRampPalette(RColorBrewer::brewer.pal(n = 9, name = "Reds"))(100)
[1] "#FFF5F0" "#FEF3ED" "#FEF1EB" "#FEEFE8" "#FEEEE6" "#FEECE3" "#FEEAE1"
[8] "#FEE9DF" "#FEE7DC" "#FEE5DA" "#FEE4D7" "#FEE2D5" "#FEE0D2" "#FDDECF"
[15] "#FDDBCB" "#FDD8C7" "#FDD5C3" "#FDD2BF" "#FDCFBB" "#FCCCB7" "#FCC9B3"
[22] "#FCC6AF" "#FCC3AB" "#FCC0A7" "#FCBDA3" "#FCBAA0" "#FCB69C" "#FCB398"
[29] "#FCB094" "#FCAC90" "#FCA98D" "#FCA689" "#FCA285" "#FC9F81" "#FC9C7D"
[36] "#FC997A" "#FC9576" "#FC9272" "#FB8F6F" "#FB8B6B" "#FB8868" "#FB8565"
[43] "#FB8262" "#FB7F5F" "#FB7B5B" "#FB7858" "#FB7555" "#FB7252" "#FB6E4E"
[50] "#FB6B4B" "#FA6848" "#F96446" "#F86043" "#F75C41" "#F6583F" "#F5553C"
[57] "#F4513A" "#F34D37" "#F24935" "#F14532" "#F04230" "#EF3E2E" "#EE3A2B"
[64] "#EB372A" "#E83429" "#E53228" "#E32F26" "#E02C25" "#DD2924" "#DA2623"
[71] "#D72422" "#D42120" "#D11E1F" "#CE1B1E" "#CB181D" "#C8171C" "#C5161B"
[78] "#C2161B" "#BF151A" "#BC1419" "#B91319" "#B61318" "#B31217" "#B01117"
[85] "#AD1016" "#A91016" "#A60F15" "#A30E14" "#9E0D14" "#990C13" "#940A12"
[92] "#8F0912" "#8A0811" "#850710" "#800610" "#7B040F" "#76030E" "#71020E"
[99] "#6C010D" "#67000D"
Session info is below.
> sessionInfo()
R version 4.3.1 (2023-06-16)
Platform: x86_64-conda-linux-gnu (64-bit)
Running under: Debian GNU/Linux 10 (buster)
Matrix products: default
BLAS/LAPACK: /mnt/vast/hpc/homes/omr2109/miniconda3/envs/ORpy/lib/libopenblasp-r0.3.21.so; LAPACK version 3.9.0
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
time zone: America/New_York
tzcode source: system (glibc)
attached base packages:
[1] stats4 stats graphics grDevices utils datasets methods
[8] base
other attached packages:
[1] circlize_0.4.16 NMF_0.27
[3] cluster_2.1.6 rngtools_1.5.2
[5] registry_0.5-1 ggalluvial_0.12.5
[7] reticulate_1.34.0 CellChat_1.6.1
[9] igraph_2.0.3 SeuratWrappers_0.3.5
[11] monocle3_1.3.7 SingleCellExperiment_1.24.0
[13] clustree_0.5.1 ggraph_2.2.1
[15] rcartocolor_2.1.1 presto_1.0.0
[17] data.table_1.15.4 Rcpp_1.0.13
[19] cowplot_1.1.3 viridis_0.6.4
[21] viridisLite_0.4.2 RColorBrewer_1.1-3
[23] clusterProfiler_4.10.1 org.Hs.eg.db_3.18.0
[25] AnnotationDbi_1.64.1 EnhancedVolcano_1.20.0
[27] ggrepel_0.9.4 DESeq2_1.42.1
[29] SummarizedExperiment_1.32.0 Biobase_2.62.0
[31] MatrixGenerics_1.14.0 matrixStats_1.0.0
[33] GenomicRanges_1.54.1 GenomeInfoDb_1.38.1
[35] IRanges_2.36.0 S4Vectors_0.40.2
[37] BiocGenerics_0.48.1 lme4_1.1-35.5
[39] Matrix_1.7-0 lubridate_1.9.3
[41] forcats_1.0.0 stringr_1.5.1
[43] purrr_1.0.2 readr_2.1.5
[45] tidyr_1.3.1 tibble_3.2.1
[47] tidyverse_2.0.0 dplyr_1.1.4
[49] patchwork_1.2.0 Seurat_5.1.0
[51] SeuratObject_5.0.2 sp_2.1-4
[53] scRepertoire_1.12.0 ggplot2_3.5.1
loaded via a namespace (and not attached):
[1] R.methodsS3_1.8.2 goftest_1.2-3 Biostrings_2.70.3
[4] vctrs_0.6.5 spatstat.random_3.3-1 digest_0.6.36
[7] png_0.1-8 shape_1.4.6.1 deldir_2.0-4
[10] parallelly_1.37.1 permute_0.9-7 MASS_7.3-60
[13] reshape2_1.4.4 httpuv_1.6.12 foreach_1.5.2
[16] qvalue_2.34.0 withr_3.0.0 ggfun_0.1.5
[19] ggpubr_0.6.0 survival_3.7-0 memoise_2.0.1
[22] gson_0.1.0 systemfonts_1.1.0 tidytree_0.4.6
[25] zoo_1.8-12 GlobalOptions_0.1.2 pbapply_1.7-2
[28] R.oo_1.26.0 KEGGREST_1.42.0 promises_1.3.0
[31] evmix_2.12 httr_1.4.7 rstatix_0.7.2
[34] globals_0.16.3 fitdistrplus_1.2-1 miniUI_0.1.1.1
[37] generics_0.1.3 DOSE_3.28.2 zlibbioc_1.48.0
[40] polyclip_1.10-7 GenomeInfoDbData_1.2.11 SparseArray_1.2.2
[43] xtable_1.8-4 doParallel_1.0.17 S4Arrays_1.2.0
[46] hms_1.1.3 irlba_2.3.5.1 colorspace_2.1-0
[49] ggnetwork_0.5.13 ROCR_1.0-11 spatstat.data_3.1-2
[52] magrittr_2.0.3 lmtest_0.9-40 later_1.3.2
[55] ggtree_3.10.1 lattice_0.22-6 spatstat.geom_3.3-2
[58] future.apply_1.11.2 SparseM_1.84-2 scattermore_1.2
[61] shadowtext_0.1.4 RcppAnnoy_0.0.21 pillar_1.9.0
[64] nlme_3.1-165 sna_2.7-2 iterators_1.0.14
[67] gridBase_0.4-7 compiler_4.3.1 RSpectra_0.16-2
[70] stringi_1.8.4 tensor_1.5 minqa_1.2.6
[73] plyr_1.8.9 crayon_1.5.3 abind_1.4-5
[76] gridGraphics_0.5-1 powerTCR_1.22.0 locfit_1.5-9.10
[79] graphlayouts_1.1.1 bit_4.0.5 fastmatch_1.1-4
[82] codetools_0.2-20 GetoptLong_1.0.5 plotly_4.10.2
[85] mime_0.12 splines_4.3.1 fastDummies_1.7.3
[88] HDO.db_0.99.1 blob_1.2.4 utf8_1.2.4
[91] clue_0.3-65 fs_1.6.4 listenv_0.9.1
[94] evd_2.3-7 gsl_2.1-8 ggsignif_0.6.4
[97] ggplotify_0.1.2 svglite_2.1.3 tzdb_0.4.0
[100] network_1.18.2 tweenr_2.0.3 pkgconfig_2.0.3
[103] tools_4.3.1 cachem_1.1.0 RSQLite_2.3.7
[106] DBI_1.2.3 fastmap_1.2.0 scales_1.3.0
[109] grid_4.3.1 ica_1.0-3 broom_1.0.6
[112] coda_0.19-4.1 FNN_1.1.3.2 BiocManager_1.30.23
[115] dotCall64_1.1-1 carData_3.0-5 RANN_2.6.1
[118] farver_2.1.2 tidygraph_1.3.1 scatterpie_0.2.3
[121] mgcv_1.9-1 VGAM_1.1-11 cli_3.6.3
[124] leiden_0.4.3.1 lifecycle_1.0.4 uwot_0.1.16
[127] backports_1.5.0 BiocParallel_1.36.0 timechange_0.3.0
[130] gtable_0.3.5 rjson_0.2.21 ggridges_0.5.6
[133] progressr_0.14.0 cubature_2.1.1 parallel_4.3.1
[136] ape_5.8 jsonlite_1.8.8 RcppHNSW_0.5.0
[139] bitops_1.0-7 bit64_4.0.5 Rtsne_0.16
[142] yulab.utils_0.1.4 vegan_2.6-6.1 spatstat.utils_3.0-5
[145] BiocNeighbors_1.20.0 GOSemSim_2.28.1 spatstat.univar_3.0-0
[148] R.utils_2.12.3 truncdist_1.0-2 lazyeval_0.2.2
[151] shiny_1.8.1.1 htmltools_0.5.7 enrichplot_1.22.0
[154] GO.db_3.18.0 sctransform_0.4.1 rappdirs_0.3.3
[157] glue_1.7.0 spam_2.10-0 XVector_0.42.0
[160] RCurl_1.98-1.12 treeio_1.26.0 gridExtra_2.3
[163] boot_1.3-30 R6_2.5.1 labeling_0.4.3
[166] stringdist_0.9.12 aplot_0.2.3 statnet.common_4.9.0
[169] nloptr_2.0.3 DelayedArray_0.28.0 tidyselect_1.2.1
[172] ggforce_0.4.2 car_3.1-2 future_1.33.2
[175] rsvd_1.0.5 munsell_0.5.1 KernSmooth_2.23-24
[178] htmlwidgets_1.6.4 fgsea_1.28.0 ComplexHeatmap_2.18.0
[181] rlang_1.1.4 spatstat.sparse_3.1-0 spatstat.explore_3.3-1
[184] remotes_2.5.0 Cairo_1.6-1 fansi_1.0.6
Olivia is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.