biopipen 0.32.3__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 (117) 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 +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 +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 +85 -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/MarkersFinder.R +273 -654
  59. biopipen/scripts/scrna/RadarPlots.R +73 -53
  60. biopipen/scripts/scrna/SCP-plot.R +15202 -0
  61. biopipen/scripts/scrna/ScVelo.py +0 -0
  62. biopipen/scripts/scrna/SeuratClusterStats-clustree.R +23 -31
  63. biopipen/scripts/scrna/SeuratClusterStats-dimplots.R +26 -54
  64. biopipen/scripts/scrna/SeuratClusterStats-features.R +85 -403
  65. biopipen/scripts/scrna/SeuratClusterStats-ngenes.R +32 -17
  66. biopipen/scripts/scrna/SeuratClusterStats-stats.R +45 -239
  67. biopipen/scripts/scrna/SeuratClusterStats.R +13 -19
  68. biopipen/scripts/scrna/SeuratMap2Ref.R +16 -12
  69. biopipen/scripts/scrna/SeuratPreparing.R +138 -81
  70. biopipen/scripts/scrna/SlingShot.R +71 -0
  71. biopipen/scripts/scrna/celltypist-wrapper.py +7 -6
  72. biopipen/scripts/snp/Plink2GTMat.py +26 -11
  73. biopipen/scripts/snp/PlinkFilter.py +7 -7
  74. biopipen/scripts/snp/PlinkFromVcf.py +8 -5
  75. biopipen/scripts/snp/PlinkSimulation.py +4 -4
  76. biopipen/scripts/snp/PlinkUpdateName.py +4 -4
  77. biopipen/scripts/stats/ChowTest.R +48 -22
  78. biopipen/scripts/tcgamaf/Maf2Vcf.py +2 -2
  79. biopipen/scripts/tcgamaf/MafAddChr.py +2 -2
  80. biopipen/scripts/tcr/ClonalStats.R +484 -0
  81. biopipen/scripts/tcr/ScRepLoading.R +127 -0
  82. biopipen/scripts/tcr/TCRDock.py +10 -6
  83. biopipen/scripts/tcr/vdjtools-patch.sh +1 -1
  84. biopipen/scripts/vcf/BcftoolsAnnotate.py +8 -8
  85. biopipen/scripts/vcf/BcftoolsFilter.py +3 -3
  86. biopipen/scripts/vcf/BcftoolsMerge.py +31 -0
  87. biopipen/scripts/vcf/BcftoolsSort.py +4 -4
  88. biopipen/scripts/vcf/BcftoolsView.py +5 -5
  89. biopipen/scripts/vcf/Vcf2Bed.py +2 -2
  90. biopipen/scripts/vcf/VcfAnno.py +11 -11
  91. biopipen/scripts/vcf/VcfDownSample.sh +22 -10
  92. biopipen/scripts/vcf/VcfFilter.py +5 -5
  93. biopipen/scripts/vcf/VcfFix.py +7 -7
  94. biopipen/scripts/vcf/VcfFix_utils.py +12 -3
  95. biopipen/scripts/vcf/VcfIndex.py +3 -3
  96. biopipen/scripts/vcf/VcfIntersect.py +3 -3
  97. biopipen/scripts/vcf/VcfLiftOver.sh +5 -0
  98. biopipen/scripts/vcf/VcfSplitSamples.py +4 -4
  99. biopipen/scripts/vcf/bcftools_utils.py +3 -3
  100. biopipen/scripts/web/Download.py +8 -4
  101. biopipen/scripts/web/DownloadList.py +5 -5
  102. biopipen/scripts/web/GCloudStorageDownloadBucket.py +5 -5
  103. biopipen/scripts/web/GCloudStorageDownloadFile.py +3 -3
  104. biopipen/scripts/web/gcloud_common.py +1 -1
  105. biopipen/utils/gsea.R +75 -35
  106. biopipen/utils/misc.R +205 -7
  107. biopipen/utils/misc.py +17 -8
  108. biopipen/utils/reference.py +11 -11
  109. biopipen/utils/repr.R +146 -0
  110. biopipen/utils/vcf.py +1 -1
  111. {biopipen-0.32.3.dist-info → biopipen-0.33.0.dist-info}/METADATA +8 -8
  112. {biopipen-0.32.3.dist-info → biopipen-0.33.0.dist-info}/RECORD +114 -105
  113. {biopipen-0.32.3.dist-info → biopipen-0.33.0.dist-info}/WHEEL +1 -1
  114. biopipen/scripts/scrna/SeuratClusterStats-hists.R +0 -144
  115. biopipen/scripts/scrna/SeuratPreparing-common.R +0 -467
  116. biopipen/scripts/scrna/SeuratPreparing-doublet_detection.R +0 -204
  117. {biopipen-0.32.3.dist-info → biopipen-0.33.0.dist-info}/entry_points.txt +0 -0
@@ -1,23 +1,11 @@
1
- {{ biopipen_dir | joinpaths: "utils", "misc.R" | source_r }}
2
- {{ biopipen_dir | joinpaths: "utils", "caching.R" | source_r }}
3
- {{ biopipen_dir | joinpaths: "utils", "mutate_helpers.R" | source_r }}
4
-
5
1
  library(rlang)
6
2
  library(dplyr)
7
- library(tidyr)
8
- library(tibble)
9
3
  library(Seurat)
10
- library(enrichR)
11
- library(ggplot2)
12
- library(ggprism)
13
- library(ggrepel)
14
- library(future)
15
- library(tidyseurat)
16
- library(ggVennDiagram)
17
- library(UpSetR)
18
-
19
- log_info("Setting up EnrichR ...")
20
- setEnrichrSite("Enrichr")
4
+ library(plotthis)
5
+ library(biopipen.utils)
6
+
7
+ log <- get_logger()
8
+ reporter <- get_reporter()
21
9
 
22
10
  srtfile <- {{ in.srtobj | quote }}
23
11
  outdir <- {{ out.outdir | quote }}
@@ -30,58 +18,37 @@ group.by <- {{ envs["group-by"] | r }}
30
18
  each <- {{ envs.each | r }}
31
19
  prefix_each <- {{ envs.prefix_each | r }}
32
20
  prefix_group <- {{ envs.prefix_group | r }}
33
- section <- {{ envs.section | r }}
34
- dbs <- {{ envs.dbs | r }}
35
21
  assay <- {{ envs.assay | r }}
36
- sigmarkers <- {{ envs.sigmarkers | r }}
37
- volcano_genes <- {{ envs.volcano_genes | r }}
38
22
  subset <- {{ envs.subset | r }}
23
+ error <- {{ envs.error | r }}
24
+ site <- {{ envs.site | r }}
39
25
  rest <- {{ envs.rest | r: todot="-" }}
40
- dotplot <- {{ envs.dotplot | r: todot="-" }}
41
- cases <- {{ envs.cases | r: todot="-", skip=1 }}
42
- overlapping_defaults <- {{ envs.overlap_defaults | r }}
43
- overlapping <- {{ envs.overlap | r }}
26
+ dbs <- {{ envs.dbs | r }}
27
+ sigmarkers <- {{ envs.sigmarkers | r }}
44
28
  cache <- {{ envs.cache | r }}
29
+ allmarker_plots_defaults <- {{ envs.allmarker_plots_defaults | r }}
30
+ allmarker_plots <- {{ envs.allmarker_plots | r }}
31
+ marker_plots_defaults <- {{ envs.marker_plots_defaults | r }}
32
+ marker_plots <- {{ envs.marker_plots | r }}
33
+ enrich_plots_defaults <- {{ envs.enrich_plots_defaults | r }}
34
+ enrich_plots <- {{ envs.enrich_plots | r }}
35
+ cases <- {{ envs.cases | r: todot="-", skip=1 }}
36
+ overlaps_defaults <- {{ envs.overlaps_defaults | r }}
37
+ overlaps <- {{ envs.overlaps | r }}
45
38
 
46
39
  if (isTRUE(cache)) { cache <- joboutdir }
47
40
 
48
- # expand overlapping
49
- for (sec in names(overlapping)) {
50
- overlapping[[sec]] <- list_update(overlapping_defaults, overlapping[[sec]])
51
- }
52
- overlapping_sections <- names(overlapping)
53
-
54
- overlaps <- list()
55
- if (is.character(volcano_genes) && length(volcano_genes) == 1) {
56
- volcano_genes <- trimws(strsplit(volcano_genes, ",")[[1]])
57
- }
58
-
59
41
  set.seed(8525)
60
42
  if (ncores > 1) {
61
43
  options(future.globals.maxSize = 80000 * 1024^2)
62
44
  plan(strategy = "multicore", workers = ncores)
63
45
  }
64
46
 
65
- log_info("- Reading Seurat object ...")
47
+ log$info("Reading Seurat object ...")
66
48
  srtobj <- readRDS(srtfile)
67
- defassay <- DefaultAssay(srtobj)
68
- if (defassay == "SCT" && !"PrepSCTFindMarkers" %in% names(srtobj@commands)) {
69
- log_warn(" SCTransform used but PrepSCTFindMarkers not applied, running ...")
70
-
71
- srtobj <- PrepSCTFindMarkers(srtobj)
72
- # compose a new SeuratCommand to record it to srtobj@commands
73
- commands <- names(pbmc_small@commands)
74
- scommand <- pbmc_small@commands[[commands[length(commands)]]]
75
- scommand@name <- "PrepSCTFindMarkers"
76
- scommand@time.stamp <- Sys.time()
77
- scommand@assay.used <- "SCT"
78
- scommand@call.string <- "PrepSCTFindMarkers(object = srtobj)"
79
- scommand@params <- list()
80
- srtobj@commands$PrepSCTFindMarkers <- scommand
81
- }
82
49
 
83
50
  if (!is.null(mutaters) && length(mutaters) > 0) {
84
- log_info("- Mutating meta data ...")
51
+ log$info("Mutating meta data ...")
85
52
  srtobj@meta.data <- srtobj@meta.data %>%
86
53
  mutate(!!!lapply(mutaters, parse_expr))
87
54
  }
@@ -93,665 +60,317 @@ defaults <- list(
93
60
  each = each,
94
61
  prefix_each = prefix_each,
95
62
  prefix_group = prefix_group,
96
- section = section,
97
63
  dbs = dbs,
98
- assay = assay %||% defassay,
64
+ assay = assay %||% DefaultAssay(srtobj),
99
65
  subset = subset,
66
+ error = error,
67
+ site = site,
100
68
  sigmarkers = sigmarkers,
101
- volcano_genes = volcano_genes,
102
- dotplot = dotplot,
69
+ allmarker_plots = allmarker_plots,
70
+ marker_plots = marker_plots,
71
+ enrich_plots = enrich_plots,
72
+ cache = cache,
103
73
  rest = rest
104
74
  )
105
75
 
106
- expand_each <- function(name, case) {
76
+ log$info("Expanding cases ...")
77
+
78
+ post_casing <- function(name, case) {
107
79
  outcases <- list()
108
- no_each <- is.null(case$each) || nchar(case$each) == 0
109
- if (no_each && !is.null(case$ident.1)) {
80
+ no_each <- is.null(case$each) || is.na(case$each) || nchar(case$each) == 0
81
+
82
+ if (no_each) {
110
83
  # single cases, no need to expand
111
- if (is.null(case$section) || case$section == "DEFAULT") {
112
- outcases[[name]] <- case
84
+ case$allmarker_plots <- lapply(
85
+ case$allmarker_plots,
86
+ function(x) { list_update(allmarker_plots_defaults, x) }
87
+ )
88
+ case$marker_plots <- lapply(
89
+ case$marker_plots,
90
+ function(x) { list_update(marker_plots_defaults, x) }
91
+ )
92
+ case$enrich_plots <- lapply(
93
+ case$enrich_plots,
94
+ function(x) { list_update(enrich_plots_defaults, x) }
95
+ )
96
+ outcases[[name]] <- case
97
+ } else { # !no_each
98
+ if (!is.null(case$subset)) {
99
+ sobj <- srtobj %>% filter(!!parse_expr(case$subset))
113
100
  } else {
114
- outcases[[paste0(case$section, "::", name)]] <- case
101
+ sobj <- srtobj
115
102
  }
116
- } else { # !no_each || is.null(case$ident.1)
117
- if (!is.null(case$section) && case$section != "DEFAULT") {
118
- log_warn(" Ignoring `section` in case `{name}` that will be expanded (`each` is set or `ident-1` is not set).")
119
- case$section <- NULL
120
- }
121
- if (no_each) { # is.null(ident.1)
122
- # no each and no ident.1, use FindAllMarkers
123
- key <- paste0(name, "::", name)
124
- outcases[[key]] <- case
125
- outcases[[key]]$section <- name
126
- outcases[[key]]$findall <- TRUE
127
- } else if (!no_each) {
128
- # expand each
129
- if (is.null(case$subset)) {
130
- eachs <- srtobj@meta.data %>%
131
- pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
103
+
104
+ eachs <- sobj@meta.data %>% pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
105
+ case_1 <- case
106
+ for (each in eachs) {
107
+ each_name <- ifelse(case_1$prefix_each, paste0(case_1$each, " - ", each), each)
108
+ if (!is.null(case_1$ident.1)) {
109
+ # Make name a section
110
+ key <- paste0(name, "::", each_name)
132
111
  } else {
133
- eachs <- srtobj@meta.data %>% dplyr::filter(!!parse_expr(case$subset)) %>%
134
- pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
112
+ key <- paste0(name, ": ", each_name)
135
113
  }
136
- for (each in eachs) {
137
- by <- make.names(paste0("..", name, "_", case$each,"_", each))
138
- srtobj@meta.data <<- srtobj@meta.data %>% mutate(
139
- !!sym(by) := if_else(
140
- !!sym(case$each) == each,
141
- !!sym(case$group.by),
142
- NA
143
- )
144
- )
145
- if (isTRUE(case$prefix_each)) {
146
- key <- paste0(name, "::", case$each, " - ", each)
147
- } else {
148
- key <- paste0(name, "::", each)
149
- }
150
- outcases[[key]] <- case
151
- outcases[[key]]$section <- name
152
- outcases[[key]]$group.by <- by
153
- if (is.null(case$ident.1)) {
154
- outcases[[key]]$findall <- TRUE
155
- }
114
+ if (!is.null(case$subset)) {
115
+ case_1$subset <- paste0(case$subset, " & `", case_1$each, "` == '", each, "'")
116
+ } else {
117
+ case_1$subset <- paste0("`", case_1$each, "` == '", each, "'")
156
118
  }
119
+ case_1$allmarker_plots <- lapply(
120
+ case_1$allmarker_plots,
121
+ function(x) { list_update(allmarker_plots_defaults, x) }
122
+ )
123
+ case_1$marker_plots <- lapply(
124
+ case_1$marker_plots,
125
+ function(x) { list_update(marker_plots_defaults, x) }
126
+ )
127
+ case_1$enrich_plots <- lapply(
128
+ case_1$enrich_plots,
129
+ function(x) { list_update(enrich_plots_defaults, x) }
130
+ )
131
+ outcases[[key]] <- case_1
157
132
  }
158
133
  }
159
134
  outcases
160
135
  }
161
-
162
- log_info("- Expanding cases ...")
163
- cases <- expand_cases(cases, defaults, expand_each)
164
-
165
- plot_volcano = function(markers, volfile, sig, volgenes) {
166
- # markers
167
- # gene p_val avg_log2FC pct.1 pct.2 p_val_adj
168
- # 1 CCL5 1.883596e-11 -4.8282535 0.359 0.927 4.332270e-09
169
- # 2 HLA-DQB1 3.667713e-09 6.1543174 0.718 0.098 8.435740e-07
170
- # 3 HLA-DRB5 1.242993e-07 3.9032231 0.744 0.195 2.858885e-05
171
- # 4 CD79B 2.036731e-07 4.2748835 0.692 0.146 4.684482e-05
172
- log_info(" Plotting volcano plot ...")
173
- markers = markers %>%
174
- mutate(
175
- Significant = if_else(
176
- !!parse_expr(sig),
177
- if_else(avg_log2FC > 0, "Up", "Down"),
178
- "No"
179
- ),
180
- Label = if_else(
181
- Significant != "No" & (isTRUE(volgenes) | (gene %in% volgenes)),
182
- gene,
183
- ""
184
- )
185
- )
186
-
187
- p_vol = ggplot(markers, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
188
- geom_point(aes(color = Significant), alpha = 0.75) +
189
- scale_color_manual(
190
- values = c(Up = "#FF3333", Down = "#3333FF", No = "#AAAAAA"),
191
- labels = c(Up = "Up", Down = "Down", No = "Non-Significant")
192
- ) +
193
- geom_text_repel(
194
- aes(label = Label),
195
- size = 3,
196
- color = "#000000",
197
- box.padding = unit(0.35, "lines"),
198
- point.padding = unit(0.5, "lines"),
199
- segment.color = "#000000"
200
- ) +
201
- theme_prism() +
202
- theme(legend.title=element_blank(), plot.margin=unit(c(1,1,1,1), "cm")) +
203
- labs(
204
- x = "log2 Fold Change",
205
- y = "-log10 Adjusted P-value"
206
- )
207
-
208
- png(volfile, res = 100, height = 1200, width = 900)
209
- print(p_vol)
210
- dev.off()
211
-
212
- volfile_pdf <- gsub(".png$", ".pdf", volfile)
213
- pdf(volfile_pdf, width = 9, height = 12)
214
- print(p_vol)
215
- dev.off()
216
- }
217
-
218
- # Do enrichment analysis for a case using Enrichr
219
- # Args:
220
- # case: case name
221
- # markers: markers dataframe
222
- # sig: The expression to filter significant markers
223
- do_enrich <- function(info, markers, sig, volgenes) {
224
- log_info(" Running enrichment for case: {info$casename}")
225
-
226
- if (nrow(markers) == 0) {
227
- log_warn(" No markers found for case: {info$casename}")
228
- return(NULL)
229
- }
230
-
231
- plot_volcano(markers, file.path(info$casedir, "volcano.png"), sig, volgenes)
232
-
233
- markers_sig <- markers %>% filter(!!parse_expr(sig)) %>% arrange(p_val_adj)
234
- if (nrow(markers_sig) == 0) {
235
- log_warn(" No significant markers found.")
236
- return(NULL)
237
- }
238
-
239
- write.table(
240
- markers_sig,
241
- file.path(info$casedir, "markers.txt"),
242
- sep = "\t",
243
- row.names = FALSE,
244
- col.names = TRUE,
245
- quote = FALSE
246
- )
247
- if (nrow(markers_sig) < 5) {
248
- log_warn(" Too few significant markers found for case: {info$casename}")
249
- } else {
250
- enriched <- enrichr(unique(markers_sig$gene), dbs)
251
- for (db in dbs) {
252
- write.table(
253
- enriched[[db]],
254
- file.path(info$casedir, paste0("Enrichr-", db, ".txt")),
255
- sep = "\t",
256
- row.names = FALSE,
257
- col.names = TRUE,
258
- quote = FALSE
259
- )
260
- if (nrow(enriched[[db]]) == 0) {
261
- log_warn(" No enrichment found for case: {info$casename} - {db}")
262
- next
136
+ cases <- expand_cases(cases, defaults, post_casing)
137
+
138
+ # Checking the overlapping cases
139
+ case_markers <- list()
140
+ if (length(overlaps) > 0) {
141
+ log$info("Checking overlapping cases ...")
142
+ overlaps <- expand_cases(overlaps, overlaps_defaults)
143
+ for (ovname in names(overlaps)) {
144
+ ov <- overlaps[[ovname]]
145
+ # check the existence of the cases
146
+ for (case in ov$cases) {
147
+ if (is.null(cases[[case]])) {
148
+ stop(paste0("Case '", case, "' not found in the cases for overlapping case '", ovname, "'"))
263
149
  }
264
- enrich_p <- plotEnrich(enriched[[db]], showTerms = 20, title = db) +
265
- theme_prism()
266
- enrich_plot <- file.path(info$casedir, paste0("Enrichr-", db, ".png"))
267
- png(enrich_plot, res = 100, height = 1000, width = 1000)
268
- print(enrich_p)
269
- dev.off()
270
-
271
- enrich_plot_pdf <- gsub(".png$", ".pdf", enrich_plot)
272
- pdf(enrich_plot_pdf, width = 10, height = 10)
273
- print(enrich_p)
274
- dev.off()
150
+ }
151
+ if (length(ov$cases) < 2) {
152
+ stop("Overlapping cases must have at least 2 cases for overlapping case '", ovname, "'")
153
+ }
154
+ for (case in ov$cases) {
155
+ case_markers[[case]] <- TRUE
156
+ }
157
+ if (identical(ov$venn$enabled, "auto")) {
158
+ overlaps[[ovname]]$venn$enabled <- length(ov$cases) <= 5
275
159
  }
276
160
  }
277
- unique(markers_sig$gene)
278
161
  }
279
162
 
280
- do_dotplot <- function(info, siggenes, dotplot, args) {
281
- max_dotplot_features <- dotplot$maxgenes %||% 20
282
- dotplot$maxgenes <- NULL
283
- if (length(siggenes) > max_dotplot_features) {
284
- log_debug(" Too many significant markers ({length(siggenes)}), using first {max_dotplot_features} for dotplot")
285
- siggenes <- siggenes[1:max_dotplot_features]
286
- }
287
- dotplot_devpars <- dotplot$devpars
288
- dotplot$devpars <- NULL
289
- dotplot$object <- args$object
290
- dotplot$features <- siggenes
291
- dotplot$group.by <- args$group.by
292
- dotplot_width <- dotplot_devpars$width %||%
293
- ifelse(length(siggenes) <= 20, length(siggenes) * 60, min(1000, length(siggenes)) * 30)
294
- dotplot_height <- dotplot_devpars$height %||% 600
295
- dotplot_res <- dotplot_devpars$res %||% 100
296
- dotplot_file <- file.path(info$casedir, "dotplot.png")
297
- dot_p <- do_call(DotPlot, dotplot) +
298
- theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
299
- coord_flip()
300
- png(dotplot_file, res = dotplot_res, width = dotplot_height, height = dotplot_width)
301
- # rotate x axis labels
302
- print(dot_p)
303
- dev.off()
304
-
305
- dotplot_file_pdf <- gsub(".png$", ".pdf", dotplot_file)
306
- pdf(dotplot_file_pdf, width = dotplot_height / dotplot_res, height = dotplot_width / dotplot_res)
307
- print(dot_p)
308
- dev.off()
309
- }
163
+ log$info("Running cases ...")
310
164
 
311
- add_case_report <- function(info, sigmarkers, siggenes) {
312
- h1 = info$h1
313
- h2 = info$h2
314
- if (is.null(siggenes) || length(siggenes) == 0) {
315
- add_report(
316
- list(
317
- kind = "error",
318
- content = "No significant markers found."
319
- ),
320
- h1 = h1,
321
- h2 = ifelse(h2 == "#", "Markers", h2),
322
- h3 = ifelse(h2 == "#", "#", "Markers"),
323
- ui = "flat"
324
- )
325
- } else {
326
- add_report(
327
- list(
328
- title = "Significant Markers",
329
- ui = "flat",
330
- contents = list(
331
- list(
332
- kind = "descr",
333
- content = paste0(
334
- "The markers are found using Seurat's FindMarkers function, ",
335
- "and filtered by: ",
336
- html_escape(sigmarkers)
337
- )
338
- ),
339
- list(
340
- kind = "table",
341
- data = list(nrows = 100),
342
- src = file.path(info$casedir, "markers.txt")
343
- )
344
- )
345
- ),
346
- list(
347
- title = "Volcano Plot",
348
- ui = "flat",
349
- contents = list(
350
- list(
351
- kind = "descr",
352
- content = paste0(
353
- "The volcano plot is generated using ggplot2. ",
354
- "The significant markers are highlighted in blue and red, ",
355
- "indicating up-regulated and down-regulated genes, respectively. ",
356
- "The non-significant genes are shown in grey. "
357
- )
358
- ),
359
- list(
360
- kind = "img",
361
- src = file.path(info$casedir, "volcano.png"),
362
- download = file.path(info$casedir, "volcano.pdf")
363
- )
364
- )
365
- ),
165
+ process_markers <- function(markers, info, case) {
166
+ # Save markers
167
+ write.table(markers, file.path(info$prefix, "markers.tsv"), sep = "\t", quote = FALSE, row.names = FALSE)
168
+ reporter$add2(
169
+ list(
170
+ name = "Table",
171
+ contents = list(list(kind = "table", src = file.path(info$prefix, "markers.tsv"), data = list(nrows = 100)))
172
+ ),
173
+ hs = c(info$section, info$name),
174
+ hs2 = "Markers",
175
+ ui = "tabs"
176
+ )
177
+
178
+ for (plotname in names(case$marker_plots)) {
179
+ plotargs <- case$marker_plots[[plotname]]
180
+ plotargs$degs <- markers
181
+ plotargs$outprefix <- file.path(info$prefix, paste0("markers.", slugify(plotname)))
182
+ do_call(VizDEGs, plotargs)
183
+ reporter$add2(
366
184
  list(
367
- title = "Dot Plot",
368
- ui = "flat",
369
- contents = list(
370
- list(
371
- kind = "descr",
372
- content = paste0(
373
- "The dot plot is generated using Seurat's DotPlot function. ",
374
- "The top significant markers are used as input. ",
375
- "The sizes of the dots are proportional to the percentage of cells ",
376
- "expressing the gene in each group. ",
377
- "The colors of the dots are proportional to the average expression ",
378
- "of the gene in each group. "
379
- )
380
- ),
381
- list(
382
- kind = "img",
383
- src = file.path(info$casedir, "dotplot.png"),
384
- download = file.path(info$casedir, "dotplot.pdf")
385
- )
386
- )
387
- ),
388
- h1 = h1,
389
- h2 = ifelse(h2 == "#", "Markers", h2),
390
- h3 = ifelse(h2 == "#", "#", "Markers"),
185
+ name = plotname,
186
+ contents = list(reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code))),
187
+ hs = c(info$section, info$name),
188
+ hs2 = "Markers",
391
189
  ui = "tabs"
392
190
  )
191
+ }
393
192
 
394
- add_report(
395
- list(
396
- kind = "descr",
397
- content = paste0(
398
- "The enrichment analysis is done using Enrichr. ",
399
- "The significant markers are used as input. "
400
- )
401
- ),
193
+ # Do enrichment analysis
194
+ tryCatch({
195
+ enrich <- RunEnrichment(
196
+ markers, deg = case$sigmarkers, dbs = case$dbs, cache = case$cache,
197
+ error = TRUE, site = case$site)
198
+
199
+ write.table(enrich, file.path(info$prefix, "enrich.tsv"), sep = "\t", quote = FALSE, row.names = FALSE)
200
+ reporter$add2(
402
201
  list(
403
- kind = "enrichr",
404
- dir = info$casedir
202
+ name = "Table",
203
+ contents = list(list(kind = "table", src = file.path(info$prefix, "enrich.tsv"), data = list(nrows = 100)))
405
204
  ),
406
- h1 = h1,
407
- h2 = ifelse(h2 == "#", "Enrichment Analysis", h2),
408
- h3 = ifelse(h2 == "#", "#", "Enrichment Analysis"),
409
- ui = "flat"
205
+ hs = c(info$section, info$name),
206
+ hs2 = "Enrichment Analysis",
207
+ ui = "tabs"
410
208
  )
411
- }
412
- }
413
-
414
- ensure_sobj <- function(expr, allow_empty) {
415
- tryCatch({ expr }, error = function(e) {
416
- if (allow_empty) {
417
- log_warn(" Ignoring this case: {e$message}")
418
- return(NULL)
419
- } else {
420
- stop(e)
421
- }
422
- })
423
- }
424
209
 
425
- do_case_findall <- function(casename) {
426
- # casename
427
- ## Cluster::Cluster
428
- info <- casename_info(casename, cases, outdir, create = FALSE)
429
- if (info$section %in% overlapping_sections) {
430
- stop(paste0(" Can't do overlapping analysis for case without `ident-1` set: ", casename))
431
- }
432
-
433
- case <- cases[[casename]]
434
- log_info(" Using FindAllMarkers for case: {casename}...")
435
- args <- case$rest
436
- args$assay <- case$assay
437
- args$group.by <- case$group.by
438
- # args$logfc.threshold <- args$logfc.threshold %||% 0
439
- # args$min.cells.group <- args$min.cells.group %||% 1
440
- # args$min.cells.feature <- args$min.cells.feature %||% 1
441
- # args$min.pct <- args$min.pct %||% 0
442
- allow_empty = startsWith(case$group.by, "..")
443
- if (!is.null(case$subset)) {
444
- args$object <- ensure_sobj({
445
- srtobj %>% filter(!!parse_expr(case$subset) & !is.na(!!sym(case$group.by)))
446
- }, allow_empty)
447
- if (is.null(args$object)) { return() }
448
- } else {
449
- args$object <- ensure_sobj({
450
- srtobj %>% filter(!is.na(!!sym(case$group.by)))
451
- }, allow_empty)
452
- if (is.null(args$object)) { return() }
453
- }
454
- Idents(args$object) <- case$group.by
210
+ # Visualize enriched terms
211
+ if (length(case$enrich_plots) > 0) {
212
+ for (db in case$dbs) {
213
+ plots <- list()
214
+ for (plotname in names(case$enrich_plots)) {
215
+ plotargs <- case$enrich_plots[[plotname]]
216
+ plotargs$enrich <- enrich[enrich$db == db, , drop = FALSE]
217
+ plotargs$outprefix <- file.path(info$prefix, paste0("enrich.", slugify(db), ".", slugify(plotname)))
455
218
 
456
- cached <- get_cached(args, "FindAllMarkers", cache)
457
- if (!is.null(cached$data)) {
458
- log_info(" Using cached markers ...")
459
- markers <- cached$data
460
- } else {
461
- markers <- find_markers(args, find_all = TRUE)
462
- cached$data <- markers
463
- save_to_cache(cached, "FindAllMarkers", cache)
464
- }
465
-
466
- if (is.null(case$dotplot$assay)) {
467
- case$dotplot$assay <- case$assay
468
- }
219
+ do_call(VizEnrich, plotargs)
469
220
 
470
- if (nrow(markers) == 0) {
471
- idents <- unique(Idents(args$object))
472
- } else {
473
- idents <- unique(markers$cluster)
474
- }
475
- for (ident in idents) {
476
- log_debug(" * Dealing with ident: {ident}...")
477
- if (case$prefix_group) {
478
- key <- paste0(info$section, "::", case$group.by, " - ", ident)
479
- } else {
480
- key <- paste0(info$section, "::", ident)
481
- }
482
- info_ident <- casename_info(key, cases, outdir, create = TRUE)
483
- if (nrow(markers) > 0) {
484
- markers_ident <- markers %>% filter(cluster == ident)
485
- } else {
486
- markers_ident <- markers
487
- }
488
- siggenes <- do_enrich(info_ident, markers_ident, case$sigmarkers, case$volcano_genes)
489
-
490
- if (length(siggenes) > 0) {
491
- args$ident.1 <- as.character(ident)
492
- do_dotplot(info_ident, siggenes, case$dotplot, args)
493
- }
494
-
495
- add_case_report(info_ident, case$sigmarkers, siggenes)
496
- }
497
- }
498
-
499
- find_markers <- function(findmarkers_args, find_all = FALSE) {
500
- if (find_all) {
501
- fun <- FindAllMarkers
502
- empty <- data.frame(
503
- gene = character(),
504
- p_val = numeric(),
505
- avg_log2FC = numeric(),
506
- pct.1 = numeric(),
507
- pct.2 = numeric(),
508
- p_val_adj = numeric(),
509
- cluster = character()
510
- )
511
- } else {
512
- fun <- FindMarkers
513
- empty <- data.frame(
514
- gene = character(),
515
- p_val = numeric(),
516
- avg_log2FC = numeric(),
517
- pct.1 = numeric(),
518
- pct.2 = numeric(),
519
- p_val_adj = numeric()
520
- )
521
- }
522
-
523
- call_findmarkers <- function(fn, args) {
524
- if (find_all) {
525
- do_call(fn, args)
526
- } else {
527
- do_call(fn, args) %>% rownames_to_column("gene")
221
+ plots[[length(plots) + 1]] <- reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code)
222
+ }
223
+ reporter$add2(
224
+ list(name = db, contents = plots),
225
+ hs = c(info$section, info$name),
226
+ hs2 = "Enrichment Analysis",
227
+ ui = "tabs"
228
+ )
229
+ }
528
230
  }
529
- }
530
- markers <- tryCatch({
531
- call_findmarkers(fun, findmarkers_args)
532
231
  }, error = function(e) {
533
- if (!grepl("PrepSCTFindMarkers", e$message) && defassay == "SCT") {
534
- log_warn(paste0(" ! ", e$message))
232
+ if (case$error) {
233
+ stop("Error: ", e$message)
234
+ } else {
235
+ log$warn(" ! Error: {e$message}")
236
+ reporter$add2(
237
+ list(
238
+ name = "Warning",
239
+ contents = list(list(kind = "error", content = e$message, kind_ = "warning"))),
240
+ hs = c(info$section, info$name),
241
+ hs2 = "Enrichment Analysis",
242
+ ui = "tabs"
243
+ )
535
244
  }
536
- empty
537
245
  })
538
-
539
- if (nrow(markers) == 0 && defassay == "SCT") {
540
- log_warn(" ! No markers found from SCT assay, trying recorrect_umi = FALSE")
541
- findmarkers_args$recorrect_umi <- FALSE
542
- markers <- tryCatch({
543
- call_findmarkers(fun, findmarkers_args)
544
- }, error = function(e) {
545
- log_warn(paste0(" ! ", e$message))
546
- empty
547
- })
548
- }
549
-
550
- markers
551
246
  }
552
247
 
553
- sections <- c()
554
- do_case <- function(casename) {
555
- if (isTRUE(cases[[casename]]$findall)) {
556
- log_info("- Dealing with case: {casename} (all idents) ...")
557
- do_case_findall(casename)
558
- return()
559
- }
560
- log_info("- Dealing with case: {casename} ...")
561
-
562
- info <- casename_info(casename, cases, outdir, create = TRUE)
563
- case <- cases[[casename]]
564
- # ident1
565
- # ident2
566
- # groupby
567
- # each # expanded
568
- # prefix_each
569
- # dbs
570
- # sigmarkers
571
- # rest
572
- args <- case$rest
573
- allow_empty = startsWith(case$group.by, "..")
574
- if (!is.null(case$subset)) {
575
- args$object <- ensure_sobj({
576
- srtobj %>% filter(!!parse_expr(case$subset) & !is.na(!!sym(case$group.by)))
577
- }, allow_empty)
578
- if (is.null(args$object)) { return() }
579
- } else {
580
- args$object <- ensure_sobj({
581
- srtobj %>% filter(!is.na(!!sym(case$group.by)))
582
- }, allow_empty)
583
- if (is.null(args$object)) { return() }
584
- }
248
+ run_case <- function(name) {
249
+ case <- cases[[name]]
250
+ log$info("- Case: {name} ...")
585
251
 
586
- args$assay <- case$assay
252
+ args <- case$rest %||% list()
253
+ args$object <- srtobj
587
254
  args$group.by <- case$group.by
588
255
  args$ident.1 <- case$ident.1
589
256
  args$ident.2 <- case$ident.2
590
- if (is.null(args$ident.2)) {
591
- args$ident.2 <- ".rest"
592
- args$object <- args$object %>% mutate(
593
- !!sym(args$group.by) := if_else(
594
- !!sym(args$group.by) == args$ident.1,
595
- args$ident.1,
596
- args$ident.2
597
- )
598
- )
599
- } else {
600
- args$object <- args$object %>%
601
- filter(!!sym(args$group.by) %in% c(args$ident.1, args$ident.2))
602
- }
603
- # args$logfc.threshold <- args$logfc.threshold %||% 0
604
- # args$min.cells.group <- args$min.cells.group %||% 1
605
- # args$min.cells.feature <- args$min.cells.feature %||% 1
606
- # args$min.pct <- args$min.pct %||% 0
607
-
608
- markers <- find_markers(args)
609
- siggenes <- do_enrich(info, markers, case$sigmarkers, case$volcano_genes)
257
+ args$cache <- case$cache
258
+ args$assay <- case$assay
259
+ args$error <- case$error
260
+ args$subset <- case$subset
610
261
 
611
- if (length(siggenes) > 0) {
612
- case$dotplot$assay <- case$dotplot$assay %||% args$assay
613
- do_dotplot(info, siggenes, case$dotplot, args)
262
+ markers <- do_call(RunSeuratDEAnalysis, args)
263
+ if (isTRUE(case_markers[[name]])) {
264
+ case_markers[[name]] <<- markers
614
265
  }
266
+ if (is.null(case$ident.1)) {
267
+ if (!is.null(case_markers[[name]])) {
268
+ stop("Case '", name, "' for overlapping analysis must have 'ident.1' defined")
269
+ }
270
+ all_idents <- unique(markers[[case$group.by]])
271
+ # Visualize all markers
272
+ if (length(case$allmarker_plots) > 0) {
273
+ log$info(" Visualizing all markers ...")
274
+ casename <- paste0(name, "::", ifelse(case$prefix_group, paste0(case$group.by, " - All Markers"), "All Markers"))
275
+ info <- case_info(casename, outdir, create = TRUE)
276
+ for (plotname in names(case$allmarker_plots)) {
277
+ plotargs <- case$allmarker_plots[[plotname]]
278
+ plotargs$degs <- markers
279
+ plotargs$outprefix <- file.path(info$prefix, slugify(plotname))
280
+ do_call(VizDEGs, plotargs)
281
+ reporter$add2(
282
+ list(
283
+ name = plotname,
284
+ contents = list(reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code))
285
+ ),
286
+ hs = c(info$section, info$name),
287
+ ui = "tabs"
288
+ )
289
+ }
290
+ }
291
+ for (ident in all_idents) {
292
+ log$info(" {case$group.by}: {ident} ...")
293
+ ident_markers <- markers[markers[[case$group.by]] == ident, , drop = TRUE]
294
+ casename <- paste0(name, "::", ifelse(case$prefix_group, paste0(case$group.by, " - ", ident), ident))
295
+ info <- case_info(casename, outdir, create = TRUE)
615
296
 
616
- sections <<- union(sections, info$section)
617
- if (info$section %in% overlapping_sections) {
618
- overlaps[[info$section]] <<- overlaps[[info$section]] %||% list()
619
- overlaps[[info$section]][[info$case]] <<- siggenes %||% character()
297
+ process_markers(ident_markers, info = info, case = case)
298
+ }
299
+ } else {
300
+ info <- case_info(name, outdir, create = TRUE)
301
+ process_markers(markers, info = info, case = case)
620
302
  }
621
-
622
- add_case_report(info, case$sigmarkers, siggenes)
623
303
  }
624
304
 
625
- do_overlap <- function(section) {
626
- log_info("- Dealing with overlapping: {section}...")
627
-
628
- ov_args <- overlapping[[section]]
629
- ov_dir <- file.path(outdir, "OVERLAPPING", section)
630
- dir.create(ov_dir, showWarnings = FALSE, recursive = TRUE)
305
+ sapply(names(cases), run_case)
631
306
 
632
- ov_cases <- overlaps[[section]]
633
- if (length(ov_cases) < 2) {
634
- stop(sprintf(" Not enough cases for overlap: %s", section))
635
- }
307
+ if (length(overlaps) > 0) {
308
+ log$info("Running overlapping cases ...")
636
309
 
637
- if (is.list(ov_args$venn) && length(ov_cases) > 4) {
638
- stop(paste0(" Too many cases (", length(ov_cases)," > 4) for venn plot for section: ", section))
639
- }
640
- if (is.list(ov_args$venn)) {
641
- venn_plot <- file.path(ov_dir, "venn.png")
642
- venn_p <- ggVennDiagram(ov_cases, label_percent_digit = 1) +
643
- scale_fill_distiller(palette = "Reds", direction = 1) +
644
- scale_x_continuous(expand = expansion(mult = .2))
645
- ov_args$venn$devpars$file <- venn_plot
646
- do.call(png, ov_args$venn$devpars)
647
- print(venn_p)
648
- dev.off()
649
-
650
- venn_plot_pdf <- file.path(ov_dir, "venn.pdf")
651
- pdf(
652
- venn_plot_pdf,
653
- width = ov_args$venn$devpars$width / ov_args$venn$devpars$res,
654
- height = ov_args$venn$devpars$height / ov_args$venn$devpars$res)
655
- print(venn_p)
656
- dev.off()
657
- }
658
-
659
- df_markers <- fromList(ov_cases)
660
- # A B MARKERS
661
- # 1 0 G1
662
- # 1 0 G2
663
- # 0 1 G3
664
- # 0 1 G4
665
- # 1 1 G5
666
- df_markers$MARKERS = Reduce(union, ov_cases)
667
- df_markers = df_markers %>%
668
- group_by(across(-MARKERS)) %>%
669
- summarise(MARKERS = paste0(MARKERS, collapse = ","), .groups = "drop")
670
-
671
- write.table(
672
- df_markers,
673
- file.path(ov_dir, "markers.txt"),
674
- sep = "\t",
675
- row.names = FALSE,
676
- col.names = TRUE,
677
- quote = FALSE
678
- )
310
+ run_overlap <- function(ovname) {
311
+ ov <- overlaps[[ovname]]
312
+ ov$sigmarkers <- ov$sigmarkers %||% sigmarkers
313
+ log$info("- Overlapping case: {ovname} ...")
314
+ markers <- lapply(ov$cases, function(case) {
315
+ case_markers[[case]] %>% filter(!!parse_expr(ov$sigmarkers)) %>%
316
+ pull("gene") %>% unique()
317
+ })
318
+ names(markers) <- ov$cases
319
+ info <- case_info(paste0("OVERLAPPING::", ovname), outdir, create = TRUE)
320
+
321
+ if (ov$venn$enabled) {
322
+ venn <- extract_vars(ov$venn, "enabled", "more_formats", "save_code", "devpars")
323
+ venn$data <- markers
324
+ venn$in_form <- "list"
325
+ prefix <- file.path(info$prefix, "venn")
326
+ p <- do_call(gglogger::register(VennDiagram), venn)
327
+ save_plot(p, prefix, devpars, formats = c("png", more_formats))
328
+ if (save_code) {
329
+ save_plotcode(
330
+ p, prefix,
331
+ c("library(plotthis)", "load('data.RData')", "invisible(list2env(venn, .GlobalEnv))"),
332
+ "venn",
333
+ auto_data_setup = FALSE)
334
+ }
679
335
 
680
- if (is.list(ov_args$upset)) {
681
- upset_plot <- file.path(ov_dir, "upset.png")
682
- if (nrow(df_markers) == 0) {
683
- upset_p <- ggplot() +
684
- theme_void() +
685
- ggtitle("No overlapping markers found") +
686
- # center the title, and make it red
687
- theme(plot.title = element_text(hjust = 0.5, color = "red"))
688
- ov_args$upset$devpars <- list(
689
- res = 100, height = 42, width = 400
336
+ reporter$add2(
337
+ list(
338
+ name = "Venn Diagram",
339
+ contents = list(reporter$image(prefix, more_formats, save_code))
340
+ ),
341
+ hs = c(info$section, info$name),
342
+ ui = "tabs"
690
343
  )
691
- } else {
692
- upset_p <- upset(fromList(ov_cases))
693
344
  }
694
- ov_args$upset$devpars$file <- upset_plot
695
- do.call(png, ov_args$upset$devpars)
696
- print(upset_p)
697
- dev.off()
698
-
699
- upset_plot_pdf <- file.path(ov_dir, "upset.pdf")
700
- pdf(
701
- upset_plot_pdf,
702
- width = ov_args$upset$devpars$width / ov_args$upset$devpars$res,
703
- height = ov_args$upset$devpars$height / ov_args$upset$devpars$res)
704
- print(upset_p)
705
- dev.off()
706
- }
707
345
 
708
- add_report(
709
- list(
710
- title = "Venn Diagram",
711
- ui = "flat",
712
- contents = list(
713
- list(
714
- kind = "img",
715
- src = file.path(ov_dir, "venn.png"),
716
- download = file.path(ov_dir, "venn.pdf")
717
- )
718
- )
719
- ),
720
- list(
721
- title = "UpSet Plot",
722
- ui = "flat",
723
- contents = list(
724
- list(
725
- kind = "img",
726
- src = file.path(ov_dir, "upset.png"),
727
- download = file.path(ov_dir, "upset.pdf")
728
- )
729
- )
730
- ),
731
- list(
732
- title = "Marker Table",
733
- ui = "flat",
734
- contents = list(
346
+ if (ov$upset$enabled) {
347
+ upset <- extract_vars(ov$upset, "enabled", "more_formats", "save_code", "devpars")
348
+ upset$data <- markers
349
+ upset$in_form <- "list"
350
+ prefix <- file.path(info$prefix, "upset")
351
+ p <- do_call(gglogger::register(UpsetPlot), upset)
352
+ save_plot(p, prefix, devpars, formats = c("png", more_formats))
353
+ if (save_code) {
354
+ save_plotcode(
355
+ p, prefix,
356
+ c("library(plotthis)", "load('data.RData')", "invisible(list2env(upset, .GlobalEnv))"),
357
+ "upset",
358
+ auto_data_setup = FALSE)
359
+ }
360
+
361
+ reporter$add2(
735
362
  list(
736
- kind = "table",
737
- data = list(nrows = 100),
738
- src = file.path(ov_dir, "markers.txt")
739
- )
363
+ name = "UpSet Plot",
364
+ contents = list(reporter$image(prefix, more_formats, save_code))
365
+ ),
366
+ hs = c(info$section, info$name),
367
+ ui = "tabs"
740
368
  )
741
- ),
742
- h1 = "Overlapping Markers",
743
- h2 = section,
744
- ui = "tabs"
745
- )
746
- }
369
+ }
747
370
 
748
- sapply(sort(names(cases)), do_case)
371
+ }
749
372
 
750
- unhit_overlaps <- setdiff(overlapping_sections, names(overlaps))
751
- if (length(unhit_overlaps) > 0) {
752
- log_warn(paste0("- No sections found for overlapping analysis: ", paste(unhit_overlaps, collapse = ", ")))
753
- log_warn(" Available sections: ", paste(sections, collapse = ", "))
373
+ sapply(names(overlaps), run_overlap)
754
374
  }
755
- sapply(sort(names(overlaps)), do_overlap)
756
375
 
757
- save_report(joboutdir)
376
+ reporter$save(joboutdir)