biopipen 0.33.1__py3-none-any.whl → 0.34.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 (150) hide show
  1. biopipen/__init__.py +1 -1
  2. biopipen/core/filters.py +10 -183
  3. biopipen/core/proc.py +5 -3
  4. biopipen/core/testing.py +8 -1
  5. biopipen/ns/bam.py +40 -4
  6. biopipen/ns/cnv.py +1 -1
  7. biopipen/ns/cnvkit.py +1 -1
  8. biopipen/ns/delim.py +1 -1
  9. biopipen/ns/gsea.py +63 -37
  10. biopipen/ns/misc.py +38 -0
  11. biopipen/ns/plot.py +8 -0
  12. biopipen/ns/scrna.py +328 -292
  13. biopipen/ns/scrna_metabolic_landscape.py +207 -366
  14. biopipen/ns/tcr.py +165 -97
  15. biopipen/reports/bam/CNVpytor.svelte +4 -9
  16. biopipen/reports/cnvkit/CNVkitDiagram.svelte +1 -1
  17. biopipen/reports/cnvkit/CNVkitHeatmap.svelte +1 -1
  18. biopipen/reports/cnvkit/CNVkitScatter.svelte +1 -1
  19. biopipen/reports/{delim/SampleInfo.svelte → common.svelte} +2 -3
  20. biopipen/reports/scrna/DimPlots.svelte +1 -1
  21. biopipen/reports/scrna_metabolic_landscape/MetabolicFeatures.svelte +51 -22
  22. biopipen/reports/scrna_metabolic_landscape/MetabolicPathwayActivity.svelte +46 -42
  23. biopipen/reports/scrna_metabolic_landscape/MetabolicPathwayHeterogeneity.svelte +63 -6
  24. biopipen/reports/snp/PlinkCallRate.svelte +2 -2
  25. biopipen/reports/snp/PlinkFreq.svelte +1 -1
  26. biopipen/reports/snp/PlinkHWE.svelte +1 -1
  27. biopipen/reports/snp/PlinkHet.svelte +1 -1
  28. biopipen/reports/snp/PlinkIBD.svelte +1 -1
  29. biopipen/reports/tcr/CDR3AAPhyschem.svelte +1 -1
  30. biopipen/scripts/bam/CNAClinic.R +41 -6
  31. biopipen/scripts/bam/CNVpytor.py +2 -1
  32. biopipen/scripts/bam/ControlFREEC.py +2 -3
  33. biopipen/scripts/bam/SamtoolsView.py +33 -0
  34. biopipen/scripts/cnv/AneuploidyScore.R +25 -13
  35. biopipen/scripts/cnv/AneuploidyScoreSummary.R +218 -163
  36. biopipen/scripts/cnv/TMADScore.R +4 -4
  37. biopipen/scripts/cnv/TMADScoreSummary.R +51 -84
  38. biopipen/scripts/cnvkit/CNVkitGuessBaits.py +3 -3
  39. biopipen/scripts/cnvkit/CNVkitHeatmap.py +3 -3
  40. biopipen/scripts/cnvkit/CNVkitReference.py +3 -3
  41. biopipen/scripts/delim/RowsBinder.R +1 -1
  42. biopipen/scripts/delim/SampleInfo.R +4 -1
  43. biopipen/scripts/gene/GeneNameConversion.R +14 -12
  44. biopipen/scripts/gsea/Enrichr.R +2 -2
  45. biopipen/scripts/gsea/FGSEA.R +184 -50
  46. biopipen/scripts/gsea/PreRank.R +3 -3
  47. biopipen/scripts/misc/Plot.R +80 -0
  48. biopipen/scripts/plot/VennDiagram.R +2 -2
  49. biopipen/scripts/protein/ProdigySummary.R +34 -27
  50. biopipen/scripts/regulatory/MotifAffinityTest.R +11 -9
  51. biopipen/scripts/regulatory/MotifAffinityTest_AtSNP.R +5 -5
  52. biopipen/scripts/regulatory/MotifAffinityTest_MotifBreakR.R +4 -4
  53. biopipen/scripts/regulatory/VariantMotifPlot.R +10 -8
  54. biopipen/scripts/regulatory/motifs-common.R +10 -9
  55. biopipen/scripts/rnaseq/Simulation-ESCO.R +14 -11
  56. biopipen/scripts/rnaseq/Simulation-RUVcorr.R +7 -4
  57. biopipen/scripts/rnaseq/Simulation.R +0 -2
  58. biopipen/scripts/rnaseq/UnitConversion.R +6 -5
  59. biopipen/scripts/scrna/AnnData2Seurat.R +25 -73
  60. biopipen/scripts/scrna/CellCellCommunication.py +1 -1
  61. biopipen/scripts/scrna/CellCellCommunicationPlots.R +51 -168
  62. biopipen/scripts/scrna/CellTypeAnnotation-celltypist.R +99 -150
  63. biopipen/scripts/scrna/CellTypeAnnotation-direct.R +11 -9
  64. biopipen/scripts/scrna/CellTypeAnnotation-hitype.R +12 -9
  65. biopipen/scripts/scrna/CellTypeAnnotation-sccatch.R +14 -11
  66. biopipen/scripts/scrna/CellTypeAnnotation-sctype.R +19 -16
  67. biopipen/scripts/scrna/CellTypeAnnotation.R +10 -2
  68. biopipen/scripts/scrna/CellsDistribution.R +1 -1
  69. biopipen/scripts/scrna/ExprImputation-alra.R +87 -11
  70. biopipen/scripts/scrna/ExprImputation-rmagic.R +247 -21
  71. biopipen/scripts/scrna/ExprImputation-scimpute.R +8 -5
  72. biopipen/scripts/scrna/MarkersFinder.R +481 -215
  73. biopipen/scripts/scrna/MetaMarkers.R +3 -3
  74. biopipen/scripts/scrna/ModuleScoreCalculator.R +14 -13
  75. biopipen/scripts/scrna/RadarPlots.R +1 -1
  76. biopipen/scripts/scrna/ScFGSEA.R +231 -76
  77. biopipen/scripts/scrna/ScSimulation.R +11 -10
  78. biopipen/scripts/scrna/ScVelo.py +605 -0
  79. biopipen/scripts/scrna/Seurat2AnnData.R +2 -3
  80. biopipen/scripts/scrna/SeuratClusterStats-clustree.R +1 -1
  81. biopipen/scripts/scrna/SeuratClusterStats-features.R +43 -30
  82. biopipen/scripts/scrna/SeuratClusterStats-ngenes.R +56 -65
  83. biopipen/scripts/scrna/SeuratClusterStats-stats.R +4 -4
  84. biopipen/scripts/scrna/SeuratClusterStats.R +9 -6
  85. biopipen/scripts/scrna/SeuratClustering.R +31 -48
  86. biopipen/scripts/scrna/SeuratLoading.R +2 -2
  87. biopipen/scripts/scrna/SeuratMap2Ref.R +66 -367
  88. biopipen/scripts/scrna/SeuratMetadataMutater.R +5 -7
  89. biopipen/scripts/scrna/SeuratPreparing.R +76 -24
  90. biopipen/scripts/scrna/SeuratSubClustering.R +46 -185
  91. biopipen/scripts/scrna/{SlingShot.R → Slingshot.R} +12 -16
  92. biopipen/scripts/scrna/Subset10X.R +2 -2
  93. biopipen/scripts/scrna/TopExpressingGenes.R +144 -185
  94. biopipen/scripts/scrna/celltypist-wrapper.py +6 -4
  95. biopipen/scripts/scrna/seurat_anndata_conversion.py +81 -0
  96. biopipen/scripts/scrna_metabolic_landscape/MetabolicFeatures.R +429 -123
  97. biopipen/scripts/scrna_metabolic_landscape/MetabolicPathwayActivity.R +346 -245
  98. biopipen/scripts/scrna_metabolic_landscape/MetabolicPathwayHeterogeneity.R +182 -173
  99. biopipen/scripts/snp/MatrixEQTL.R +39 -20
  100. biopipen/scripts/snp/PlinkCallRate.R +43 -34
  101. biopipen/scripts/snp/PlinkFreq.R +34 -41
  102. biopipen/scripts/snp/PlinkHWE.R +23 -18
  103. biopipen/scripts/snp/PlinkHet.R +26 -22
  104. biopipen/scripts/snp/PlinkIBD.R +30 -34
  105. biopipen/scripts/stats/ChowTest.R +9 -8
  106. biopipen/scripts/stats/DiffCoexpr.R +13 -11
  107. biopipen/scripts/stats/LiquidAssoc.R +7 -8
  108. biopipen/scripts/stats/Mediation.R +8 -8
  109. biopipen/scripts/stats/MetaPvalue.R +11 -13
  110. biopipen/scripts/stats/MetaPvalue1.R +6 -5
  111. biopipen/scripts/tcr/CDR3AAPhyschem.R +105 -164
  112. biopipen/scripts/tcr/ClonalStats.R +6 -5
  113. biopipen/scripts/tcr/CloneResidency.R +3 -3
  114. biopipen/scripts/tcr/CloneSizeQQPlot.R +2 -2
  115. biopipen/scripts/tcr/Immunarch2VDJtools.R +2 -2
  116. biopipen/scripts/tcr/ImmunarchFilter.R +3 -3
  117. biopipen/scripts/tcr/ImmunarchLoading.R +5 -5
  118. biopipen/scripts/tcr/ScRepCombiningExpression.R +39 -0
  119. biopipen/scripts/tcr/ScRepLoading.R +114 -92
  120. biopipen/scripts/tcr/TCRClusterStats.R +2 -2
  121. biopipen/scripts/tcr/TCRClustering.R +86 -97
  122. biopipen/scripts/tcr/TESSA.R +65 -115
  123. biopipen/scripts/tcr/VJUsage.R +5 -5
  124. biopipen/scripts/vcf/TruvariBenchSummary.R +15 -11
  125. biopipen/utils/common_docstrs.py +66 -63
  126. biopipen/utils/reporter.py +177 -0
  127. {biopipen-0.33.1.dist-info → biopipen-0.34.1.dist-info}/METADATA +2 -1
  128. {biopipen-0.33.1.dist-info → biopipen-0.34.1.dist-info}/RECORD +130 -145
  129. {biopipen-0.33.1.dist-info → biopipen-0.34.1.dist-info}/WHEEL +1 -1
  130. biopipen/reports/scrna/CellCellCommunicationPlots.svelte +0 -14
  131. biopipen/reports/scrna/ScFGSEA.svelte +0 -16
  132. biopipen/reports/scrna/SeuratClusterStats.svelte +0 -16
  133. biopipen/reports/scrna/SeuratMap2Ref.svelte +0 -37
  134. biopipen/reports/scrna/SeuratPreparing.svelte +0 -15
  135. biopipen/reports/scrna_metabolic_landscape/MetabolicFeaturesIntraSubset.svelte +0 -28
  136. biopipen/reports/utils/gsea.liq +0 -110
  137. biopipen/scripts/scrna/CellTypeAnnotation-common.R +0 -10
  138. biopipen/scripts/scrna/SeuratClustering-common.R +0 -213
  139. biopipen/scripts/scrna_metabolic_landscape/MetabolicFeaturesIntraSubset.R +0 -193
  140. biopipen/utils/caching.R +0 -44
  141. biopipen/utils/gene.R +0 -95
  142. biopipen/utils/gsea.R +0 -329
  143. biopipen/utils/io.R +0 -20
  144. biopipen/utils/misc.R +0 -602
  145. biopipen/utils/mutate_helpers.R +0 -581
  146. biopipen/utils/plot.R +0 -209
  147. biopipen/utils/repr.R +0 -146
  148. biopipen/utils/rnaseq.R +0 -48
  149. biopipen/utils/single_cell.R +0 -207
  150. {biopipen-0.33.1.dist-info → biopipen-0.34.1.dist-info}/entry_points.txt +0 -0
@@ -7,34 +7,35 @@ library(biopipen.utils)
7
7
  log <- get_logger()
8
8
  reporter <- get_reporter()
9
9
 
10
- srtfile <- {{ in.srtobj | quote }}
11
- outdir <- {{ out.outdir | quote }}
12
- joboutdir <- {{ job.outdir | quote }}
10
+ srtfile <- {{ in.srtobj | r }}
11
+ outdir <- {{ out.outdir | r }}
12
+ joboutdir <- {{ job.outdir | r }}
13
+
13
14
  ncores <- {{ envs.ncores | int }}
14
15
  mutaters <- {{ envs.mutaters | r }}
16
+ group.by <- {{ envs["group-by"] | r }}
15
17
  ident.1 <- {{ envs["ident-1"] | r }}
16
18
  ident.2 <- {{ envs["ident-2"] | r }}
17
- group.by <- {{ envs["group-by"] | r }}
18
19
  each <- {{ envs.each | r }}
19
- prefix_each <- {{ envs.prefix_each | r }}
20
- prefix_group <- {{ envs.prefix_group | r }}
21
- assay <- {{ envs.assay | r }}
22
- subset <- {{ envs.subset | r }}
23
- error <- {{ envs.error | r }}
24
- site <- {{ envs.site | r }}
25
- rest <- {{ envs.rest | r: todot="-" }}
26
20
  dbs <- {{ envs.dbs | r }}
27
21
  sigmarkers <- {{ envs.sigmarkers | r }}
22
+ enrich_style <- {{ envs.enrich_style | r }}
23
+ assay <- {{ envs.assay | r }}
24
+ error <- {{ envs.error | r }}
25
+ subset <- {{ envs.subset | r }}
28
26
  cache <- {{ envs.cache | r }}
27
+ rest <- {{ envs.rest | r: todot="-" }}
29
28
  allmarker_plots_defaults <- {{ envs.allmarker_plots_defaults | r }}
30
29
  allmarker_plots <- {{ envs.allmarker_plots | r }}
30
+ allenrich_plots_defaults <- {{ envs.allenrich_plots_defaults | r }}
31
+ allenrich_plots <- {{ envs.allenrich_plots | r }}
31
32
  marker_plots_defaults <- {{ envs.marker_plots_defaults | r }}
32
33
  marker_plots <- {{ envs.marker_plots | r }}
33
34
  enrich_plots_defaults <- {{ envs.enrich_plots_defaults | r }}
34
35
  enrich_plots <- {{ envs.enrich_plots | r }}
35
- cases <- {{ envs.cases | r: todot="-", skip=1 }}
36
36
  overlaps_defaults <- {{ envs.overlaps_defaults | r }}
37
37
  overlaps <- {{ envs.overlaps | r }}
38
+ cases <- {{ envs.cases | r: todot="-", skip=1 }}
38
39
 
39
40
  if (isTRUE(cache)) { cache <- joboutdir }
40
41
 
@@ -45,7 +46,11 @@ if (ncores > 1) {
45
46
  }
46
47
 
47
48
  log$info("Reading Seurat object ...")
48
- srtobj <- readRDS(srtfile)
49
+ srtobj <- read_obj(srtfile)
50
+ if (!"Identity" %in% colnames(srtobj@meta.data)) {
51
+ srtobj@meta.data$Identity <- Idents(srtobj)
52
+ }
53
+
49
54
 
50
55
  if (!is.null(mutaters) && length(mutaters) > 0) {
51
56
  log$info("Mutating meta data ...")
@@ -53,22 +58,43 @@ if (!is.null(mutaters) && length(mutaters) > 0) {
53
58
  mutate(!!!lapply(mutaters, parse_expr))
54
59
  }
55
60
 
61
+ allmarker_plots <- lapply(allmarker_plots, function(x) {
62
+ list_update(allmarker_plots_defaults, x)
63
+ })
64
+ allenrich_plots <- lapply(allenrich_plots, function(x) {
65
+ list_update(allenrich_plots_defaults, x)
66
+ })
67
+ marker_plots <- lapply(marker_plots, function(x) {
68
+ list_update(marker_plots_defaults, x)
69
+ })
70
+ enrich_plots <- lapply(enrich_plots, function(x) {
71
+ list_update(enrich_plots_defaults, x)
72
+ })
73
+ overlaps <- lapply(overlaps, function(x) {
74
+ list_update(overlaps_defaults, x)
75
+ })
76
+
56
77
  defaults <- list(
78
+ group.by = group.by,
57
79
  ident.1 = ident.1,
58
80
  ident.2 = ident.2,
59
- group.by = group.by,
60
- each = each,
61
- prefix_each = prefix_each,
62
- prefix_group = prefix_group,
63
81
  dbs = dbs,
82
+ sigmarkers = sigmarkers,
83
+ enrich_style = enrich_style,
64
84
  assay = assay %||% DefaultAssay(srtobj),
65
- subset = subset,
85
+ each = each,
66
86
  error = error,
67
- site = site,
68
- sigmarkers = sigmarkers,
87
+ subset = subset,
88
+ allmarker_plots_defaults = allmarker_plots_defaults,
69
89
  allmarker_plots = allmarker_plots,
90
+ allenrich_plots_defaults = allenrich_plots_defaults,
91
+ allenrich_plots = allenrich_plots,
92
+ marker_plots_defaults = marker_plots_defaults,
70
93
  marker_plots = marker_plots,
94
+ enrich_plots_defaults = enrich_plots_defaults,
71
95
  enrich_plots = enrich_plots,
96
+ overlaps_defaults = overlaps_defaults,
97
+ overlaps = overlaps,
72
98
  cache = cache,
73
99
  rest = rest
74
100
  )
@@ -77,107 +103,171 @@ log$info("Expanding cases ...")
77
103
 
78
104
  post_casing <- function(name, case) {
79
105
  outcases <- list()
80
- no_each <- is.null(case$each) || is.na(case$each) || nchar(case$each) == 0
81
106
 
82
- if (no_each) {
107
+ case$group.by <- case$group.by %||% "Identity"
108
+
109
+ if (is.null(case$each) || is.na(case$each) || nchar(case$each) == 0 || isFALSE(each)) {
83
110
  # single cases, no need to expand
111
+ if (length(case$ident.1) > 0 && length(case$overlaps) > 0) {
112
+ stop("Cannot perform 'overlaps' with a single comparison (ident-1 is set) in case '", name, "'")
113
+ }
114
+ if (length(case$ident.1) > 0 && length(case$allmarker_plots) > 0) {
115
+ stop("Cannot perform 'allmarker_plots' with a single comparison (ident-1 is set) in case '", name, "'")
116
+ }
117
+ if (length(case$ident.1) > 0 && length(case$allenrich_plots) > 0) {
118
+ stop("Cannot perform 'allenrich_plots' with a single comparison (ident-1 is set) in case '", name, "'")
119
+ }
120
+
84
121
  case$allmarker_plots <- lapply(
85
122
  case$allmarker_plots,
86
- function(x) { list_update(allmarker_plots_defaults, x) }
123
+ function(x) { list_update(case$allmarker_plots_defaults, x) }
87
124
  )
125
+ case$allmarker_plots_defaults <- NULL
126
+
127
+ case$allenrich_plots <- lapply(
128
+ case$allenrich_plots,
129
+ function(x) { list_update(case$allenrich_plots_defaults, x) }
130
+ )
131
+ case$allenrich_plots_defaults <- NULL
132
+
88
133
  case$marker_plots <- lapply(
89
134
  case$marker_plots,
90
- function(x) { list_update(marker_plots_defaults, x) }
135
+ function(x) { list_update(case$marker_plots_defaults, x) }
91
136
  )
137
+ case$marker_plots_defaults <- NULL
138
+
92
139
  case$enrich_plots <- lapply(
93
140
  case$enrich_plots,
94
- function(x) { list_update(enrich_plots_defaults, x) }
141
+ function(x) { list_update(case$enrich_plots_defaults, x) }
142
+ )
143
+ case$enrich_plots_defaults <- NULL
144
+
145
+ case$overlaps <- lapply(
146
+ case$overlaps,
147
+ function(x) { list_update(case$overlaps_defaults, x) }
95
148
  )
149
+ case$overlaps_defaults <- NULL
150
+
96
151
  outcases[[name]] <- case
97
152
  } else { # !no_each
98
- if (!is.null(case$subset)) {
99
- sobj <- srtobj %>% filter(!!parse_expr(case$subset))
153
+ eachs <- if (!is.null(case$subset)) {
154
+ srtobj@meta.data %>%
155
+ filter(!!parse_expr(case$subset)) %>%
156
+ pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
100
157
  } else {
101
- sobj <- srtobj
158
+ srtobj@meta.data %>%
159
+ pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
160
+ }
161
+ if (length(case$overlaps) > 0 && is.null(case$ident.1)) {
162
+ stop("Cannot perform 'overlaps' analysis with 'each' and without 'ident.1' in case '", name, "'")
163
+ }
164
+
165
+ if (length(cases) == 0 && name == "Marker Discovery") {
166
+ name <- case$each
102
167
  }
103
168
 
104
- eachs <- sobj@meta.data %>% pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
105
- case_1 <- case
106
169
  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)
111
- } else {
112
- key <- paste0(name, ": ", each_name)
113
- }
170
+ newname <- paste0(name, " - ", each)
171
+ newcase <- case
172
+
173
+ newcase$original_case <- name
174
+ newcase$each_name <- case$each
175
+ newcase$each <- each
176
+
114
177
  if (!is.null(case$subset)) {
115
- case_1$subset <- paste0(case$subset, " & `", case_1$each, "` == '", each, "'")
178
+ newcase$subset <- paste0(case$subset, " & ", bQuote(case$each), " == '", each, "'")
116
179
  } else {
117
- case_1$subset <- paste0("`", case_1$each, "` == '", each, "'")
180
+ newcase$subset <- paste0(bQuote(case$each), " == '", each, "'")
118
181
  }
119
- case_1$allmarker_plots <- lapply(
120
- case_1$allmarker_plots,
121
- function(x) { list_update(allmarker_plots_defaults, x) }
182
+
183
+ newcase$marker_plots <- lapply(
184
+ case$marker_plots,
185
+ function(x) { list_update(case$marker_plots_defaults, x) }
186
+ )
187
+ newcase$marker_plots_defaults <- NULL
188
+
189
+ newcase$enrich_plots <- lapply(
190
+ case$enrich_plots,
191
+ function(x) { list_update(case$enrich_plots_defaults, x) }
192
+ )
193
+ newcase$enrich_plots_defaults <- NULL
194
+
195
+ # Will be processed by the case itself, which collects the markers
196
+ newcase$allmarker_plots <- NULL
197
+ newcase$allmarker_plots_defaults <- NULL
198
+ newcase$allenrich_plots <- NULL
199
+ newcase$allenrich_plots_defaults <- NULL
200
+ newcase$overlaps <- NULL
201
+ newcase$overlaps_defaults <- NULL
202
+
203
+ outcases[[newname]] <- newcase
204
+ }
205
+
206
+ if (length(case$overlaps) > 0 || length(case$allmarker_plots) > 0 || length(case$allenrich_plots) > 0) {
207
+ ovcase <- case
208
+
209
+ ovcase$markers <- list()
210
+ ovcase$allmarker_plots <- lapply(
211
+ ovcase$allmarker_plots,
212
+ function(x) { list_update(ovcase$allmarker_plots_defaults, x) }
122
213
  )
123
- case_1$marker_plots <- lapply(
124
- case_1$marker_plots,
125
- function(x) { list_update(marker_plots_defaults, x) }
214
+ ovcase$allmarker_plots_defaults <- NULL
215
+
216
+ ovcase$enriches <- list()
217
+ ovcase$allenrich_plots <- lapply(
218
+ ovcase$allenrich_plots,
219
+ function(x) { list_update(ovcase$allenrich_plots_defaults, x) }
126
220
  )
127
- case_1$enrich_plots <- lapply(
128
- case_1$enrich_plots,
129
- function(x) { list_update(enrich_plots_defaults, x) }
221
+ ovcase$allenrich_plots_defaults <- NULL
222
+
223
+ ovcase$overlaps <- lapply(
224
+ ovcase$overlaps,
225
+ function(x) { list_update(ovcase$overlaps_defaults, x) }
130
226
  )
131
- outcases[[key]] <- case_1
227
+ ovcase$overlaps_defaults <- NULL
228
+ outcases[[name]] <- ovcase
132
229
  }
133
230
  }
134
231
  outcases
135
232
  }
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, "'"))
149
- }
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
159
- }
160
- }
161
- }
233
+ cases <- expand_cases(cases, defaults, post_casing, default_case = "Marker Discovery")
162
234
 
163
235
  log$info("Running cases ...")
164
236
 
165
237
  process_markers <- function(markers, info, case) {
238
+ ## Attributes lost
239
+ # markers <- markers %>%
240
+ # mutate(gene = as.character(gene)) %>%
241
+ # arrange(p_val_adj, desc(abs(avg_log2FC)))
242
+ markers$gene <- as.character(markers$gene)
243
+ markers <- markers[order(markers$p_val_adj, -abs(markers$avg_log2FC)), ]
244
+
166
245
  # Save markers
167
246
  write.table(markers, file.path(info$prefix, "markers.tsv"), sep = "\t", quote = FALSE, row.names = FALSE)
247
+
248
+ sigmarkers <- markers %>% filter(!!parse_expr(case$sigmarkers))
249
+ write.table(sigmarkers, file.path(info$prefix, "sigmarkers.tsv"), sep = "\t", quote = FALSE, row.names = FALSE)
168
250
  reporter$add2(
169
251
  list(
170
252
  name = "Table",
171
- contents = list(list(kind = "table", src = file.path(info$prefix, "markers.tsv"), data = list(nrows = 100)))
253
+ contents = list(
254
+ list(kind = "descr", content = paste0(
255
+ "Showing top 100 markers ordered by p_val_adj ascendingly, then abs(avg_log2FC) descendingly. ",
256
+ "Use 'Download the entire data' button to download all significant markers by '",
257
+ html_escape(case$sigmarkers), "'."
258
+ )),
259
+ list(kind = "table", src = file.path(info$prefix, "sigmarkers.tsv"), data = list(nrows = 100))
260
+ )
172
261
  ),
173
262
  hs = c(info$section, info$name),
174
- hs2 = "Markers",
263
+ hs2 = ifelse(is.null(case$ident), "Markers", paste0("Markers (", case$ident, ")")),
175
264
  ui = "tabs"
176
265
  )
177
266
 
178
267
  for (plotname in names(case$marker_plots)) {
179
268
  plotargs <- case$marker_plots[[plotname]]
180
269
  plotargs$degs <- markers
270
+ rownames(plotargs$degs) <- make.unique(markers$gene)
181
271
  plotargs$outprefix <- file.path(info$prefix, paste0("markers.", slugify(plotname)))
182
272
  do_call(VizDEGs, plotargs)
183
273
  reporter$add2(
@@ -185,192 +275,368 @@ process_markers <- function(markers, info, case) {
185
275
  name = plotname,
186
276
  contents = list(reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code))),
187
277
  hs = c(info$section, info$name),
188
- hs2 = "Markers",
278
+ hs2 = ifelse(is.null(case$ident), "Markers", paste0("Markers (", case$ident, ")")),
189
279
  ui = "tabs"
190
280
  )
191
281
  }
192
282
 
193
283
  # 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(
201
- list(
202
- name = "Table",
203
- contents = list(list(kind = "table", src = file.path(info$prefix, "enrich.tsv"), data = list(nrows = 100)))
204
- ),
205
- hs = c(info$section, info$name),
206
- hs2 = "Enrichment Analysis",
207
- ui = "tabs"
284
+ significant_markers <- unique(sigmarkers$gene)
285
+ empty <- if (case$enrich_style == "enrichr") {
286
+ data.frame(
287
+ Database = character(0),
288
+ Term = character(0),
289
+ Overlap = character(0),
290
+ P.value = numeric(0),
291
+ Adjusted.P.value = numeric(0),
292
+ Odds.Ratio = numeric(0),
293
+ Combined.Score = numeric(0),
294
+ Genes = character(0),
295
+ Rank = numeric(0)
208
296
  )
297
+ } else { # clusterProfiler
298
+ data.frame(
299
+ ID = character(0),
300
+ Description = character(0),
301
+ GeneRatio = character(0),
302
+ BgRatio = character(0),
303
+ Count = integer(0),
304
+ pvalue = numeric(0),
305
+ p.adjust = numeric(0),
306
+ qvalue = numeric(0),
307
+ geneID = character(0),
308
+ Database = character(0)
309
+ )
310
+ }
209
311
 
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)))
218
-
219
- do_call(VizEnrich, plotargs)
220
-
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
- }
230
- }
231
- }, error = function(e) {
312
+ if (length(significant_markers) < 5) {
232
313
  if (case$error) {
233
- stop("Error: ", e$message)
314
+ stop("Error: Not enough significant markers with '", case$sigmarkers, "' in case '", info$name, "' found (< 5) for enrichment analysis.")
234
315
  } else {
235
- log$warn(" ! Error: {e$message}")
316
+ message <- paste0("Not enough significant markers with '", case$sigmarkers, "' found (< 5) for enrichment analysis.")
317
+ log$warn(" ! Error: {message}")
236
318
  reporter$add2(
237
319
  list(
238
320
  name = "Warning",
239
- contents = list(list(kind = "error", content = e$message, kind_ = "warning"))),
321
+ contents = list(list(kind = "error", content = message, kind_ = "warning"))),
240
322
  hs = c(info$section, info$name),
241
323
  hs2 = "Enrichment Analysis",
242
324
  ui = "tabs"
243
325
  )
244
326
  }
245
- })
246
- }
327
+ return(empty)
328
+ } else {
329
+ tryCatch({
330
+ enrich <- RunEnrichment(
331
+ significant_markers,
332
+ dbs = case$dbs, style = case$enrich_style)
247
333
 
248
- run_case <- function(name) {
249
- case <- cases[[name]]
250
- log$info("- Case: {name} ...")
251
-
252
- args <- case$rest %||% list()
253
- args$object <- srtobj
254
- args$group.by <- case$group.by
255
- args$ident.1 <- case$ident.1
256
- args$ident.2 <- case$ident.2
257
- args$cache <- case$cache
258
- args$assay <- case$assay
259
- args$error <- case$error
260
- args$subset <- case$subset
261
-
262
- markers <- do_call(RunSeuratDEAnalysis, args)
263
- if (isTRUE(case_markers[[name]])) {
264
- case_markers[[name]] <<- markers
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)
334
+ write.table(enrich, file.path(info$prefix, "enrich.tsv"), sep = "\t", quote = FALSE, row.names = FALSE)
335
+ reporter$add2(
336
+ list(
337
+ name = "Table",
338
+ contents = list(list(kind = "table", src = file.path(info$prefix, "enrich.tsv"), data = list(nrows = 100)))
339
+ ),
340
+ hs = c(info$section, info$name),
341
+ hs2 = "Enrichment Analysis",
342
+ ui = "tabs"
343
+ )
344
+
345
+ # Visualize enriched terms
346
+ if (length(case$enrich_plots) > 0) {
347
+ for (db in case$dbs) {
348
+ plots <- list()
349
+ for (plotname in names(case$enrich_plots)) {
350
+ plotargs <- case$enrich_plots[[plotname]]
351
+ plotargs$data <- enrich[enrich$Database == db, , drop = FALSE]
352
+
353
+ p <- do_call(VizEnrichment, plotargs)
354
+
355
+ if (plotargs$plot_type == "bar") {
356
+ attr(p, "height") <- attr(p, "height") / 1.5
357
+ }
358
+ outprefix <- file.path(info$prefix, paste0("enrich.", slugify(db), ".", slugify(plotname)))
359
+ save_plot(p, outprefix, plotargs$devpars, formats = "png")
360
+ plots[[length(plots) + 1]] <- reporter$image(outprefix, c(), FALSE)
361
+ }
362
+ reporter$add2(
363
+ list(name = db, contents = plots),
364
+ hs = c(info$section, info$name),
365
+ hs2 = "Enrichment Analysis",
366
+ ui = "tabs"
367
+ )
368
+ }
369
+ }
370
+ return(enrich)
371
+ }, error = function(e) {
372
+ if (case$error) {
373
+ stop("Error: ", e$message)
374
+ } else {
375
+ log$warn(" ! Error: {e$message}")
281
376
  reporter$add2(
282
377
  list(
283
- name = plotname,
284
- contents = list(reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code))
285
- ),
378
+ name = "Warning",
379
+ contents = list(list(kind = "error", content = e$message, kind_ = "warning"))),
286
380
  hs = c(info$section, info$name),
381
+ hs2 = "Enrichment Analysis",
287
382
  ui = "tabs"
288
383
  )
289
384
  }
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)
385
+ return(empty)
386
+ })
387
+ }
388
+ }
389
+
390
+ process_allmarkers <- function(markers, plotcases, casename, groupname) {
391
+ name <- paste0(casename, "::", paste0(groupname, " (All Markers)"))
392
+ info <- case_info(name, outdir, create = TRUE)
393
+
394
+ for (plotname in names(plotcases)) {
395
+ plotargs <- plotcases[[plotname]]
396
+ plotargs$degs <- markers
397
+ plotargs$outprefix <- file.path(info$prefix, slugify(plotname))
398
+ do_call(VizDEGs, plotargs)
399
+ reporter$add2(
400
+ list(
401
+ name = plotname,
402
+ contents = list(reporter$image(plotargs$outprefix, plotargs$more_formats, plotargs$save_code))
403
+ ),
404
+ hs = c(info$section, info$name),
405
+ ui = "tabs"
406
+ )
407
+ }
408
+ }
409
+
410
+ process_allenriches <- function(enriches, plotcases, casename, groupname) {
411
+ name <- paste0(casename, "::", paste0(groupname, " (All Enrichments)"))
412
+ info <- case_info(name, outdir, create = TRUE)
413
+ dbs <- unique(as.character(enriches$Database))
414
+
415
+ for (db in dbs) {
416
+ plots <- list()
417
+ for (plotname in names(plotcases)) {
418
+ plotargs <- plotcases[[plotname]]
419
+ plotargs <- extract_vars(plotargs, "devpars")
420
+ plotargs$data <- enriches[enriches$Database == db, , drop = FALSE]
421
+ if (plotargs$plot_type == "heatmap") {
422
+ plotargs$group_by <- groupname
423
+ plotargs$show_row_names = plotargs$show_row_names %||% TRUE
424
+ plotargs$show_column_names = plotargs$show_column_names %||% TRUE
425
+ }
426
+
427
+ p <- do_call(VizEnrichment, plotargs)
296
428
 
297
- process_markers(ident_markers, info = info, case = case)
429
+ if (plotargs$plot_type == "bar") {
430
+ attr(p, "height") <- attr(p, "height") / 1.5
431
+ }
432
+ outprefix <- file.path(info$prefix, paste0("allenrich.", slugify(db), ".", slugify(plotname)))
433
+ save_plot(p, outprefix, devpars, formats = "png")
434
+ plots[[length(plots) + 1]] <- reporter$image(outprefix, c(), FALSE)
298
435
  }
299
- } else {
300
- info <- case_info(name, outdir, create = TRUE)
301
- process_markers(markers, info = info, case = case)
436
+ reporter$add2(
437
+ list(name = db, contents = plots),
438
+ hs = c(info$section, info$name),
439
+ hs2 = plotname,
440
+ ui = "tabs"
441
+ )
302
442
  }
303
443
  }
304
444
 
305
- sapply(names(cases), run_case)
445
+ process_overlaps <- function(markers, ovcases, casename, groupname) {
446
+ name <- paste0(casename, "::", paste0(groupname, ": Overlaps"))
447
+ info <- case_info(name, outdir, create = TRUE)
306
448
 
307
- if (length(overlaps) > 0) {
308
- log$info("Running overlapping cases ...")
449
+ for (plotname in names(ovcases)) {
450
+ args <- extract_vars(
451
+ ovcases[[plotname]],
452
+ sigm = "sigmarkers", "more_formats", "save_code", "devpars", "plot_type",
453
+ allow_nonexisting = TRUE
454
+ )
309
455
 
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)) %>%
456
+ sigm <- sigm %||% sigmarkers
457
+ ugroups <- unique(markers[[groupname]])
458
+ m <- lapply(ugroups, function(g) {
459
+ markers[markers[[groupname]] == g, , drop = FALSE] %>%
460
+ filter(!!parse_expr(sigm)) %>%
316
461
  pull("gene") %>% unique()
317
462
  })
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)
463
+ names(m) <- ugroups
464
+
465
+ if (plot_type == "venn") {
466
+ args$data <- m
467
+ args$in_form <- "list"
468
+ prefix <- file.path(info$prefix, slugify(plotname))
469
+ p <- do_call(gglogger::register(VennDiagram), args)
327
470
  save_plot(p, prefix, devpars, formats = c("png", more_formats))
328
471
  if (save_code) {
329
472
  save_plotcode(
330
473
  p, prefix,
331
- c("library(plotthis)", "load('data.RData')", "invisible(list2env(venn, .GlobalEnv))"),
332
- "venn",
333
- auto_data_setup = FALSE)
474
+ c("library(plotthis)", "load('data.RData')", "invisible(list2env(args, .GlobalEnv))"),
475
+ "args",
476
+ auto_data_setup = FALSE
477
+ )
334
478
  }
335
-
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"
343
- )
344
- }
345
-
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)
479
+ } else {
480
+ args$data <- m
481
+ args$in_form <- "list"
482
+ prefix <- file.path(info$prefix, slugify(plotname))
483
+ p <- do_call(gglogger::register(UpsetPlot), args)
352
484
  save_plot(p, prefix, devpars, formats = c("png", more_formats))
353
485
  if (save_code) {
354
486
  save_plotcode(
355
487
  p, prefix,
356
- c("library(plotthis)", "load('data.RData')", "invisible(list2env(upset, .GlobalEnv))"),
357
- "upset",
358
- auto_data_setup = FALSE)
488
+ c("library(plotthis)", "load('data.RData')", "invisible(list2env(args, .GlobalEnv))"),
489
+ "args",
490
+ auto_data_setup = FALSE
491
+ )
492
+ }
493
+ }
494
+
495
+ reporter$add2(
496
+ list(
497
+ name = plotname,
498
+ contents = list(reporter$image(prefix, more_formats, save_code))
499
+ ),
500
+ hs = c(info$section, info$name),
501
+ ui = "tabs"
502
+ )
503
+ }
504
+ }
505
+
506
+ run_case <- function(name) {
507
+ case <- cases[[name]]
508
+ log$info("Case: {name} ...")
509
+
510
+ case <- extract_vars(
511
+ case,
512
+ "dbs", "sigmarkers", "allmarker_plots", "allenrich_plots", "marker_plots", "enrich_plots",
513
+ "overlaps", "original_case", "markers", "enriches", "each_name", "each", "enrich_style",
514
+ allow_nonexisting = TRUE
515
+ )
516
+
517
+ if (!is.null(markers) || !is.null(enriches)) {
518
+ if (!is.null(markers)) { # It is the overlap/allmarker case
519
+ log$info("- Summarizing markers in subcases (by each: {each}) ...")
520
+ # handle the overlaps / allmarkers analysis here
521
+ if (!is.data.frame(markers)) {
522
+ each_levels <- names(markers)
523
+ markers <- do_call(rbind, lapply(each_levels, function(x) {
524
+ markers_df <- markers[[x]]
525
+ if (nrow(markers_df) > 0) {
526
+ markers_df[[each]] <- x
527
+ } else {
528
+ markers_df[[each]] <- character(0) # Empty case
529
+ }
530
+ markers_df
531
+ }))
532
+ markers[[each]] <- factor(markers[[each]], levels = each_levels)
533
+ }
534
+ # gene, p_val, avg_log2FC, pct.1, pct.2, p_val_adj, diff_pct, <each>
535
+
536
+ if (length(allmarker_plots) > 0) {
537
+ log$info("- Visualizing all markers together ...")
538
+ attr(markers, "object") <- srtobj
539
+ attr(markers, "group.by") <- each
540
+ attr(markers, "ident.1") <- NULL
541
+ attr(markers, "ident.2") <- NULL
542
+ process_allmarkers(markers, allmarker_plots, name, each)
543
+ }
544
+
545
+ if (length(overlaps) > 0) {
546
+ log$info("- Visualizing overlaps between subcases ...")
547
+ process_overlaps(markers, overlaps, name, each)
359
548
  }
360
549
 
361
- reporter$add2(
362
- list(
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"
368
- )
369
550
  }
370
551
 
552
+ if (!is.null(enriches)) {
553
+ log$info("- Summarizing enrichments in subcases (by each: {each}) ...")
554
+ if (!is.data.frame(enriches)) {
555
+ each_levels <- names(enriches)
556
+ enriches <- do_call(rbind, lapply(each_levels, function(x) {
557
+ enrich_df <- enriches[[x]]
558
+ if (nrow(enrich_df) > 0) {
559
+ enrich_df[[each]] <- x
560
+ } else {
561
+ enrich_df[[each]] <- character(0) # Empty case
562
+ }
563
+ enrich_df
564
+ }))
565
+ enriches[[each]] <- factor(enriches[[each]], levels = each_levels)
566
+ }
567
+
568
+ if (length(allenrich_plots) > 0) {
569
+ log$info("- Visualizing all enrichments together ...")
570
+ process_allenriches(enriches, allenrich_plots, name, each)
571
+ }
572
+ }
573
+
574
+ return(invisible())
575
+ }
576
+
577
+ case$object <- srtobj
578
+ markers <- do_call(RunSeuratDEAnalysis, case)
579
+ case$object <- NULL
580
+ gc()
581
+
582
+ if (is.null(case$ident.1)) {
583
+ all_idents <- unique(as.character(markers[[case$group.by]]))
584
+ enriches <- list()
585
+ for (ident in all_idents) {
586
+ log$info("- {case$group.by}: {ident} ...")
587
+ ident_markers <- markers[markers[[case$group.by]] == ident, , drop = TRUE]
588
+ casename <- paste0(name, "::", paste0(case$group.by, ": ", ident))
589
+ info <- case_info(casename, outdir, create = TRUE)
590
+
591
+ attr(ident_markers, "ident.1") <- ident
592
+ enrich <- process_markers(ident_markers, info = info, case = list(
593
+ dbs = dbs,
594
+ sigmarkers = sigmarkers,
595
+ enrich_style = enrich_style,
596
+ marker_plots = marker_plots,
597
+ enrich_plots = enrich_plots,
598
+ error = case$error,
599
+ ident = NULL
600
+ ))
601
+ enriches[[ident]] <- enrich
602
+ }
603
+
604
+ if (length(allmarker_plots) > 0) {
605
+ log$info("- Visualizing all markers together ...")
606
+ process_allmarkers(markers, allmarker_plots, name, case$group.by)
607
+ }
608
+
609
+ if (length(overlaps) > 0) {
610
+ log$info("- Visualizing overlaps between subcases ...")
611
+ process_overlaps(markers, overlaps, name, case$group.by)
612
+ }
613
+
614
+ if (length(allenrich_plots) > 0) {
615
+ log$info("- Visualizing all enrichments together ...")
616
+ process_allenriches(enriches, allenrich_plots, name, case$group.by)
617
+ }
618
+ } else {
619
+ info <- case_info(name, outdir, create = TRUE)
620
+ enrich <- process_markers(markers, info = info, case = list(
621
+ dbs = dbs,
622
+ sigmarkers = sigmarkers,
623
+ enrich_style = enrich_style,
624
+ marker_plots = marker_plots,
625
+ enrich_plots = enrich_plots,
626
+ error = case$error,
627
+ ident = if (is.null(case$ident.2)) case$ident.1 else paste0(case$ident.1, " vs ", case$ident.2)
628
+ ))
629
+
630
+ if (!is.null(original_case) && !is.null(cases[[original_case]])) {
631
+ markers[[each_name]] <- each
632
+ cases[[original_case]]$markers[[each]] <<- markers
633
+ cases[[original_case]]$enriches[[each]] <<- enrich
634
+ }
371
635
  }
372
636
 
373
- sapply(names(overlaps), run_overlap)
637
+ invisible()
374
638
  }
375
639
 
640
+ sapply(names(cases), run_case)
641
+
376
642
  reporter$save(joboutdir)