biopipen 0.21.0__py3-none-any.whl → 0.34.26__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.
Files changed (290) hide show
  1. biopipen/__init__.py +1 -1
  2. biopipen/core/config.toml +28 -0
  3. biopipen/core/filters.py +79 -4
  4. biopipen/core/proc.py +12 -3
  5. biopipen/core/testing.py +75 -3
  6. biopipen/ns/bam.py +148 -6
  7. biopipen/ns/bed.py +75 -0
  8. biopipen/ns/cellranger.py +186 -0
  9. biopipen/ns/cellranger_pipeline.py +126 -0
  10. biopipen/ns/cnv.py +19 -3
  11. biopipen/ns/cnvkit.py +1 -1
  12. biopipen/ns/cnvkit_pipeline.py +20 -12
  13. biopipen/ns/delim.py +34 -35
  14. biopipen/ns/gene.py +68 -23
  15. biopipen/ns/gsea.py +63 -37
  16. biopipen/ns/misc.py +39 -14
  17. biopipen/ns/plot.py +304 -1
  18. biopipen/ns/protein.py +183 -0
  19. biopipen/ns/regulatory.py +290 -0
  20. biopipen/ns/rnaseq.py +142 -5
  21. biopipen/ns/scrna.py +2053 -473
  22. biopipen/ns/scrna_metabolic_landscape.py +228 -382
  23. biopipen/ns/snp.py +659 -0
  24. biopipen/ns/stats.py +484 -0
  25. biopipen/ns/tcr.py +683 -98
  26. biopipen/ns/vcf.py +236 -2
  27. biopipen/ns/web.py +97 -6
  28. biopipen/reports/bam/CNVpytor.svelte +4 -9
  29. biopipen/reports/cellranger/CellRangerCount.svelte +18 -0
  30. biopipen/reports/cellranger/CellRangerSummary.svelte +16 -0
  31. biopipen/reports/cellranger/CellRangerVdj.svelte +18 -0
  32. biopipen/reports/cnvkit/CNVkitDiagram.svelte +1 -1
  33. biopipen/reports/cnvkit/CNVkitHeatmap.svelte +1 -1
  34. biopipen/reports/cnvkit/CNVkitScatter.svelte +1 -1
  35. biopipen/reports/common.svelte +15 -0
  36. biopipen/reports/protein/ProdigySummary.svelte +16 -0
  37. biopipen/reports/scrna/CellsDistribution.svelte +4 -39
  38. biopipen/reports/scrna/DimPlots.svelte +1 -1
  39. biopipen/reports/scrna/MarkersFinder.svelte +6 -126
  40. biopipen/reports/scrna/MetaMarkers.svelte +3 -75
  41. biopipen/reports/scrna/RadarPlots.svelte +4 -20
  42. biopipen/reports/scrna_metabolic_landscape/MetabolicFeatures.svelte +61 -22
  43. biopipen/reports/scrna_metabolic_landscape/MetabolicPathwayActivity.svelte +88 -82
  44. biopipen/reports/scrna_metabolic_landscape/MetabolicPathwayHeterogeneity.svelte +70 -10
  45. biopipen/reports/snp/PlinkCallRate.svelte +24 -0
  46. biopipen/reports/snp/PlinkFreq.svelte +18 -0
  47. biopipen/reports/snp/PlinkHWE.svelte +18 -0
  48. biopipen/reports/snp/PlinkHet.svelte +18 -0
  49. biopipen/reports/snp/PlinkIBD.svelte +18 -0
  50. biopipen/reports/tcr/CDR3AAPhyschem.svelte +19 -66
  51. biopipen/reports/tcr/ClonalStats.svelte +16 -0
  52. biopipen/reports/tcr/CloneResidency.svelte +3 -93
  53. biopipen/reports/tcr/Immunarch.svelte +4 -155
  54. biopipen/reports/tcr/TCRClusterStats.svelte +3 -45
  55. biopipen/reports/tcr/TESSA.svelte +11 -28
  56. biopipen/reports/utils/misc.liq +22 -7
  57. biopipen/scripts/bam/BamMerge.py +11 -15
  58. biopipen/scripts/bam/BamSampling.py +90 -0
  59. biopipen/scripts/bam/BamSort.py +141 -0
  60. biopipen/scripts/bam/BamSplitChroms.py +10 -10
  61. biopipen/scripts/bam/BamSubsetByBed.py +38 -0
  62. biopipen/scripts/bam/CNAClinic.R +41 -5
  63. biopipen/scripts/bam/CNVpytor.py +153 -54
  64. biopipen/scripts/bam/ControlFREEC.py +13 -14
  65. biopipen/scripts/bam/SamtoolsView.py +33 -0
  66. biopipen/scripts/bed/Bed2Vcf.py +5 -5
  67. biopipen/scripts/bed/BedConsensus.py +5 -5
  68. biopipen/scripts/bed/BedLiftOver.sh +6 -4
  69. biopipen/scripts/bed/BedtoolsIntersect.py +54 -0
  70. biopipen/scripts/bed/BedtoolsMakeWindows.py +47 -0
  71. biopipen/scripts/bed/BedtoolsMerge.py +4 -4
  72. biopipen/scripts/cellranger/CellRangerCount.py +138 -0
  73. biopipen/scripts/cellranger/CellRangerSummary.R +181 -0
  74. biopipen/scripts/cellranger/CellRangerVdj.py +112 -0
  75. biopipen/scripts/cnv/AneuploidyScore.R +55 -20
  76. biopipen/scripts/cnv/AneuploidyScoreSummary.R +221 -163
  77. biopipen/scripts/cnv/TMADScore.R +25 -9
  78. biopipen/scripts/cnv/TMADScoreSummary.R +57 -86
  79. biopipen/scripts/cnvkit/CNVkitAccess.py +7 -6
  80. biopipen/scripts/cnvkit/CNVkitAutobin.py +26 -18
  81. biopipen/scripts/cnvkit/CNVkitBatch.py +6 -6
  82. biopipen/scripts/cnvkit/CNVkitCall.py +3 -3
  83. biopipen/scripts/cnvkit/CNVkitCoverage.py +4 -3
  84. biopipen/scripts/cnvkit/CNVkitDiagram.py +5 -5
  85. biopipen/scripts/cnvkit/CNVkitFix.py +3 -3
  86. biopipen/scripts/cnvkit/CNVkitGuessBaits.py +12 -8
  87. biopipen/scripts/cnvkit/CNVkitHeatmap.py +5 -5
  88. biopipen/scripts/cnvkit/CNVkitReference.py +6 -5
  89. biopipen/scripts/cnvkit/CNVkitScatter.py +5 -5
  90. biopipen/scripts/cnvkit/CNVkitSegment.py +5 -5
  91. biopipen/scripts/cnvkit/guess_baits.py +166 -93
  92. biopipen/scripts/delim/RowsBinder.R +1 -1
  93. biopipen/scripts/delim/SampleInfo.R +116 -118
  94. biopipen/scripts/gene/GeneNameConversion.R +67 -0
  95. biopipen/scripts/gene/GenePromoters.R +61 -0
  96. biopipen/scripts/gsea/Enrichr.R +5 -5
  97. biopipen/scripts/gsea/FGSEA.R +184 -50
  98. biopipen/scripts/gsea/GSEA.R +2 -2
  99. biopipen/scripts/gsea/PreRank.R +5 -5
  100. biopipen/scripts/misc/Config2File.py +2 -2
  101. biopipen/scripts/misc/Plot.R +80 -0
  102. biopipen/scripts/misc/Shell.sh +15 -0
  103. biopipen/scripts/misc/Str2File.py +2 -2
  104. biopipen/scripts/plot/Heatmap.R +3 -3
  105. biopipen/scripts/plot/Manhattan.R +147 -0
  106. biopipen/scripts/plot/QQPlot.R +146 -0
  107. biopipen/scripts/plot/ROC.R +88 -0
  108. biopipen/scripts/plot/Scatter.R +112 -0
  109. biopipen/scripts/plot/VennDiagram.R +5 -9
  110. biopipen/scripts/protein/MMCIF2PDB.py +33 -0
  111. biopipen/scripts/protein/PDB2Fasta.py +60 -0
  112. biopipen/scripts/protein/Prodigy.py +119 -0
  113. biopipen/scripts/protein/ProdigySummary.R +140 -0
  114. biopipen/scripts/protein/RMSD.py +178 -0
  115. biopipen/scripts/regulatory/MotifAffinityTest.R +102 -0
  116. biopipen/scripts/regulatory/MotifAffinityTest_AtSNP.R +127 -0
  117. biopipen/scripts/regulatory/MotifAffinityTest_MotifBreakR.R +104 -0
  118. biopipen/scripts/regulatory/MotifScan.py +159 -0
  119. biopipen/scripts/regulatory/VariantMotifPlot.R +78 -0
  120. biopipen/scripts/regulatory/motifs-common.R +324 -0
  121. biopipen/scripts/rnaseq/Simulation-ESCO.R +180 -0
  122. biopipen/scripts/rnaseq/Simulation-RUVcorr.R +45 -0
  123. biopipen/scripts/rnaseq/Simulation.R +21 -0
  124. biopipen/scripts/rnaseq/UnitConversion.R +325 -54
  125. biopipen/scripts/scrna/AnnData2Seurat.R +40 -0
  126. biopipen/scripts/scrna/CCPlotR-patch.R +161 -0
  127. biopipen/scripts/scrna/CellCellCommunication.py +150 -0
  128. biopipen/scripts/scrna/CellCellCommunicationPlots.R +93 -0
  129. biopipen/scripts/scrna/CellSNPLite.py +30 -0
  130. biopipen/scripts/scrna/CellTypeAnnotation-celltypist.R +185 -0
  131. biopipen/scripts/scrna/CellTypeAnnotation-direct.R +68 -31
  132. biopipen/scripts/scrna/CellTypeAnnotation-hitype.R +27 -22
  133. biopipen/scripts/scrna/CellTypeAnnotation-sccatch.R +28 -20
  134. biopipen/scripts/scrna/CellTypeAnnotation-sctype.R +48 -25
  135. biopipen/scripts/scrna/CellTypeAnnotation.R +37 -1
  136. biopipen/scripts/scrna/CellsDistribution.R +456 -167
  137. biopipen/scripts/scrna/DimPlots.R +1 -1
  138. biopipen/scripts/scrna/ExprImputation-alra.R +109 -0
  139. biopipen/scripts/scrna/ExprImputation-rmagic.R +256 -0
  140. biopipen/scripts/scrna/{ExprImpution-scimpute.R → ExprImputation-scimpute.R} +8 -5
  141. biopipen/scripts/scrna/ExprImputation.R +7 -0
  142. biopipen/scripts/scrna/LoomTo10X.R +51 -0
  143. biopipen/scripts/scrna/MQuad.py +25 -0
  144. biopipen/scripts/scrna/MarkersFinder.R +679 -400
  145. biopipen/scripts/scrna/MetaMarkers.R +265 -161
  146. biopipen/scripts/scrna/ModuleScoreCalculator.R +66 -11
  147. biopipen/scripts/scrna/PseudoBulkDEG.R +678 -0
  148. biopipen/scripts/scrna/RadarPlots.R +355 -134
  149. biopipen/scripts/scrna/ScFGSEA.R +298 -100
  150. biopipen/scripts/scrna/ScSimulation.R +65 -0
  151. biopipen/scripts/scrna/ScVelo.py +617 -0
  152. biopipen/scripts/scrna/Seurat2AnnData.R +7 -0
  153. biopipen/scripts/scrna/SeuratClusterStats-clustree.R +87 -0
  154. biopipen/scripts/scrna/SeuratClusterStats-dimplots.R +36 -30
  155. biopipen/scripts/scrna/SeuratClusterStats-features.R +138 -187
  156. biopipen/scripts/scrna/SeuratClusterStats-ngenes.R +81 -0
  157. biopipen/scripts/scrna/SeuratClusterStats-stats.R +78 -89
  158. biopipen/scripts/scrna/SeuratClusterStats.R +47 -10
  159. biopipen/scripts/scrna/SeuratClustering.R +36 -233
  160. biopipen/scripts/scrna/SeuratLoading.R +2 -2
  161. biopipen/scripts/scrna/SeuratMap2Ref.R +84 -113
  162. biopipen/scripts/scrna/SeuratMetadataMutater.R +16 -6
  163. biopipen/scripts/scrna/SeuratPreparing.R +223 -173
  164. biopipen/scripts/scrna/SeuratSubClustering.R +64 -0
  165. biopipen/scripts/scrna/SeuratTo10X.R +27 -0
  166. biopipen/scripts/scrna/Slingshot.R +65 -0
  167. biopipen/scripts/scrna/Subset10X.R +2 -2
  168. biopipen/scripts/scrna/TopExpressingGenes.R +169 -135
  169. biopipen/scripts/scrna/celltypist-wrapper.py +195 -0
  170. biopipen/scripts/scrna/scvelo_paga.py +313 -0
  171. biopipen/scripts/scrna/seurat_anndata_conversion.py +98 -0
  172. biopipen/scripts/scrna_metabolic_landscape/MetabolicFeatures.R +447 -82
  173. biopipen/scripts/scrna_metabolic_landscape/MetabolicPathwayActivity.R +348 -241
  174. biopipen/scripts/scrna_metabolic_landscape/MetabolicPathwayHeterogeneity.R +188 -166
  175. biopipen/scripts/snp/MatrixEQTL.R +217 -0
  176. biopipen/scripts/snp/Plink2GTMat.py +148 -0
  177. biopipen/scripts/snp/PlinkCallRate.R +199 -0
  178. biopipen/scripts/snp/PlinkFilter.py +100 -0
  179. biopipen/scripts/snp/PlinkFreq.R +291 -0
  180. biopipen/scripts/snp/PlinkFromVcf.py +81 -0
  181. biopipen/scripts/snp/PlinkHWE.R +85 -0
  182. biopipen/scripts/snp/PlinkHet.R +96 -0
  183. biopipen/scripts/snp/PlinkIBD.R +196 -0
  184. biopipen/scripts/snp/PlinkSimulation.py +124 -0
  185. biopipen/scripts/snp/PlinkUpdateName.py +124 -0
  186. biopipen/scripts/stats/ChowTest.R +146 -0
  187. biopipen/scripts/stats/DiffCoexpr.R +152 -0
  188. biopipen/scripts/stats/LiquidAssoc.R +135 -0
  189. biopipen/scripts/stats/Mediation.R +108 -0
  190. biopipen/scripts/stats/MetaPvalue.R +130 -0
  191. biopipen/scripts/stats/MetaPvalue1.R +74 -0
  192. biopipen/scripts/tcgamaf/Maf2Vcf.py +2 -2
  193. biopipen/scripts/tcgamaf/MafAddChr.py +2 -2
  194. biopipen/scripts/tcr/Attach2Seurat.R +3 -2
  195. biopipen/scripts/tcr/CDR3AAPhyschem.R +211 -143
  196. biopipen/scripts/tcr/CDR3Clustering.R +343 -0
  197. biopipen/scripts/tcr/ClonalStats.R +526 -0
  198. biopipen/scripts/tcr/CloneResidency.R +255 -131
  199. biopipen/scripts/tcr/CloneSizeQQPlot.R +4 -4
  200. biopipen/scripts/tcr/GIANA/GIANA.py +1356 -797
  201. biopipen/scripts/tcr/GIANA/GIANA4.py +1362 -789
  202. biopipen/scripts/tcr/GIANA/query.py +164 -162
  203. biopipen/scripts/tcr/Immunarch-basic.R +31 -9
  204. biopipen/scripts/tcr/Immunarch-clonality.R +25 -5
  205. biopipen/scripts/tcr/Immunarch-diversity.R +352 -134
  206. biopipen/scripts/tcr/Immunarch-geneusage.R +45 -5
  207. biopipen/scripts/tcr/Immunarch-kmer.R +68 -8
  208. biopipen/scripts/tcr/Immunarch-overlap.R +84 -4
  209. biopipen/scripts/tcr/Immunarch-spectratyping.R +35 -6
  210. biopipen/scripts/tcr/Immunarch-tracking.R +38 -6
  211. biopipen/scripts/tcr/Immunarch-vjjunc.R +165 -0
  212. biopipen/scripts/tcr/Immunarch.R +63 -11
  213. biopipen/scripts/tcr/Immunarch2VDJtools.R +2 -2
  214. biopipen/scripts/tcr/ImmunarchFilter.R +4 -4
  215. biopipen/scripts/tcr/ImmunarchLoading.R +38 -29
  216. biopipen/scripts/tcr/SampleDiversity.R +1 -1
  217. biopipen/scripts/tcr/ScRepCombiningExpression.R +40 -0
  218. biopipen/scripts/tcr/ScRepLoading.R +166 -0
  219. biopipen/scripts/tcr/TCRClusterStats.R +176 -22
  220. biopipen/scripts/tcr/TCRDock.py +110 -0
  221. biopipen/scripts/tcr/TESSA.R +102 -118
  222. biopipen/scripts/tcr/VJUsage.R +5 -5
  223. biopipen/scripts/tcr/immunarch-patched.R +142 -0
  224. biopipen/scripts/tcr/vdjtools-patch.sh +1 -1
  225. biopipen/scripts/vcf/BcftoolsAnnotate.py +91 -0
  226. biopipen/scripts/vcf/BcftoolsFilter.py +90 -0
  227. biopipen/scripts/vcf/BcftoolsMerge.py +31 -0
  228. biopipen/scripts/vcf/BcftoolsSort.py +113 -0
  229. biopipen/scripts/vcf/BcftoolsView.py +73 -0
  230. biopipen/scripts/vcf/TruvariBench.sh +14 -7
  231. biopipen/scripts/vcf/TruvariBenchSummary.R +16 -13
  232. biopipen/scripts/vcf/TruvariConsistency.R +1 -1
  233. biopipen/scripts/vcf/Vcf2Bed.py +2 -2
  234. biopipen/scripts/vcf/VcfAnno.py +11 -11
  235. biopipen/scripts/vcf/VcfDownSample.sh +22 -10
  236. biopipen/scripts/vcf/VcfFilter.py +5 -5
  237. biopipen/scripts/vcf/VcfFix.py +7 -7
  238. biopipen/scripts/vcf/VcfFix_utils.py +13 -4
  239. biopipen/scripts/vcf/VcfIndex.py +3 -3
  240. biopipen/scripts/vcf/VcfIntersect.py +3 -3
  241. biopipen/scripts/vcf/VcfLiftOver.sh +5 -0
  242. biopipen/scripts/vcf/VcfSplitSamples.py +4 -4
  243. biopipen/scripts/vcf/bcftools_utils.py +52 -0
  244. biopipen/scripts/web/Download.py +8 -4
  245. biopipen/scripts/web/DownloadList.py +5 -5
  246. biopipen/scripts/web/GCloudStorageDownloadBucket.py +82 -0
  247. biopipen/scripts/web/GCloudStorageDownloadFile.py +23 -0
  248. biopipen/scripts/web/gcloud_common.py +49 -0
  249. biopipen/utils/gene.py +108 -60
  250. biopipen/utils/misc.py +146 -20
  251. biopipen/utils/reference.py +64 -20
  252. biopipen/utils/reporter.py +177 -0
  253. biopipen/utils/vcf.py +1 -1
  254. biopipen-0.34.26.dist-info/METADATA +27 -0
  255. biopipen-0.34.26.dist-info/RECORD +292 -0
  256. {biopipen-0.21.0.dist-info → biopipen-0.34.26.dist-info}/WHEEL +1 -1
  257. {biopipen-0.21.0.dist-info → biopipen-0.34.26.dist-info}/entry_points.txt +6 -2
  258. biopipen/ns/bcftools.py +0 -111
  259. biopipen/ns/scrna_basic.py +0 -255
  260. biopipen/reports/delim/SampleInfo.svelte +0 -36
  261. biopipen/reports/scrna/GeneExpressionInvistigation.svelte +0 -32
  262. biopipen/reports/scrna/ScFGSEA.svelte +0 -35
  263. biopipen/reports/scrna/SeuratClusterStats.svelte +0 -82
  264. biopipen/reports/scrna/SeuratMap2Ref.svelte +0 -20
  265. biopipen/reports/scrna/SeuratPreparing.svelte +0 -38
  266. biopipen/reports/scrna/TopExpressingGenes.svelte +0 -55
  267. biopipen/reports/scrna_metabolic_landscape/MetabolicFeaturesIntraSubset.svelte +0 -31
  268. biopipen/reports/utils/gsea.liq +0 -110
  269. biopipen/scripts/bcftools/BcftoolsAnnotate.py +0 -42
  270. biopipen/scripts/bcftools/BcftoolsFilter.py +0 -79
  271. biopipen/scripts/bcftools/BcftoolsSort.py +0 -19
  272. biopipen/scripts/gene/GeneNameConversion.py +0 -66
  273. biopipen/scripts/scrna/ExprImpution-alra.R +0 -32
  274. biopipen/scripts/scrna/ExprImpution-rmagic.R +0 -29
  275. biopipen/scripts/scrna/ExprImpution.R +0 -7
  276. biopipen/scripts/scrna/GeneExpressionInvistigation.R +0 -132
  277. biopipen/scripts/scrna/Write10X.R +0 -11
  278. biopipen/scripts/scrna_metabolic_landscape/MetabolicFeaturesIntraSubset.R +0 -150
  279. biopipen/scripts/tcr/TCRClustering.R +0 -280
  280. biopipen/utils/common_docstrs.py +0 -61
  281. biopipen/utils/gene.R +0 -49
  282. biopipen/utils/gsea.R +0 -193
  283. biopipen/utils/io.R +0 -20
  284. biopipen/utils/misc.R +0 -114
  285. biopipen/utils/mutate_helpers.R +0 -433
  286. biopipen/utils/plot.R +0 -173
  287. biopipen/utils/rnaseq.R +0 -48
  288. biopipen/utils/single_cell.R +0 -115
  289. biopipen-0.21.0.dist-info/METADATA +0 -22
  290. biopipen-0.21.0.dist-info/RECORD +0 -218
@@ -1,17 +1,23 @@
1
- source("{{biopipen_dir}}/utils/misc.R")
2
- source("{{biopipen_dir}}/utils/mutate_helpers.R")
1
+ {{ biopipen_dir | joinpaths: "utils", "misc.R" | source_r }}
2
+ {{ biopipen_dir | joinpaths: "utils", "mutate_helpers.R" | source_r }}
3
+
3
4
  library(Seurat)
4
5
  library(rlang)
5
6
  library(tidyr)
7
+ library(tibble)
6
8
  library(dplyr)
7
9
  library(ggplot2)
8
- library(ggsci)
10
+ library(patchwork)
9
11
  library(ggVennDiagram)
10
12
  library(UpSetR)
13
+ library(circlize)
14
+ library(ComplexHeatmap)
11
15
 
12
16
  srtfile <- {{in.srtobj | r}} # nolint
13
17
  outdir <- {{out.outdir | r}} # nolint
18
+ joboutdir <- {{job.outdir | r}} # nolint
14
19
  mutaters <- {{envs.mutaters | r}} # nolint
20
+ cluster_orderby <- {{envs.cluster_orderby | r}} # nolint
15
21
  group_by <- {{envs.group_by | r}} # nolint
16
22
  group_order <- {{envs.group_order | r}} # nolint
17
23
  cells_by <- {{envs.cells_by | r}} # nolint
@@ -19,235 +25,479 @@ cells_order <- {{envs.cells_order | r}} # nolint
19
25
  cells_orderby <- {{envs.cells_orderby | r}} # nolint
20
26
  cells_n <- {{envs.cells_n | r}} # nolint
21
27
  subset <- {{envs.subset | r}} # nolint
28
+ descr <- {{envs.descr | r}} # nolint
22
29
  devpars <- {{envs.devpars | r}} # nolint
30
+ hm_devpars <- {{envs.hm_devpars | r}} # nolint
23
31
  each <- {{envs.each | r}} # nolint
24
32
  section <- {{envs.section | r}} # nolint
33
+ prefix_each <- {{envs.prefix_each | r}} # nolint
25
34
  overlap <- {{envs.overlap | r}} # nolint
26
35
  cases <- {{envs.cases | r}} # nolint
27
36
 
28
- if (is.null(overlap)) { overlap = c() }
37
+ overlap <- overlap %||% c()
29
38
  overlaps <- list()
30
- print("- Loading seurat object ...")
31
- srtobj <- readRDS(srtfile)
39
+ log_info("- Loading seurat object ...")
40
+ srtobj <- biopipen.utils::read_obj(srtfile)
32
41
 
33
42
  if (!is.null(mutaters) && length(mutaters) > 0) {
34
- print("- Mutating seurat object ...")
35
- srtobj@meta.data <- srtobj@meta.data %>%
36
- mutate(!!!lapply(mutaters, parse_expr))
43
+ log_info("- Mutating seurat object ...")
44
+ srtobj@meta.data <- srtobj@meta.data %>% mutate(!!!lapply(mutaters, parse_expr))
37
45
  }
38
46
 
39
- all_clusters = srtobj@meta.data %>% pull(seurat_clusters)
40
- if (!is.factor(all_clusters)) {
41
- all_clusters = factor(all_clusters, levels = sort(unique(all_clusters)))
42
- }
47
+ defaults <- list(
48
+ cluster_orderby = cluster_orderby,
49
+ group_by = group_by,
50
+ group_order = group_order,
51
+ cells_by = cells_by,
52
+ cells_order = cells_order,
53
+ cells_orderby = cells_orderby,
54
+ cells_n = cells_n,
55
+ devpars = devpars,
56
+ hm_devpars = hm_devpars,
57
+ each = each,
58
+ section = section,
59
+ prefix_each = prefix_each,
60
+ subset = subset,
61
+ descr = descr
62
+ )
43
63
 
44
- expand_cases <- function() {
45
- # fill up cases with missing parameters
46
- if (is.null(cases) || length(cases) == 0) {
47
- filled_cases <- list(
48
- DEFAULT = list(
49
- group_by = group_by,
50
- group_order = group_order,
51
- cells_by = cells_by,
52
- cells_order = cells_order,
53
- cells_orderby = cells_orderby,
54
- cells_n = cells_n,
55
- devpars = devpars,
56
- each = each,
57
- section = section,
58
- subset = subset
59
- )
60
- )
64
+ expand_each <- function(name, case) {
65
+ outcases <- list()
66
+ if (is.null(case$each) || nchar(case$each) == 0) {
67
+ if (is.null(case$section) || case$section == "DEFAULT") {
68
+ outcases[[name]] <- case
69
+ } else {
70
+ outcases[[paste0(case$section, "::", name)]] <- case
71
+ }
61
72
  } else {
62
- filled_cases <- list()
63
- for (name in names(cases)) {
64
- case <- list_setdefault(
65
- cases[[name]],
66
- group_by = group_by,
67
- group_order = group_order,
68
- cells_by = cells_by,
69
- cells_order = cells_order,
70
- cells_orderby = cells_orderby,
71
- cells_n = cells_n,
72
- devpars = devpars,
73
- each = each,
74
- section = section,
75
- subset = subset
76
- )
77
- case$devpars <- list_setdefault(case$devpars, devpars)
78
- filled_cases[[name]] <- case
73
+ if (!is.null(case$section) && case$section != "DEFAULT") {
74
+ log_warn("Ignoring `section` in case `{name}` when `each` is set.")
75
+ case$section <- NULL
79
76
  }
80
- }
81
-
82
- outcases <- list()
83
- # expand each
84
- for (name in names(filled_cases)) {
85
- case <- filled_cases[[name]]
86
- if (is.null(case$each) || nchar(case$each) == 0) {
87
- outcases[[paste0(case$section, ":", name)]] <- case
77
+ if (!is.null(case$subset)) {
78
+ eachs <- srtobj@meta.data %>%
79
+ dplyr::filter(!!parse_expr(case$subset)) %>%
80
+ pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
88
81
  } else {
89
- eachs <- srtobj@meta.data %>% pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
90
- for (ea in eachs) {
91
- by <- make.names(paste0(".", name, "_", case$each,"_", ea))
92
- srtobj@meta.data <<- srtobj@meta.data %>%
93
- mutate(!!sym(by) := if_else(
94
- !!sym(case$each) == ea,
95
- !!sym(case$group_by),
96
- NA
97
- ))
98
- key <- paste0(case$each, ":", name, " (", ea, ")")
99
- outcases[[key]] <- case
100
- outcases[[key]]$group_by <- by
82
+ eachs <- srtobj@meta.data %>%
83
+ pull(case$each) %>% na.omit() %>% unique() %>% as.vector()
84
+ }
85
+
86
+ for (each in eachs) {
87
+ by <- make.names(paste0(".", name, "_", case$each,"_", each))
88
+ srtobj@meta.data <<- srtobj@meta.data %>%
89
+ mutate(!!sym(by) := if_else(
90
+ !!sym(case$each) == each,
91
+ !!sym(case$group_by),
92
+ NA
93
+ ))
94
+ if (isTRUE(case$prefix_each)) {
95
+ key <- paste0(name, "::", case$each, " - ", each)
96
+ } else {
97
+ key <- paste0(name, "::", each)
101
98
  }
99
+ outcases[[key]] <- case
100
+ outcases[[key]]$section <- name
101
+ outcases[[key]]$group_by <- by
102
102
  }
103
103
  }
104
104
  outcases
105
105
  }
106
106
 
107
+ log_info("- Expanding cases...")
108
+ cases <- expand_cases(cases, defaults, expand_each)
109
+
110
+ plot_heatmap <- function(m, cells_by, group_by, cluster_order_val, cluster_orderby) {
111
+ # A matrix: 10 × 8 of type int
112
+ # g3 g6 g0 g1 g7 g5 g4 g8
113
+ # CSARDATNNEQFF 8 32 17 26 7 1 NA NA
114
+ # CASRQNRGSYNEQFF 2 1 20 16 NA NA 1 NA
115
+ # CSATSYNEQFF 2 6 3 7 1 8 6 NA
116
+ hmdata <- m %>%
117
+ mutate(
118
+ !!sym(cells_by) := paste0("[", !!sym(group_by), "] ", !!sym(cells_by))
119
+ ) %>%
120
+ select(!!sym(cells_by), CloneGroupClusterSize, seurat_clusters) %>%
121
+ distinct(!!sym(cells_by), seurat_clusters, .keep_all = TRUE) %>%
122
+ pivot_wider(names_from = seurat_clusters, values_from = CloneGroupClusterSize) %>%
123
+ tibble::column_to_rownames(cells_by)
124
+
125
+ hmdata[, setdiff(levels(m$seurat_clusters), colnames(hmdata))] <- NA
126
+ # order
127
+ hmdata <- select(hmdata, all_of(levels(m$seurat_clusters)))
128
+
129
+ row_ha <- rowAnnotation(
130
+ Total = anno_barplot(
131
+ hmdata %>% rowSums(na.rm = T),
132
+ gp = gpar(fill = "lightblue", col = NA),
133
+ width = unit(2, "cm")
134
+ )
135
+ )
136
+ ha <- NULL
137
+ extra_height <- 0
138
+ extra_width <- 0 # legend
139
+ if (!is.null(cluster_order_val)) {
140
+ ha <- list()
141
+ ha[[cluster_orderby]] <- cluster_order_val
142
+ if (is.numeric(cluster_order_val)) {
143
+ col_fun <- colorRamp2(
144
+ c(min(cluster_order_val), max(cluster_order_val)),
145
+ c("lightyellow", "red"))
146
+ ha$col <- list()
147
+ ha$col[[cluster_orderby]] <- col_fun
148
+ }
149
+ ha <- do_call(HeatmapAnnotation, ha)
150
+ extra_height <- 40
151
+ extra_width <- 120
152
+ }
153
+
154
+ col_fun <- colorRamp2(c(0, max(hmdata, na.rm = T)), c("lightyellow", "purple"))
155
+ Heatmap(
156
+ as.matrix(hmdata),
157
+ name = cells_by,
158
+ col = col_fun,
159
+ na_col = "lightyellow",
160
+ row_names_side = "left",
161
+ cluster_rows = FALSE,
162
+ cluster_columns = FALSE,
163
+ rect_gp = gpar(col = "white", lwd = 1),
164
+ row_names_max_width = max_text_width(rownames(hmdata)),
165
+ right_annotation = row_ha,
166
+ top_annotation = ha
167
+ )
168
+ }
169
+
170
+ sections <- c()
107
171
  do_case <- function(name, case) {
108
- print(paste("- Running for case:", name))
172
+ log_info("- Handling case: {name}")
109
173
  if (is.null(case$group_by) || nchar(case$group_by) == 0) {
110
- stop(paste0("`group_by` must be specified for case", name))
174
+ stop(paste0(" `group_by` must be specified for case", name))
111
175
  }
112
176
  if (is.null(case$cells_by) || nchar(case$cells_by) == 0) {
113
- stop(paste0("`cells_by` must be specified for case", name))
177
+ stop(paste0(" `cells_by` must be specified for case", name))
114
178
  }
179
+
180
+ info <- casename_info(name, cases, outdir, create = TRUE)
115
181
  cells_by <- trimws(strsplit(case$cells_by, ",")[[1]])
116
182
 
117
- sec_case_names <- strsplit(name, ":")[[1]]
118
- sec_dir <- file.path(outdir, sec_case_names[1])
119
- casename <- paste(sec_case_names[-1], collapse = ":")
120
- dir.create(sec_dir, showWarnings = FALSE, recursive = TRUE)
121
- outfile <- file.path(sec_dir, paste0("case-", casename, ".png"))
122
- txtfile <- file.path(sec_dir, paste0("case-", casename, ".txt"))
183
+ meta <- srtobj@meta.data
184
+ # order the clusters if cluster_orderby is specified
185
+ cluster_order_val <- NULL
186
+ if (!is.null(case$cluster_orderby) && length(case$cluster_orderby) > 0) {
187
+ cluster_order_df <- meta %>%
188
+ group_by(seurat_clusters) %>%
189
+ summarise(
190
+ !!sym(case$cluster_orderby) := !!parse_expr(case$cluster_orderby),
191
+ .groups = "drop") %>%
192
+ arrange(!!sym(case$cluster_orderby))
193
+
194
+ cluster_order_val <- pull(cluster_order_df, case$cluster_orderby)
195
+
196
+ meta$seurat_clusters <- factor(
197
+ meta$seurat_clusters,
198
+ levels = cluster_order_df %>% pull(seurat_clusters) %>% as.character()
199
+ )
200
+ }
201
+ if (!is.factor(meta$seurat_clusters)) {
202
+ meta$seurat_clusters <- factor(meta$seurat_clusters, levels = sort(unique(meta$seurat_clusters)))
203
+ }
204
+ all_clusters <- meta$seurat_clusters
123
205
 
124
206
  # subset the seurat object
125
- meta <- srtobj@meta.data
126
207
  if (!is.null(case$subset) && nchar(case$subset) > 0) {
127
208
  meta <- dplyr::filter(meta, !!!parse_exprs(case$subset))
128
209
  }
129
- meta <- meta %>%
130
- drop_na(case$group_by) %>%
131
- dplyr::filter(!if_all(all_of(cells_by), is.na))
210
+ meta <- meta %>% drop_na(case$group_by)
211
+ # dplyr::filter(!if_all(all_of(cells_by), is.na))
132
212
 
133
213
  if (nrow(meta) == 0) {
134
- stop(paste0("No cells left after filtering NAs for group_by and cells_by for case: ", name))
214
+ stop(paste0("No cells left after filtering NAs for `group_by`"))
135
215
  }
136
216
 
137
- if (length(cells_by) > 1) {
138
- new_cells_by <- paste0(".", paste(cells_by, collapse = "_"))
139
- meta1 <- meta %>% drop_na(cells_by[1])
140
- meta1[[new_cells_by]] <- meta1[[cells_by[1]]]
141
- for (i in 2:length(cells_by)) {
142
- meta2 <- meta %>% drop_na(cells_by[i])
143
- meta2[[new_cells_by]] <- meta2[[cells_by[i]]]
144
- meta1 <- rbind(meta1, meta2)
145
- }
146
-
147
- cells_by <- new_cells_by
148
- meta <- meta1
217
+ if (info$section %in% overlap && length(cells_by) > 1) {
218
+ stop(paste0("Overlapping groups can only be done for a single `cells_by`"))
149
219
  }
150
220
 
151
- if (sec_case_names[1] %in% overlap) {
152
- if (is.null(overlaps[[sec_case_names[1]]])) {
153
- overlaps[[sec_case_names[1]]] <<- list()
154
- }
155
- overlaps[[sec_case_names[1]]][[casename]] <<- meta %>% pull(case$cells_by) %>% unique()
156
- }
157
-
158
- # add sizes
159
- meta <- meta %>%
160
- add_count(!!sym(cells_by), name = "CloneSize") %>%
161
- add_count(!!sym(cells_by), !!sym(case$group_by), name = "CloneGroupSize") %>%
162
- add_count(!!sym(cells_by), seurat_clusters, name = "CloneClusterSize") %>%
163
- add_count(!!sym(cells_by), !!sym(case$group_by), seurat_clusters, name = "CloneGroupClusterSize")
164
-
165
221
  # filter group_by values not in group_order
166
222
  if (!is.null(case$group_order) && length(case$group_order) > 0) {
167
223
  meta <- meta %>%
168
224
  dplyr::filter(!!sym(case$group_by) %in% case$group_order) %>%
169
- mutate(!!sym(case$group_by) := factor(!!sym(case$group_by), levels = case$group_order)) %>%
170
- arrange(!!sym(case$group_by))
225
+ mutate(!!sym(case$group_by) := factor(!!sym(case$group_by), levels = case$group_order))
171
226
 
172
227
  if (nrow(meta) == 0) {
173
228
  stop(paste0(
174
229
  "No items in `group_order` (",
175
230
  paste0(case$group_order, collapse=", "),
176
- ") in column `", case$group_by , "` for case: ",
177
- name,
231
+ ") in column `", case$group_by ,
178
232
  ". Did you specify the correct `group_by` and `group_order`?"
179
233
  ))
180
234
  }
181
235
  } else {
182
- meta <- meta %>% arrange(!!sym(case$group_by))
236
+ meta <- meta %>% mutate(!!sym(case$group_by) := factor(!!sym(case$group_by)))
183
237
  }
238
+ ngroups <- length(unique(meta[[case$group_by]]))
239
+ sections <<- union(sections, info$section)
184
240
 
185
- if (!is.null(case$cells_order) && length(case$cells_order) > 0) {
186
- # filter cells_by values not in cells_order
187
- meta <- meta %>%
188
- dplyr::filter(!!sym(cells_by) %in% case$cells_order) %>%
189
- mutate(!!sym(cells_by) := factor(!!sym(cells_by), levels = case$cells_order))
190
- } else if (!is.null(case$cells_orderby)) {
191
- # otherwise use cells_orderby to order cells_by
192
- ordered_meta <- meta %>%
193
- arrange(!!!parse_exprs(case$cells_orderby))
194
- cells <- ordered_meta %>% pull(cells_by) %>% unique() %>% head(case$cells_n)
195
- meta <- ordered_meta %>% dplyr::filter(!!sym(cells_by) %in% cells)
196
- meta[[cells_by]] = factor(meta[[cells_by]], levels = cells)
197
- }
241
+ piecharts <- list()
242
+ hmdata <- NULL
243
+ hmrowlbls <- c()
244
+ hmsplits <- c()
245
+ hmfile <- file.path(info$casedir, paste0(info$case_slug, ".heatmap.png"))
246
+ cells_rows <- 0
247
+ table_files <- c()
248
+ for (n in seq_along(cells_by)) {
249
+ cby <- cells_by[n]
250
+ log_info("- Processing cells_by: {cby}")
251
+ m <- meta %>% drop_na(!!sym(cby))
198
252
 
199
- write.table(
200
- meta,
201
- txtfile,
202
- sep = "\t",
203
- row.names = TRUE,
204
- col.names = TRUE,
205
- quote = FALSE
206
- )
253
+ # check if there are enough cells
254
+ if (nrow(m) == 0) {
255
+ stop(paste0(" No cells left after filtering NAs for `", cby, "`"))
256
+ }
207
257
 
208
- nrows <- length(unique(meta[[cells_by]]))
209
- ncols <- length(unique(meta[[case$group_by]]))
210
-
211
- devpars <- case$devpars
212
- if (is.null(devpars)) { devpars = list() }
213
- if (is.null(devpars$res)) { devpars$res = 100 }
214
- if (is.null(devpars$width)) { devpars$width = ncols * 100 + 240 }
215
- if (is.null(devpars$height)) { devpars$height = max(nrows * 100, 600) }
216
-
217
- # plot
218
- p = meta %>% ggplot(
219
- aes(
220
- x = sqrt(CloneGroupSize)/2,
221
- y = CloneSize,
222
- width = sqrt(CloneGroupSize),
223
- fill = seurat_clusters
258
+ if (info$section %in% overlap) {
259
+ overlaps[[info$section]] <<- overlaps[[info$section]] %||% list()
260
+ overlaps[[info$section]][[info$case]] <<- m %>% pull(cby) %>% unique()
261
+ }
262
+
263
+ # add sizes
264
+ m <- m %>%
265
+ add_count(!!sym(cby), name = "CloneSize") %>%
266
+ add_count(!!sym(cby), !!sym(case$group_by), name = "CloneGroupSize") %>%
267
+ add_count(!!sym(cby), seurat_clusters, name = "CloneClusterSize") %>%
268
+ add_count(!!sym(cby), !!sym(case$group_by), seurat_clusters, name = "CloneGroupClusterSize") %>%
269
+ select(
270
+ !!sym(cby),
271
+ !!sym(case$group_by),
272
+ seurat_clusters,
273
+ CloneSize,
274
+ CloneGroupSize,
275
+ CloneClusterSize,
276
+ CloneGroupClusterSize,
277
+ ) %>% distinct(
278
+ !!sym(cby),
279
+ !!sym(case$group_by),
280
+ seurat_clusters,
281
+ .keep_all = TRUE
224
282
  )
225
- ) +
226
- geom_col(width=.01, position="fill", color = "#888888") +
227
- geom_bar(stat = "identity", position = position_fill(reverse = TRUE)) +
228
- coord_polar("y", start = 0) +
229
- scale_fill_ucscgb(name = "Cluster", alpha = 1, limits = levels(all_clusters)) +
230
- theme_void() +
231
- theme(
232
- plot.margin = unit(c(1,1,1,1), "cm"),
233
- legend.text = element_text(size=8),
234
- legend.title = element_text(size=10)
235
- ) +
236
- facet_grid(vars(!!sym(cells_by)), vars(!!sym(case$group_by)), switch="y")
237
-
238
- png(outfile, res = devpars$res, width = devpars$width, height = devpars$height)
283
+
284
+
285
+ # apply cells order
286
+ if (!is.null(case$cells_order) && length(case$cells_order) > 0) {
287
+ m <- m %>%
288
+ dplyr::filter(!!sym(cby) %in% case$cells_order) %>%
289
+ mutate(!!sym(cby) := factor(!!sym(cby), levels = case$cells_order))
290
+ } else if (!is.null(case$cells_orderby)) {
291
+ ordered_m <- m %>% arrange(!!!parse_exprs(case$cells_orderby))
292
+ cells <- ordered_m %>% pull(cby) %>% unique() %>% head(case$cells_n)
293
+ m <- ordered_m %>% dplyr::filter(!!sym(cby) %in% cells)
294
+ m[[cby]] = factor(m[[cby]], levels = cells)
295
+ }
296
+
297
+ # save the filtered data
298
+ table_file <- file.path(info$casedir, paste0(info$case_slug, ".", slugify(cby), ".txt"))
299
+ table_files <- c(table_files, table_file)
300
+ write.table(
301
+ m, table_file,
302
+ sep = "\t", row.names = FALSE, col.names = TRUE, quote = FALSE
303
+ )
304
+
305
+ log_debug(" Plotting pie charts ...")
306
+ cells_rows <- cells_rows + length(unique(m[[cby]]))
307
+ if (n == 1) {
308
+ plot.margin <- unit(c(1,1,0,1), "cm")
309
+ strip.text.x <- element_text(margin = margin(b = 0.5, unit = "cm"))
310
+ } else if (n == length(cells_by)) {
311
+ plot.margin <- unit(c(0,1,1,1), "cm")
312
+ strip.text.x <- element_blank()
313
+ } else {
314
+ plot.margin <- unit(c(0,1,0,1), "cm")
315
+ strip.text.x <- element_blank()
316
+ }
317
+ p = m %>% ggplot(
318
+ aes(
319
+ x = sqrt(CloneGroupSize)/2,
320
+ y = CloneGroupClusterSize,
321
+ width = sqrt(CloneGroupSize),
322
+ fill = seurat_clusters
323
+ )
324
+ ) +
325
+ geom_col(width=.01, position="fill", color = "#888888") +
326
+ geom_bar(stat = "identity", position = position_fill(reverse = TRUE)) +
327
+ coord_polar("y", start = 0) +
328
+ scale_fill_manual(name = "Cluster", values = pal_biopipen()(length(levels(all_clusters)))) +
329
+ theme_void() +
330
+ theme(
331
+ plot.margin = plot.margin,
332
+ legend.margin = margin(l = .8, unit = "cm"),
333
+ legend.text = element_text(size=6),
334
+ legend.title = element_text(size=8),
335
+ legend.key.size = unit(0.5, "cm"),
336
+ strip.text.x = strip.text.x,
337
+ strip.text.y = element_text(
338
+ angle = 0, hjust = 1,
339
+ margin = margin(r = 0.5, unit = "cm"))
340
+ ) +
341
+ facet_grid(vars(!!sym(cby)), vars(!!sym(case$group_by)), switch="y")
342
+
343
+ piecharts[[length(piecharts) + 1]] <- p
344
+
345
+ # heatmaps
346
+ log_debug(" Preparing pie charts ...")
347
+ hmd <- m %>%
348
+ arrange(!!sym(case$group_by), !!sym(cby)) %>%
349
+ mutate(!!sym(cby) := paste0("[", !!sym(case$group_by), "] ", !!sym(cby))) %>%
350
+ select(!!sym(cby), CloneGroupClusterSize, seurat_clusters) %>%
351
+ distinct(!!sym(cby), seurat_clusters, .keep_all = TRUE) %>%
352
+ pivot_wider(names_from = seurat_clusters, values_from = CloneGroupClusterSize) %>%
353
+ tibble::column_to_rownames(cby)
354
+ hmd[, setdiff(levels(m$seurat_clusters), colnames(hmd))] <- NA
355
+ hmd <- select(hmd, all_of(levels(m$seurat_clusters)))
356
+ hmsplits <- c(hmsplits, rep(cby, nrow(hmd)))
357
+ hmrowlbls <- c(hmrowlbls, rownames(hmd))
358
+ rownames(hmd) <- NULL
359
+
360
+ hmdata <- bind_rows(hmdata, hmd)
361
+ }
362
+
363
+ log_info(" Merging and saving pie charts ...")
364
+ devpars = case$devpars
365
+ # assemble and save pie chart plots
366
+ res <- devpars$res %||% 100
367
+ # legend, cells_by names
368
+ width <- devpars$width %||% (400 + 120 + 100 * ngroups)
369
+ # group_by names
370
+ height <- devpars$height %||% (120 + 100 * cells_rows)
371
+
372
+ p <- wrap_plots(piecharts, ncol = 1, guides = "collect")
373
+
374
+ piefile <- file.path(info$casedir, paste0(info$case_slug, ".png"))
375
+ png(piefile, res = res, width = width, height = height)
239
376
  print(p)
240
377
  dev.off()
378
+
379
+ piefile_pdf <- file.path(info$casedir, paste0(info$case_slug, ".pdf"))
380
+ pdf(piefile_pdf, width = width / res, height = height / res)
381
+ print(p)
382
+ dev.off()
383
+
384
+ log_info(" Plotting and saving heatmap ...")
385
+ row_ha <- rowAnnotation(
386
+ Total = anno_barplot(
387
+ hmdata %>% rowSums(na.rm = T),
388
+ gp = gpar(fill = "lightblue", col = NA),
389
+ width = unit(1.5, "cm")
390
+ )
391
+ )
392
+ ha <- NULL
393
+ extra_height <- 0
394
+ extra_width <- 0 # legend
395
+ if (!is.null(cluster_order_val)) {
396
+ ha <- list()
397
+ ha[[cluster_orderby]] <- cluster_order_val
398
+ if (is.numeric(cluster_order_val)) {
399
+ col_fun <- colorRamp2(
400
+ c(min(cluster_order_val), max(cluster_order_val)),
401
+ c("lightyellow", "red"))
402
+ ha$col <- list()
403
+ ha$col[[cluster_orderby]] <- col_fun
404
+ }
405
+ ha <- do_call(HeatmapAnnotation, ha)
406
+ extra_height <- 40
407
+ extra_width <- 120
408
+ }
409
+ if (length(cells_by) == 1) {
410
+ hmsplits <- NULL
411
+ extra_width <- extra_width - 15
412
+ } else {
413
+ # keep the row order
414
+ hmsplits <- factor(hmsplits, levels = unique(hmsplits))
415
+ }
416
+
417
+ col_fun <- colorRamp2(c(0, max(hmdata, na.rm = T)), c("lightyellow", "purple"))
418
+ hm_devpars <- case$hm_devpars
419
+ hm_res <- hm_devpars$res %||% 100
420
+ hm_width <- hm_devpars$width %||% (600 + 15 * length(unique(meta$seurat_clusters)) + extra_width)
421
+ hm_height <- hm_devpars$height %||% (450 + 15 * cells_rows + extra_height)
422
+ hm <- Heatmap(
423
+ as.matrix(hmdata),
424
+ name = "Size",
425
+ col = col_fun,
426
+ na_col = "lightyellow",
427
+ row_names_side = "left",
428
+ row_names_max_width = max_text_width(
429
+ hmrowlbls,
430
+ gp = gpar(fontsize = 12)
431
+ ),
432
+ row_labels = hmrowlbls,
433
+ row_split = hmsplits,
434
+ cluster_rows = FALSE,
435
+ cluster_columns = FALSE,
436
+ rect_gp = gpar(col = "white", lwd = 1),
437
+ right_annotation = row_ha,
438
+ top_annotation = ha
439
+ )
440
+ png(hmfile, res = hm_res, width = hm_width, height = hm_height)
441
+ print(hm)
442
+ dev.off()
443
+
444
+ hmfile_pdf <- gsub(".png$", ".pdf", hmfile)
445
+ pdf(hmfile_pdf, width = hm_width / hm_res, height = hm_height / hm_res)
446
+ print(hm)
447
+ dev.off()
448
+
449
+ add_report(
450
+ list(
451
+ kind = "descr",
452
+ content = ifelse(
453
+ is.null(case$descr) || nchar(case$descr) == 0,
454
+ paste0(
455
+ "Distribution for cells in ",
456
+ "<code>", html_escape(cells_by), "</code>",
457
+ " for ",
458
+ "<code>", html_escape(case$group_by), "</code>"
459
+ ),
460
+ case$descr
461
+ )
462
+ ),
463
+ h1 = info$h1,
464
+ h2 = info$h2
465
+ )
466
+
467
+ add_report(
468
+ list(
469
+ name = "Pie Charts",
470
+ contents = list(list(kind = "image", src = piefile, download = piefile_pdf))
471
+ ),
472
+ list(
473
+ name = "Heatmap",
474
+ contents = list(list(src = hmfile, kind = "image", download = hmfile_pdf))
475
+ ),
476
+ list(
477
+ name = "Distribution Table",
478
+ contents = do.call(c, lapply(
479
+ seq_along(cells_by),
480
+ function(i) list(
481
+ list(kind = "descr", content = paste0("Cells by: ", cells_by[i])),
482
+ list(kind = "table", data = list(nrows = 100), src = table_files[i])
483
+ )
484
+ ))
485
+ ),
486
+ h1 = info$h1,
487
+ h2 = info$h2,
488
+ ui = "tabs"
489
+ )
241
490
  }
242
491
 
243
492
  do_overlap <- function(section) {
244
- print(paste("- Running overlaps for section:", section))
493
+ log_info(paste("- Running overlaps for section:", section))
245
494
  overlap_cases <- overlaps[[section]]
246
495
  if (length(overlap_cases) < 2) {
247
- stop(paste0("Not enough cases for overlap for section: ", section))
496
+ stop(paste0(" Not enough cases for overlap for section: ", section))
248
497
  }
249
498
 
250
- sec_dir <- file.path(outdir, section)
499
+ sec_dir <- file.path(outdir, paste0("overlap - ", slugify(section)))
500
+ dir.create(sec_dir, showWarnings = FALSE)
251
501
  venn_plot <- file.path(sec_dir, "venn.png")
252
502
  venn_p <- ggVennDiagram(overlap_cases, label_percent_digit = 1) +
253
503
  scale_fill_distiller(palette = "Reds", direction = 1) +
@@ -256,13 +506,52 @@ do_overlap <- function(section) {
256
506
  print(venn_p)
257
507
  dev.off()
258
508
 
509
+ venn_plot_pdf <- gsub(".png$", ".pdf", venn_plot)
510
+ pdf(venn_plot_pdf, width = 10, height = 6)
511
+ print(venn_p)
512
+ dev.off()
513
+
259
514
  upset_plot <- file.path(sec_dir, "upset.png")
260
515
  upset_p <- upset(fromList(overlap_cases))
261
516
  png(upset_plot, res = 100, width = 800, height = 600)
262
517
  print(upset_p)
263
518
  dev.off()
519
+
520
+ upset_plot_pdf <- gsub(".png$", ".pdf", upset_plot)
521
+ pdf(upset_plot_pdf, width = 8, height = 6)
522
+ print(upset_p)
523
+ dev.off()
524
+
525
+ add_report(
526
+ list(
527
+ name = "Venn Plot",
528
+ contents = list(list(
529
+ kind = "image",
530
+ src = venn_plot,
531
+ download = venn_plot_pdf
532
+ ))
533
+ ),
534
+ list(
535
+ name = "UpSet Plot",
536
+ contents = list(list(
537
+ kind = "image",
538
+ src = upset_plot,
539
+ download = upset_plot_pdf
540
+ ))
541
+ ),
542
+ h1 = "Overlapping Groups",
543
+ h2 = section,
544
+ ui = "tabs"
545
+ )
264
546
  }
265
547
 
266
- cases <- expand_cases()
267
548
  sapply(sort(names(cases)), function(name) do_case(name, cases[[name]]))
549
+
550
+ unhit_overlaps <- setdiff(overlap, names(overlaps))
551
+ if (length(unhit_overlaps) > 0) {
552
+ log_warn("- No sections found for overlapping analysis: {paste(unhit_overlaps, collapse=', ')}")
553
+ log_warn(" Available sections: {paste(sections, collapse=', ')}")
554
+ }
268
555
  sapply(sort(names(overlaps)), do_overlap)
556
+
557
+ save_report(joboutdir)