biopipen 0.32.3__py3-none-any.whl → 0.33.1__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 (118) hide show
  1. biopipen/__init__.py +1 -1
  2. biopipen/core/config.toml +6 -0
  3. biopipen/core/filters.py +35 -23
  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 +428 -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 +20 -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 +94 -148
  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/LoomTo10X.R +51 -0
  59. biopipen/scripts/scrna/MarkersFinder.R +273 -654
  60. biopipen/scripts/scrna/RadarPlots.R +73 -53
  61. biopipen/scripts/scrna/SCP-plot.R +15202 -0
  62. biopipen/scripts/scrna/ScVelo.py +0 -0
  63. biopipen/scripts/scrna/SeuratClusterStats-clustree.R +23 -31
  64. biopipen/scripts/scrna/SeuratClusterStats-dimplots.R +26 -54
  65. biopipen/scripts/scrna/SeuratClusterStats-features.R +85 -403
  66. biopipen/scripts/scrna/SeuratClusterStats-ngenes.R +32 -17
  67. biopipen/scripts/scrna/SeuratClusterStats-stats.R +45 -239
  68. biopipen/scripts/scrna/SeuratClusterStats.R +13 -19
  69. biopipen/scripts/scrna/SeuratMap2Ref.R +16 -12
  70. biopipen/scripts/scrna/SeuratPreparing.R +138 -81
  71. biopipen/scripts/scrna/SlingShot.R +71 -0
  72. biopipen/scripts/scrna/celltypist-wrapper.py +7 -6
  73. biopipen/scripts/snp/Plink2GTMat.py +26 -11
  74. biopipen/scripts/snp/PlinkFilter.py +7 -7
  75. biopipen/scripts/snp/PlinkFromVcf.py +8 -5
  76. biopipen/scripts/snp/PlinkSimulation.py +4 -4
  77. biopipen/scripts/snp/PlinkUpdateName.py +4 -4
  78. biopipen/scripts/stats/ChowTest.R +48 -22
  79. biopipen/scripts/tcgamaf/Maf2Vcf.py +2 -2
  80. biopipen/scripts/tcgamaf/MafAddChr.py +2 -2
  81. biopipen/scripts/tcr/ClonalStats.R +484 -0
  82. biopipen/scripts/tcr/ScRepLoading.R +127 -0
  83. biopipen/scripts/tcr/TCRDock.py +10 -6
  84. biopipen/scripts/tcr/vdjtools-patch.sh +1 -1
  85. biopipen/scripts/vcf/BcftoolsAnnotate.py +8 -8
  86. biopipen/scripts/vcf/BcftoolsFilter.py +3 -3
  87. biopipen/scripts/vcf/BcftoolsMerge.py +31 -0
  88. biopipen/scripts/vcf/BcftoolsSort.py +4 -4
  89. biopipen/scripts/vcf/BcftoolsView.py +5 -5
  90. biopipen/scripts/vcf/Vcf2Bed.py +2 -2
  91. biopipen/scripts/vcf/VcfAnno.py +11 -11
  92. biopipen/scripts/vcf/VcfDownSample.sh +22 -10
  93. biopipen/scripts/vcf/VcfFilter.py +5 -5
  94. biopipen/scripts/vcf/VcfFix.py +7 -7
  95. biopipen/scripts/vcf/VcfFix_utils.py +12 -3
  96. biopipen/scripts/vcf/VcfIndex.py +3 -3
  97. biopipen/scripts/vcf/VcfIntersect.py +3 -3
  98. biopipen/scripts/vcf/VcfLiftOver.sh +5 -0
  99. biopipen/scripts/vcf/VcfSplitSamples.py +4 -4
  100. biopipen/scripts/vcf/bcftools_utils.py +3 -3
  101. biopipen/scripts/web/Download.py +8 -4
  102. biopipen/scripts/web/DownloadList.py +5 -5
  103. biopipen/scripts/web/GCloudStorageDownloadBucket.py +5 -5
  104. biopipen/scripts/web/GCloudStorageDownloadFile.py +3 -3
  105. biopipen/scripts/web/gcloud_common.py +1 -1
  106. biopipen/utils/gsea.R +75 -35
  107. biopipen/utils/misc.R +205 -7
  108. biopipen/utils/misc.py +17 -8
  109. biopipen/utils/reference.py +11 -11
  110. biopipen/utils/repr.R +146 -0
  111. biopipen/utils/vcf.py +1 -1
  112. {biopipen-0.32.3.dist-info → biopipen-0.33.1.dist-info}/METADATA +8 -8
  113. {biopipen-0.32.3.dist-info → biopipen-0.33.1.dist-info}/RECORD +115 -105
  114. {biopipen-0.32.3.dist-info → biopipen-0.33.1.dist-info}/WHEEL +1 -1
  115. biopipen/scripts/scrna/SeuratClusterStats-hists.R +0 -144
  116. biopipen/scripts/scrna/SeuratPreparing-common.R +0 -467
  117. biopipen/scripts/scrna/SeuratPreparing-doublet_detection.R +0 -204
  118. {biopipen-0.32.3.dist-info → biopipen-0.33.1.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,430 +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
- figfile_pdf <- file.path(odir, paste0(slugify(name), ".bar.pdf"))
228
- genes <- rownames(GetAssayData(case$object))
229
- genes <- genes[sapply(genes, function(x) grepl(x, case$features))]
230
- if (length(genes) == 0) {
231
- p <- case$object@meta.data %>%
232
- group_by(Idents = Idents(case$object)) %>%
233
- summarise(!!sym(name) := !!parse_expr(case$features)) %>%
234
- ggplot(aes(x = Idents, y = !!sym(name)))
235
- } else {
236
- p <- case$object@meta.data %>%
237
- bind_cols(FetchData(case$object, vars = genes, layer = case$layer, cells = rownames(case$object@meta.data))) %>%
238
- group_by(Idents = Idents(case$object)) %>%
239
- summarise(!!sym(name) := !!parse_expr(case$features)) %>%
240
- ggplot(aes(x = Idents, y = !!sym(name)))
241
- }
242
-
243
- if (!is.null(case$group.by)) {
244
- p <- p + geom_bar(aes(fill = !!sym(case$group.by)), stat = "identity", position = "dodge")
245
- } else {
246
- p <- p + geom_bar(aes(fill = Idents), stat = "identity")
247
- }
248
-
249
- p <- p +
250
- scale_fill_biopipen() +
251
- theme_prism() +
252
- theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
253
- labs(x = "Idents", y = name)
254
-
255
- if (!is.null(case$split.by)) {
256
- p <- p + facet_wrap(~ !!sym(case$split.by), ncol = case$ncol)
257
- } else {
258
- case$ncol = 1
259
- }
260
-
261
- if (!is.null(case$plus)) {
262
- p <- p + eval(parse(text = case$plus))
263
- }
264
- devpars = list_update(default_devpars(NULL, case$ncol), devpars)
265
- png(figfile, res = devpars$res, width = devpars$width, height = devpars$height)
266
- print(p)
267
- dev.off()
268
-
269
- pdf(figfile_pdf, width = devpars$width / devpars$res, height = devpars$height / devpars$res)
270
- print(p)
271
- dev.off()
272
-
273
- add_report(
99
+ if (exists("descr") && !is.null(descr)) {
100
+ reporter$add2(
274
101
  list(
275
102
  kind = "descr",
276
- content = paste0(kind, "plots for selected features <code>", case$features, "</code>, by ", ident)
103
+ content = descr
277
104
  ),
278
- list(
279
- kind = "image",
280
- src = figfile,
281
- download = figfile_pdf
282
- ),
283
- h1 = ifelse(is.null(section), name, section),
284
- h2 = ifelse(is.null(section), "#", name)
105
+ hs = c(info$section, info$name)
285
106
  )
286
-
287
- return(NULL)
288
107
  }
289
108
 
290
- case$features = .get_features(case$features)
291
- if (kind == "avgheatmap") {
292
- figfile <- file.path(odir, paste0(slugify(name), ".avgheatmap.png"))
293
- figfile_pdf <- file.path(odir, paste0(slugify(name), ".avgheatmap.pdf"))
294
- assay <- assay %||% DefaultAssay(object)
295
- layer <- layer %||% ifelse("scale.data" %in% Layers(object, assay = assay), "scale.data", "data")
296
-
297
- case_features <- case$features
298
- case$features <- NULL
299
- meta_feats <- intersect(case_features, colnames(object@meta.data))
300
- expr_feats <- setdiff(case_features, meta_feats)
301
- exprs <- NULL
302
- if (length(meta_feats) > 0) {
303
- exprs <- object@meta.data %>% select(all_of(c(meta_feats, ident))) %>%
304
- group_by(!!sym(ident)) %>%
305
- summarise(across(everything(), ~ mean(.x, na.rm = TRUE))) %>%
306
- column_to_rownames(ident) %>%
307
- t()
308
- }
309
- if (length(expr_feats)) {
310
- exprs_tmp <- AverageExpression(
311
- object,
312
- assays = assay,
313
- layer = layer,
314
- features = expr_feats,
315
- group.by = ident)[[assay]]
316
- exprs <- bind_rows(exprs, as.data.frame(exprs_tmp))
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)
317
112
  }
318
-
319
- ha <- NULL
320
- extra_height <- 0
321
- extra_width <- 0 # legend
322
- if (!is.null(cluster_order_val)) {
323
- ha <- list()
324
- ha[[cluster_orderby]] <- cluster_order_val
325
- if (is.numeric(cluster_order_val)) {
326
- col_fun <- colorRamp2(
327
- c(min(cluster_order_val), max(cluster_order_val)),
328
- c("lightyellow", "red"))
329
- ha$col <- list()
330
- ha$col[[cluster_orderby]] <- col_fun
331
- }
332
- ha <- do_call(HeatmapAnnotation, ha)
333
- extra_height <- 40
334
- extra_width <- 120
335
- }
336
-
337
- col_fun <- colorRamp2(
338
- c(min(exprs, na.rm = T), 0, max(exprs, na.rm = T)),
339
- c("lightblue", "white", "darkred"))
340
-
341
- case <- list_update(list(
342
- matrix = as.matrix(exprs),
343
- name = "Average expression",
344
- col = col_fun,
345
- na_col = "white",
346
- row_names_side = "right",
347
- cluster_rows = FALSE,
348
- cluster_columns = FALSE,
349
- rect_gp = gpar(col = "gray", lwd = 1),
350
- row_names_max_width = max_text_width(rownames(exprs)),
351
- top_annotation = ha
352
- ), case)
353
- p <- do_call(Heatmap, case)
354
-
355
- def_devpars = default_devpars(case_features, NULL)
356
- def_devpars$width = def_devpars$width + extra_width
357
- def_devpars$height = def_devpars$height + extra_height
358
- devpars = list_update(def_devpars, devpars)
359
- png(figfile, res = devpars$res, width = devpars$width, height = devpars$height)
360
- print(p)
361
- dev.off()
362
-
363
- pdf(figfile_pdf, width = devpars$width / devpars$res, height = devpars$height / devpars$res)
364
- print(p)
365
- dev.off()
366
-
367
- add_report(
113
+ write.table(p$data, paste0(info$prefix, ".data.txt"), sep="\t", quote=FALSE, row.names=FALSE)
114
+ reporter$add2(
368
115
  list(
369
- kind = "descr",
370
- 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
+ )
371
121
  ),
372
122
  list(
373
- kind = "image",
374
- src = figfile,
375
- download = figfile_pdf
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
+ )
376
135
  ),
377
- h1 = ifelse(is.null(section), name, section),
378
- h2 = ifelse(is.null(section), "#", name)
136
+ hs = c(info$section, info$name),
137
+ ui = "tabs"
379
138
  )
380
- return(NULL)
381
- }
382
-
383
- if (!is.null(case$ncol)) {
384
- case$ncol = min(case$ncol, length(case$features))
385
- }
386
-
387
- if (kind == "table") {
388
- expr = do_call(fn, case)[[DefaultAssay(case$object)]] %>%
389
- as.data.frame() %>%
390
- rownames_to_column("Feature") %>%
391
- select(Feature, everything())
392
-
393
- exprfile = file.path(odir, paste0(slugify(name), ".txt"))
394
- write.table(expr, exprfile, sep="\t", quote=FALSE, row.names=FALSE)
395
-
396
- add_report(
397
- list(
398
- kind = "descr",
399
- content = paste0("Table of expression value for selected features, by ", ident)
400
- ),
401
- list(
402
- kind = "table",
403
- src = exprfile
404
- ),
405
- h1 = ifelse(is.null(case$section), name, case$section),
406
- 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)
407
143
  )
408
- return(NULL)
409
144
  }
410
-
411
- devpars = list_update(default_devpars(case$features, case$ncol), devpars)
412
- if (kind == "heatmap") {
413
- if (!exists("downsample") || is.null(downsample)) {
414
- log_warn(" 'downsample' is not specified for `heatmap`, using `downsample=1000`")
415
- downsample = 1000
416
- }
417
- if (is.numeric(downsample)) {
418
- case$object = base::subset(case$object, downsample = downsample)
419
- } else {
420
- stop(paste0("Unknown downsample method: ", downsample))
421
- }
422
- }
423
- p = do_call(fn, case)
424
- if (!is.null(plus)) {
425
- for (pls in plus) {
426
- p = p + eval(parse(text = pls))
427
- }
428
- }
429
- figfile = file.path(odir, paste0(slugify(name), ".", slugify(kind), ".png"))
430
- png(figfile, width=devpars$width, height=devpars$height, res=devpars$res)
431
- tryCatch({
432
- print(p)
433
- }, error = function(e) {
434
- stop(
435
- paste(
436
- paste(names(devpars), collapse=" "),
437
- paste(devpars, collapse=" "),
438
- e,
439
- sep = "\n"
440
- )
441
- )
442
- })
443
- dev.off()
444
-
445
- figfile_pdf = gsub(".png$", ".pdf", figfile)
446
- pdf(figfile_pdf, width=devpars$width / devpars$res, height=devpars$height / devpars$res)
447
- print(p)
448
- dev.off()
449
-
450
- add_report(
451
- list(
452
- kind = "descr",
453
- content = paste0(kind, "plots for selected features, by ", ident)
454
- ),
455
- list(
456
- kind = "image",
457
- src = figfile,
458
- download = figfile_pdf
459
- ),
460
- h1 = ifelse(is.null(section), name, section),
461
- h2 = ifelse(is.null(section), "#", name)
462
- )
463
145
  }
464
146
 
465
147
  sapply(names(features), do_one_features)
@@ -2,20 +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
- figfile_pdf = file.path(odir, paste0(slugify(name), ".boxplot.pdf"))
18
-
19
16
  if (!is.null(case$subset)) {
20
17
  sobj <- srtobj %>% filter(!!rlang::parse_expr(case$subset))
21
18
  } else {
@@ -26,35 +23,43 @@ do_one_ngenes <- function(name) {
26
23
  select_cols = c(case$ident, case$group.by, case$split.by, ".nexpr")
27
24
  df_cells = df_cells %>% select(all_of(select_cols))
28
25
 
29
- p = df_cells %>%
26
+ p = df_cells |>
30
27
  ggplot(aes(
31
28
  x=!!sym(case$ident),
32
29
  y=.nexpr,
33
30
  fill=!!sym(ifelse(is.null(case$group.by), case$ident, case$group.by))
34
31
  )) +
35
- 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")) +
36
33
  geom_boxplot(
37
34
  position = ifelse(is.null(case$group.by), "identity", "dodge"),
38
35
  width = .1,
39
36
  fill = "white"
40
37
  ) +
41
- theme_prism(axis_text_angle = 90) +
42
- scale_fill_biopipen() +
38
+ plotthis::theme_this() +
39
+ # scale_fill_biopipen() +
43
40
  ylab("Number of genes expressed")
44
41
 
45
42
  if (!is.null(case$split.by)) {
46
43
  p = p + facet_wrap(case$split.by)
47
44
  }
48
45
 
49
- png(figfile, width=case$devpars$width, height=case$devpars$height, res=case$devpars$res)
50
- print(p)
51
- dev.off()
46
+ figprefix = file.path(odir, paste0(slugify(name), ".boxplot"))
52
47
 
53
- pdf(figfile_pdf, width=case$devpars$width / case$devpars$res, height=case$devpars$height / case$devpars$res)
54
- print(p)
55
- dev.off()
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
+ )
56
61
 
57
- add_report(
62
+ reporter$add(
58
63
  list(
59
64
  kind = "descr",
60
65
  content = paste0(
@@ -67,7 +72,17 @@ do_one_ngenes <- function(name) {
67
72
  )
68
73
  )
69
74
  ),
70
- list(kind = "image", src = figfile, download = figfile_pdf),
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
+ )),
71
86
  h1 = name
72
87
  )
73
88
  }