biopipen 0.32.1__py3-none-any.whl → 0.33.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of biopipen might be problematic. Click here for more details.

Files changed (134) hide show
  1. biopipen/__init__.py +1 -1
  2. biopipen/core/config.toml +6 -0
  3. biopipen/core/filters.py +77 -26
  4. biopipen/core/testing.py +6 -1
  5. biopipen/ns/bam.py +39 -0
  6. biopipen/ns/cellranger.py +5 -0
  7. biopipen/ns/cellranger_pipeline.py +2 -2
  8. biopipen/ns/cnvkit_pipeline.py +4 -1
  9. biopipen/ns/delim.py +33 -27
  10. biopipen/ns/protein.py +99 -0
  11. biopipen/ns/scrna.py +411 -250
  12. biopipen/ns/snp.py +16 -3
  13. biopipen/ns/tcr.py +125 -1
  14. biopipen/ns/vcf.py +34 -0
  15. biopipen/ns/web.py +5 -1
  16. biopipen/reports/scrna/SeuratClusterStats.svelte +1 -1
  17. biopipen/reports/scrna/SeuratMap2Ref.svelte +15 -2
  18. biopipen/reports/tcr/ClonalStats.svelte +15 -0
  19. biopipen/reports/utils/misc.liq +22 -7
  20. biopipen/scripts/bam/BamMerge.py +2 -2
  21. biopipen/scripts/bam/BamSampling.py +4 -4
  22. biopipen/scripts/bam/BamSort.py +141 -0
  23. biopipen/scripts/bam/BamSplitChroms.py +10 -10
  24. biopipen/scripts/bam/BamSubsetByBed.py +3 -3
  25. biopipen/scripts/bam/CNVpytor.py +10 -10
  26. biopipen/scripts/bam/ControlFREEC.py +11 -11
  27. biopipen/scripts/bed/Bed2Vcf.py +5 -5
  28. biopipen/scripts/bed/BedConsensus.py +5 -5
  29. biopipen/scripts/bed/BedLiftOver.sh +6 -4
  30. biopipen/scripts/bed/BedtoolsIntersect.py +4 -4
  31. biopipen/scripts/bed/BedtoolsMakeWindows.py +3 -3
  32. biopipen/scripts/bed/BedtoolsMerge.py +4 -4
  33. biopipen/scripts/cellranger/CellRangerCount.py +20 -9
  34. biopipen/scripts/cellranger/CellRangerSummary.R +20 -29
  35. biopipen/scripts/cellranger/CellRangerVdj.py +8 -8
  36. biopipen/scripts/cnvkit/CNVkitAccess.py +6 -6
  37. biopipen/scripts/cnvkit/CNVkitAutobin.py +25 -18
  38. biopipen/scripts/cnvkit/CNVkitBatch.py +5 -5
  39. biopipen/scripts/cnvkit/CNVkitCall.py +3 -3
  40. biopipen/scripts/cnvkit/CNVkitCoverage.py +2 -2
  41. biopipen/scripts/cnvkit/CNVkitDiagram.py +5 -5
  42. biopipen/scripts/cnvkit/CNVkitFix.py +3 -3
  43. biopipen/scripts/cnvkit/CNVkitGuessBaits.py +9 -5
  44. biopipen/scripts/cnvkit/CNVkitHeatmap.py +4 -4
  45. biopipen/scripts/cnvkit/CNVkitReference.py +2 -2
  46. biopipen/scripts/cnvkit/CNVkitScatter.py +5 -5
  47. biopipen/scripts/cnvkit/CNVkitSegment.py +5 -5
  48. biopipen/scripts/cnvkit/guess_baits.py +166 -93
  49. biopipen/scripts/delim/SampleInfo.R +85 -139
  50. biopipen/scripts/misc/Config2File.py +2 -2
  51. biopipen/scripts/misc/Str2File.py +2 -2
  52. biopipen/scripts/protein/MMCIF2PDB.py +33 -0
  53. biopipen/scripts/protein/PDB2Fasta.py +60 -0
  54. biopipen/scripts/protein/Prodigy.py +4 -4
  55. biopipen/scripts/protein/RMSD.py +178 -0
  56. biopipen/scripts/regulatory/MotifScan.py +8 -8
  57. biopipen/scripts/scrna/CellCellCommunication.py +59 -22
  58. biopipen/scripts/scrna/CellsDistribution.R +31 -6
  59. biopipen/scripts/scrna/MarkersFinder.R +272 -602
  60. biopipen/scripts/scrna/MetaMarkers.R +16 -7
  61. biopipen/scripts/scrna/RadarPlots.R +75 -35
  62. biopipen/scripts/scrna/SCP-plot.R +15202 -0
  63. biopipen/scripts/scrna/ScVelo.py +0 -0
  64. biopipen/scripts/scrna/SeuratClusterStats-clustree.R +23 -25
  65. biopipen/scripts/scrna/SeuratClusterStats-dimplots.R +26 -47
  66. biopipen/scripts/scrna/SeuratClusterStats-features.R +85 -385
  67. biopipen/scripts/scrna/SeuratClusterStats-ngenes.R +33 -13
  68. biopipen/scripts/scrna/SeuratClusterStats-stats.R +45 -228
  69. biopipen/scripts/scrna/SeuratClusterStats.R +13 -19
  70. biopipen/scripts/scrna/SeuratMap2Ref.R +16 -6
  71. biopipen/scripts/scrna/SeuratPreparing.R +138 -81
  72. biopipen/scripts/scrna/SlingShot.R +71 -0
  73. biopipen/scripts/scrna/TopExpressingGenes.R +9 -7
  74. biopipen/scripts/scrna/celltypist-wrapper.py +7 -6
  75. biopipen/scripts/snp/Plink2GTMat.py +26 -11
  76. biopipen/scripts/snp/PlinkFilter.py +7 -7
  77. biopipen/scripts/snp/PlinkFromVcf.py +8 -5
  78. biopipen/scripts/snp/PlinkSimulation.py +4 -4
  79. biopipen/scripts/snp/PlinkUpdateName.py +4 -4
  80. biopipen/scripts/stats/ChowTest.R +48 -22
  81. biopipen/scripts/tcgamaf/Maf2Vcf.py +2 -2
  82. biopipen/scripts/tcgamaf/MafAddChr.py +2 -2
  83. biopipen/scripts/tcr/CDR3AAPhyschem.R +12 -2
  84. biopipen/scripts/tcr/ClonalStats.R +484 -0
  85. biopipen/scripts/tcr/CloneResidency.R +23 -5
  86. biopipen/scripts/tcr/Immunarch-basic.R +8 -1
  87. biopipen/scripts/tcr/Immunarch-clonality.R +5 -0
  88. biopipen/scripts/tcr/Immunarch-diversity.R +25 -4
  89. biopipen/scripts/tcr/Immunarch-geneusage.R +15 -1
  90. biopipen/scripts/tcr/Immunarch-kmer.R +14 -1
  91. biopipen/scripts/tcr/Immunarch-overlap.R +15 -1
  92. biopipen/scripts/tcr/Immunarch-spectratyping.R +10 -1
  93. biopipen/scripts/tcr/Immunarch-tracking.R +6 -0
  94. biopipen/scripts/tcr/Immunarch-vjjunc.R +33 -0
  95. biopipen/scripts/tcr/ScRepLoading.R +127 -0
  96. biopipen/scripts/tcr/TCRClusterStats.R +24 -7
  97. biopipen/scripts/tcr/TCRDock.py +10 -6
  98. biopipen/scripts/tcr/TESSA.R +6 -1
  99. biopipen/scripts/tcr/vdjtools-patch.sh +1 -1
  100. biopipen/scripts/vcf/BcftoolsAnnotate.py +8 -8
  101. biopipen/scripts/vcf/BcftoolsFilter.py +3 -3
  102. biopipen/scripts/vcf/BcftoolsMerge.py +31 -0
  103. biopipen/scripts/vcf/BcftoolsSort.py +4 -4
  104. biopipen/scripts/vcf/BcftoolsView.py +5 -5
  105. biopipen/scripts/vcf/Vcf2Bed.py +2 -2
  106. biopipen/scripts/vcf/VcfAnno.py +11 -11
  107. biopipen/scripts/vcf/VcfDownSample.sh +22 -10
  108. biopipen/scripts/vcf/VcfFilter.py +5 -5
  109. biopipen/scripts/vcf/VcfFix.py +7 -7
  110. biopipen/scripts/vcf/VcfFix_utils.py +12 -3
  111. biopipen/scripts/vcf/VcfIndex.py +3 -3
  112. biopipen/scripts/vcf/VcfIntersect.py +3 -3
  113. biopipen/scripts/vcf/VcfLiftOver.sh +5 -0
  114. biopipen/scripts/vcf/VcfSplitSamples.py +4 -4
  115. biopipen/scripts/vcf/bcftools_utils.py +3 -3
  116. biopipen/scripts/web/Download.py +8 -4
  117. biopipen/scripts/web/DownloadList.py +5 -5
  118. biopipen/scripts/web/GCloudStorageDownloadBucket.py +5 -5
  119. biopipen/scripts/web/GCloudStorageDownloadFile.py +3 -3
  120. biopipen/scripts/web/gcloud_common.py +1 -1
  121. biopipen/utils/gsea.R +96 -42
  122. biopipen/utils/misc.R +205 -7
  123. biopipen/utils/misc.py +17 -8
  124. biopipen/utils/plot.R +53 -17
  125. biopipen/utils/reference.py +11 -11
  126. biopipen/utils/repr.R +146 -0
  127. biopipen/utils/vcf.py +1 -1
  128. {biopipen-0.32.1.dist-info → biopipen-0.33.0.dist-info}/METADATA +9 -9
  129. {biopipen-0.32.1.dist-info → biopipen-0.33.0.dist-info}/RECORD +131 -122
  130. {biopipen-0.32.1.dist-info → biopipen-0.33.0.dist-info}/WHEEL +1 -1
  131. biopipen/scripts/scrna/SeuratClusterStats-hists.R +0 -139
  132. biopipen/scripts/scrna/SeuratPreparing-common.R +0 -452
  133. biopipen/scripts/scrna/SeuratPreparing-doublet_detection.R +0 -201
  134. {biopipen-0.32.1.dist-info → biopipen-0.33.0.dist-info}/entry_points.txt +0 -0
@@ -2,15 +2,35 @@
2
2
 
3
3
  # features_defaults = {{envs.features_defaults | r: todot="-"}}
4
4
  # features = {{envs.features | r: todot="-", skip=1}}
5
- log_info("features:")
5
+ log$info("features:")
6
6
 
7
7
  odir = file.path(outdir, "features")
8
8
  dir.create(odir, recursive=TRUE, showWarnings=FALSE)
9
9
 
10
- .get_features = function(features) {
10
+ # highly variable features
11
+ hvf <- NULL
12
+
13
+ .get_features = function(features, object) {
11
14
  if (is.null(features)) { features = 20 }
12
15
  if (is.numeric(features)) {
13
- return (VariableFeatures(srtobj)[1:features])
16
+ if (!is.null(hvf)) {
17
+ return(hvf[1:features])
18
+ }
19
+ vf <- VariableFeatures(object)
20
+ if (length(vf) == 0) {
21
+ if (DefaultAssay(object) == "SCT") {
22
+ # Still use RNA assay to find variable features
23
+ # See
24
+ # https://github.com/satijalab/seurat/issues/6064
25
+ # https://github.com/satijalab/seurat/issues/8238
26
+ # https://github.com/satijalab/seurat/issues/5761
27
+ vf <- FindVariableFeatures(object, nfeatures = features, assay = "RNA")
28
+ } else {
29
+ vf <- FindVariableFeatures(object, nfeatures = features)
30
+ }
31
+ }
32
+ hvf <<- vf
33
+ return(hvf[1:features])
14
34
  }
15
35
  if (is.character(features) && length(features) > 1) {
16
36
  return (features)
@@ -36,412 +56,92 @@ dir.create(odir, recursive=TRUE, showWarnings=FALSE)
36
56
  return (trimws(unlist(strsplit(features, ","))))
37
57
  }
38
58
 
39
- do_one_features = function(name) {
40
- log_info("- Case: {name}")
59
+ do_one_features <- function(name) {
60
+ log$info("- Case: {name}")
41
61
 
42
- case = list_update(features_defaults, features[[name]])
43
- case$devpars = list_update(features_defaults$devpars, features[[name]]$devpars)
44
- excluded_args = c(
45
- "section",
46
- "devpars",
47
- "subset",
48
- "plus",
49
- "ident",
50
- "cluster_orderby",
51
- "kind"
52
- )
62
+ case <- list_update(features_defaults, features[[name]])
63
+ case <- extract_vars(
64
+ case,
65
+ "devpars", "more_formats", "save_code", "save_data", "order_by",
66
+ "subset", "features", "descr")
53
67
 
54
- if (is.character(case$subset)) {
55
- case$object = srtobj %>% filter(!!rlang::parse_expr(case$subset))
68
+ if (!is.null(subset)) {
69
+ case$object <- srtobj %>% filter(!!parse_expr(subset))
56
70
  } else {
57
- case$object = srtobj
71
+ case$object <- srtobj
58
72
  }
59
73
 
60
- if (!is.null(case$ident)) {
61
- case$object = case$object %>% filter(!is.na(!!sym(case$ident)))
62
- Idents(case$object) = case$ident
63
- }
64
- cluster_order_val <- NULL
65
- if (!is.null(case$cluster_orderby) && length(case$cluster_orderby) > 1) {
66
- case$object@meta.data[[case$ident]] = factor(Idents(case$object), levels = case$cluster_orderby)
67
- Idents(case$object) = case$ident
68
- } else if (!is.null(case$cluster_orderby)) {
69
- cluster_order_df = case$object@meta.data %>%
70
- group_by(!!sym(case$ident)) %>%
71
- summarise(!!sym(case$cluster_orderby) := !!parse_expr(case$cluster_orderby)) %>%
72
- arrange(!!sym(case$cluster_orderby))
73
- cluster_order_val = cluster_order_df[[case$cluster_orderby]]
74
- clusters = cluster_order_df[[case$ident]] %>% as.character() %>% unique()
75
- case$object@meta.data[[case$ident]] = factor(Idents(case$object), levels = clusters)
76
- Idents(case$object) = case$ident
77
- }
78
- n_uidents = length(unique(Idents(case$object)))
79
- max_nchar_idents = max(nchar(unique(as.character(Idents(case$object)))))
74
+ if (exists("order_by") && !is.null(order_by)) {
75
+ if (length(order_by) < 2) {
76
+ clusters <- case$object@meta.data %>%
77
+ group_by(!!sym(case$ident)) %>%
78
+ arrange(!!parse_expr(order_by)) %>%
79
+ ungroup() %>%
80
+ pull(!!sym(case$ident)) %>%
81
+ unique()
80
82
 
81
- fn = NULL
82
- default_devpars = NULL
83
- if (case$kind %in% c("ridge", "ridgeplot")) {
84
- case$kind = "ridge"
85
- if (is.null(case$cols)) {
86
- case$cols = pal_biopipen()(n_uidents)
87
- }
88
- excluded_args = c(excluded_args, "split.by", "reduction")
89
- fn = RidgePlot
90
- default_devpars = function(features, ncol) {
91
- if (is.null(ncol)) { ncol = 1 }
92
- list(
93
- width = 400 * ncol,
94
- height = ceiling(length(features) / ncol) * ifelse(n_uidents < 10, 300, 400),
95
- res = 100
96
- )
97
- }
98
- } else if (case$kind %in% c("vln", "violin", "vlnplot", "violinplot")) {
99
- case$kind = "violin"
100
- if (is.null(case$cols)) { case$cols = pal_biopipen()(n_uidents) }
101
- if (is.null(case$pt.size)) { case$pt.size = 0 }
102
-
103
- excluded_args = c(excluded_args, "reduction")
104
- fn = VlnPlot
105
- default_devpars = function(features, ncol) {
106
- if (is.null(ncol)) { ncol = 1 }
107
- list(
108
- width = 400 * ncol,
109
- height = ceiling(length(features) / ncol) * (max_nchar_idents * .1 + 275),
110
- res = 100
111
- )
112
- }
113
- } else if (case$kind %in% c("feature", "featureplot")) {
114
- case$kind = "feature"
115
- if (is.null(case$cols)) {
116
- case$cols = c("lightgrey", pal_biopipen()(1))
117
- }
118
- excluded_args = c(excluded_args, "group.by", "assay", "layer")
119
- case$shape.by = case$group.by
120
- if (!is.null(case$ident)) {
121
- key <- paste0("sub_umap_", case$ident)
122
- if (key %in% names(case$object@reductions) && is.null(case$reduction)) {
123
- case$reduction = key
124
- case$object = filter(case$object, !is.na(!!sym(case$ident)))
125
- }
126
- }
127
- fn = FeaturePlot
128
- default_devpars = function(features, ncol) {
129
- if (is.null(ncol)) { ncol = 1 }
130
- list(
131
- width = 400 * ncol,
132
- height = ceiling(length(features) / ncol) * 300,
133
- res = 100
134
- )
135
- }
136
- } else if (case$kind %in% c("dot", "dotplot")) {
137
- case$kind = "dot"
138
- if (is.null(case$cols)) {
139
- case$cols = c("lightgrey", pal_biopipen()(1))
140
- }
141
- if (is.null(case$plus)) {
142
- case$plus = 'theme_prism(axis_text_angle=90)'
143
- }
144
- excluded_args = c(excluded_args, "layer", "ncol", "reduction")
145
- fn = DotPlot
146
- default_devpars = function(features, ncol) {
147
- list(
148
- height = max(n_uidents * 80 + 150, 420),
149
- width = length(features) * 50 + 150,
150
- res = 100
151
- )
152
- }
153
- } else if ("heatmap" == case$kind) {
154
- case$kind = "heatmap"
155
- case = list_update(
156
- list(
157
- group.colors = pal_biopipen()(n_uidents),
158
- size = 3.5,
159
- group.bar.height = 0.01
160
- ),
161
- case
162
- )
163
- if (is.null(case$plus)) {
164
- case$plus = 'scale_fill_gradient2(
165
- low = "lightblue",
166
- high = "darkblue",
167
- na.value = "white"
168
- )'
169
- }
170
- excluded_args = c(excluded_args, "group.by", "split.by", "downsample", "ncol", "reduction", "layer")
171
- fn = DoHeatmap
172
- default_devpars = function(features, ncol) {
173
- list(
174
- width = n_uidents * 60 + 150,
175
- height = length(features) * 40 + 150,
176
- res = 100
177
- )
178
- }
179
- } else if (case$kind == "avgheatmap") {
180
- case$kind = "avgheatmap"
181
- excluded_args = c(
182
- excluded_args,
183
- "group.by", "split.by", "downsample", "ncol", "reduction", "layer",
184
- "assay", "object"
185
- )
186
- default_devpars = function(features, ncol) {
187
- list(
188
- width = n_uidents * 30 + 350,
189
- height = length(features) * 15 + 150,
190
- res = 100
191
- )
192
- }
193
- } else if (case$kind %in% c("bar", "barplot")) {
194
- case$kind = "bar"
195
- if (is.null(case$features) || length(case$features) == 0) {
196
- stop("No features is specified for barplot")
197
- }
198
- if (length(case$features) > 1) {
199
- stop("Only one feature is allowed for barplot")
200
- }
201
- excluded_args = c(excluded_args, "reduction")
202
- default_devpars = function(features, ncol) {
203
- if (is.null(ncol)) { ncol = 1 }
204
- list(
205
- height = 500 * ncol,
206
- width = n_uidents * 60 + 150,
207
- res = 100
208
- )
83
+ case$object@meta.data[[case$ident]] <- factor(case$object@meta.data[[case$ident]], levels = clusters)
84
+ } else {
85
+ case$object@meta.data[[case$ident]] <- fct_relevel(case$object@meta.data[[case$ident]], order_by)
209
86
  }
210
- } else if ("table" == case$kind) {
211
- case$kind = "table"
212
- excluded_args = c(excluded_args, "group.by", "split.by", "assay", "reduction")
213
- case$assays = case$assay
214
- fn = AverageExpression
215
- if (is.null(case$layer)) { case$layer = "data" }
216
- } else {
217
- stop(paste0("Unknown kind of plot: ", case$kind))
218
87
  }
219
88
 
220
- for (arg in excluded_args) {
221
- assign(arg, case[[arg]])
222
- case[[arg]] = NULL
89
+ info <- case_info(name, odir, is_dir = FALSE, create = TRUE)
90
+ case$features <- .get_features(features, case$object)
91
+ p <- do_call(gglogger::register(FeatureStatPlot), case)
92
+ save_plot(p, info$prefix, devpars, formats = c("png", more_formats))
93
+ if (save_code) {
94
+ save_plotcode(p, info$prefix,
95
+ setup = c("library(scplotter)", "load('data.RData')", "invisible(list2env('case'))"),
96
+ "case",
97
+ auto_data_setup = FALSE)
223
98
  }
224
-
225
- if (kind == "bar") {
226
- figfile <- file.path(odir, paste0(slugify(name), ".bar.png"))
227
- genes <- rownames(GetAssayData(case$object))
228
- genes <- genes[sapply(genes, function(x) grepl(x, case$features))]
229
- if (length(genes) == 0) {
230
- p <- case$object@meta.data %>%
231
- group_by(Idents = Idents(case$object)) %>%
232
- summarise(!!sym(name) := !!parse_expr(case$features)) %>%
233
- ggplot(aes(x = Idents, y = !!sym(name)))
234
- } else {
235
- p <- case$object@meta.data %>%
236
- bind_cols(FetchData(case$object, vars = genes, layer = case$layer, cells = rownames(case$object@meta.data))) %>%
237
- group_by(Idents = Idents(case$object)) %>%
238
- summarise(!!sym(name) := !!parse_expr(case$features)) %>%
239
- ggplot(aes(x = Idents, y = !!sym(name)))
240
- }
241
-
242
- if (!is.null(case$group.by)) {
243
- p <- p + geom_bar(aes(fill = !!sym(case$group.by)), stat = "identity", position = "dodge")
244
- } else {
245
- p <- p + geom_bar(aes(fill = Idents), stat = "identity")
246
- }
247
-
248
- p <- p +
249
- scale_fill_biopipen() +
250
- theme_prism() +
251
- theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
252
- labs(x = "Idents", y = name)
253
-
254
- if (!is.null(case$split.by)) {
255
- p <- p + facet_wrap(~ !!sym(case$split.by), ncol = case$ncol)
256
- } else {
257
- case$ncol = 1
258
- }
259
-
260
- if (!is.null(case$plus)) {
261
- p <- p + eval(parse(text = case$plus))
262
- }
263
- devpars = list_update(default_devpars(NULL, case$ncol), devpars)
264
- png(figfile, res = devpars$res, width = devpars$width, height = devpars$height)
265
- print(p)
266
- dev.off()
267
-
268
- add_report(
99
+ if (exists("descr") && !is.null(descr)) {
100
+ reporter$add2(
269
101
  list(
270
102
  kind = "descr",
271
- content = paste0(kind, "plots for selected features <code>", case$features, "</code>, by ", ident)
272
- ),
273
- list(
274
- kind = "image",
275
- src = figfile
103
+ content = descr
276
104
  ),
277
- h1 = ifelse(is.null(section), name, section),
278
- h2 = ifelse(is.null(section), "#", name)
105
+ hs = c(info$section, info$name)
279
106
  )
280
-
281
- return(NULL)
282
107
  }
283
108
 
284
- case$features = .get_features(case$features)
285
- if (kind == "avgheatmap") {
286
- figfile <- file.path(odir, paste0(slugify(name), ".avgheatmap.png"))
287
- assay <- assay %||% DefaultAssay(object)
288
- layer <- layer %||% ifelse("scale.data" %in% Layers(object, assay = assay), "scale.data", "data")
289
-
290
- case_features <- case$features
291
- case$features <- NULL
292
- meta_feats <- intersect(case_features, colnames(object@meta.data))
293
- expr_feats <- setdiff(case_features, meta_feats)
294
- exprs <- NULL
295
- if (length(meta_feats) > 0) {
296
- exprs <- object@meta.data %>% select(all_of(c(meta_feats, ident))) %>%
297
- group_by(!!sym(ident)) %>%
298
- summarise(across(everything(), ~ mean(.x, na.rm = TRUE))) %>%
299
- column_to_rownames(ident) %>%
300
- t()
109
+ if (save_data) {
110
+ if (!inherits(p$data, "data.frame") && !inherits(p$data, "matrix")) {
111
+ stop("'save_data = TRUE' is not supported for plot_type: ", case$plot_type)
301
112
  }
302
- if (length(expr_feats)) {
303
- exprs_tmp <- AverageExpression(
304
- object,
305
- assays = assay,
306
- layer = layer,
307
- features = expr_feats,
308
- group.by = ident)[[assay]]
309
- exprs <- bind_rows(exprs, as.data.frame(exprs_tmp))
310
- }
311
-
312
- ha <- NULL
313
- extra_height <- 0
314
- extra_width <- 0 # legend
315
- if (!is.null(cluster_order_val)) {
316
- ha <- list()
317
- ha[[cluster_orderby]] <- cluster_order_val
318
- if (is.numeric(cluster_order_val)) {
319
- col_fun <- colorRamp2(
320
- c(min(cluster_order_val), max(cluster_order_val)),
321
- c("lightyellow", "red"))
322
- ha$col <- list()
323
- ha$col[[cluster_orderby]] <- col_fun
324
- }
325
- ha <- do_call(HeatmapAnnotation, ha)
326
- extra_height <- 40
327
- extra_width <- 120
328
- }
329
-
330
- col_fun <- colorRamp2(
331
- c(min(exprs, na.rm = T), 0, max(exprs, na.rm = T)),
332
- c("lightblue", "white", "darkred"))
333
-
334
- case <- list_update(list(
335
- matrix = as.matrix(exprs),
336
- name = "Average expression",
337
- col = col_fun,
338
- na_col = "white",
339
- row_names_side = "right",
340
- cluster_rows = FALSE,
341
- cluster_columns = FALSE,
342
- rect_gp = gpar(col = "gray", lwd = 1),
343
- row_names_max_width = max_text_width(rownames(exprs)),
344
- top_annotation = ha
345
- ), case)
346
- p <- do_call(Heatmap, case)
347
-
348
- def_devpars = default_devpars(case_features, NULL)
349
- def_devpars$width = def_devpars$width + extra_width
350
- def_devpars$height = def_devpars$height + extra_height
351
- devpars = list_update(def_devpars, devpars)
352
- png(figfile, res = devpars$res, width = devpars$width, height = devpars$height)
353
- print(p)
354
- dev.off()
355
-
356
- add_report(
113
+ write.table(p$data, paste0(info$prefix, ".data.txt"), sep="\t", quote=FALSE, row.names=FALSE)
114
+ reporter$add2(
357
115
  list(
358
- kind = "descr",
359
- content = paste0("Average expression values for selected features, by ", ident)
116
+ name = "Plot",
117
+ contents = list(
118
+ reporter$image(
119
+ info$prefix, more_formats, save_code, kind = "image")
120
+ )
360
121
  ),
361
122
  list(
362
- kind = "image",
363
- src = figfile
123
+ name = "Data",
124
+ contents = list(
125
+ list(
126
+ kind = "descr",
127
+ content = "Data used directly for the plot"
128
+ ),
129
+ list(
130
+ kind = "table",
131
+ src = paste0(info$prefix, ".data.txt"),
132
+ data = list(nrows = 100)
133
+ )
134
+ )
364
135
  ),
365
- h1 = ifelse(is.null(section), name, section),
366
- h2 = ifelse(is.null(section), "#", name)
136
+ hs = c(info$section, info$name),
137
+ ui = "tabs"
367
138
  )
368
- return(NULL)
369
- }
370
-
371
- if (!is.null(case$ncol)) {
372
- case$ncol = min(case$ncol, length(case$features))
373
- }
374
-
375
- if (kind == "table") {
376
- expr = do_call(fn, case)[[DefaultAssay(case$object)]] %>%
377
- as.data.frame() %>%
378
- rownames_to_column("Feature") %>%
379
- select(Feature, everything())
380
-
381
- exprfile = file.path(odir, paste0(slugify(name), ".txt"))
382
- write.table(expr, exprfile, sep="\t", quote=FALSE, row.names=FALSE)
383
-
384
- add_report(
385
- list(
386
- kind = "descr",
387
- content = paste0("Table of expression value for selected features, by ", ident)
388
- ),
389
- list(
390
- kind = "table",
391
- src = exprfile
392
- ),
393
- h1 = ifelse(is.null(case$section), name, case$section),
394
- h2 = ifelse(is.null(case$section), "#", name)
139
+ } else {
140
+ reporter$add2(
141
+ reporter$image(info$prefix, more_formats, save_code, kind = "image"),
142
+ hs = c(info$section, info$name)
395
143
  )
396
- return(NULL)
397
- }
398
-
399
- devpars = list_update(default_devpars(case$features, case$ncol), devpars)
400
- if (kind == "heatmap") {
401
- if (!exists("downsample") || is.null(downsample)) {
402
- log_warn(" 'downsample' is not specified for `heatmap`, using `downsample=1000`")
403
- downsample = 1000
404
- }
405
- if (is.numeric(downsample)) {
406
- case$object = base::subset(case$object, downsample = downsample)
407
- } else {
408
- stop(paste0("Unknown downsample method: ", downsample))
409
- }
410
- }
411
- p = do_call(fn, case)
412
- if (!is.null(plus)) {
413
- for (pls in plus) {
414
- p = p + eval(parse(text = pls))
415
- }
416
144
  }
417
- figfile = file.path(odir, paste0(slugify(name), ".", slugify(kind), ".png"))
418
- png(figfile, width=devpars$width, height=devpars$height, res=devpars$res)
419
- tryCatch({
420
- print(p)
421
- }, error = function(e) {
422
- stop(
423
- paste(
424
- paste(names(devpars), collapse=" "),
425
- paste(devpars, collapse=" "),
426
- e,
427
- sep = "\n"
428
- )
429
- )
430
- })
431
- dev.off()
432
-
433
- add_report(
434
- list(
435
- kind = "descr",
436
- content = paste0(kind, "plots for selected features, by ", ident)
437
- ),
438
- list(
439
- kind = "image",
440
- src = figfile
441
- ),
442
- h1 = ifelse(is.null(section), name, section),
443
- h2 = ifelse(is.null(section), "#", name)
444
- )
445
145
  }
446
146
 
447
147
  sapply(names(features), do_one_features)
@@ -2,19 +2,17 @@
2
2
 
3
3
  # ngenes_defaults <- {{envs.ngenes_defaults | r: todot="-"}}
4
4
  # ngenes <- {{envs.ngenes | r: todot="-", skip=1}}
5
- log_info("ngenes:")
5
+ log$info("ngenes:")
6
6
 
7
7
  odir <- file.path(outdir, "ngenes")
8
8
  dir.create(odir, recursive=TRUE, showWarnings=FALSE)
9
9
 
10
10
  do_one_ngenes <- function(name) {
11
- log_info("- Case: {name}")
11
+ log$info("- Case: {name}")
12
12
 
13
13
  case <- list_update(ngenes_defaults, ngenes[[name]])
14
14
  case$devpars <- list_update(ngenes_defaults$devpars, case$devpars)
15
15
 
16
- figfile = file.path(odir, paste0(slugify(name), ".boxplot.png"))
17
-
18
16
  if (!is.null(case$subset)) {
19
17
  sobj <- srtobj %>% filter(!!rlang::parse_expr(case$subset))
20
18
  } else {
@@ -25,31 +23,43 @@ do_one_ngenes <- function(name) {
25
23
  select_cols = c(case$ident, case$group.by, case$split.by, ".nexpr")
26
24
  df_cells = df_cells %>% select(all_of(select_cols))
27
25
 
28
- p = df_cells %>%
26
+ p = df_cells |>
29
27
  ggplot(aes(
30
28
  x=!!sym(case$ident),
31
29
  y=.nexpr,
32
30
  fill=!!sym(ifelse(is.null(case$group.by), case$ident, case$group.by))
33
31
  )) +
34
- geom_violin(position = ifelse(is.null(case$group.by), "identity", "dodge")) +
32
+ geom_violin(alpha = 0.6, position = ifelse(is.null(case$group.by), "identity", "dodge")) +
35
33
  geom_boxplot(
36
34
  position = ifelse(is.null(case$group.by), "identity", "dodge"),
37
35
  width = .1,
38
36
  fill = "white"
39
37
  ) +
40
- theme_prism(axis_text_angle = 90) +
41
- scale_fill_biopipen() +
38
+ plotthis::theme_this() +
39
+ # scale_fill_biopipen() +
42
40
  ylab("Number of genes expressed")
43
41
 
44
42
  if (!is.null(case$split.by)) {
45
43
  p = p + facet_wrap(case$split.by)
46
44
  }
47
45
 
48
- png(figfile, width=case$devpars$width, height=case$devpars$height, res=case$devpars$res)
49
- print(p)
50
- dev.off()
46
+ figprefix = file.path(odir, paste0(slugify(name), ".boxplot"))
47
+
48
+ save_plot(p, figprefix, case$devpars)
49
+ save_plotcode(
50
+ p,
51
+ figprefix,
52
+ c(
53
+ 'library(rlang)',
54
+ 'library(ggplot2)',
55
+ 'library(ggprism)',
56
+ '',
57
+ 'load("data.RData")'
58
+ ),
59
+ "df_cells", "case"
60
+ )
51
61
 
52
- add_report(
62
+ reporter$add(
53
63
  list(
54
64
  kind = "descr",
55
65
  content = paste0(
@@ -62,7 +72,17 @@ do_one_ngenes <- function(name) {
62
72
  )
63
73
  )
64
74
  ),
65
- list(kind = "image", src = figfile),
75
+ list(
76
+ kind = "image",
77
+ src = paste0(figprefix, ".png"),
78
+ download = list(
79
+ paste0(figprefix, ".pdf"),
80
+ list(
81
+ src = paste0(figprefix, ".code.zip"),
82
+ tip = "Download the code to reproduce the plot",
83
+ icon = "Code"
84
+ )
85
+ )),
66
86
  h1 = name
67
87
  )
68
88
  }