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
biopipen/utils/misc.R DELETED
@@ -1,602 +0,0 @@
1
- # Misc utilities for R
2
- suppressPackageStartupMessages({
3
- library(logger)
4
- library(rlang)
5
- library(jsonlite)
6
- })
7
-
8
- .logger_layout <- layout_glue_generator(
9
- format = '{sprintf("%-7s", level)} [{format(time, "%Y-%m-%d %H:%M:%S")}] {msg}'
10
- )
11
- # print also debug messages, let pipen-poplog to filter
12
- log_threshold(DEBUG)
13
- log_layout(.logger_layout)
14
- log_appender(appender_stdout)
15
- tryCatch(log_errors(), error = function(e) {})
16
-
17
- .isBQuoted <- function(x) {
18
- # Check if x is backtick-quoted
19
- nchar(x) >= 2 && startsWith(x, "`") && endsWith(x, "`")
20
- }
21
-
22
- bQuote <- function(x) {
23
- if (.isBQuoted(x)) {
24
- x
25
- } else {
26
- paste0("`", x, "`")
27
- }
28
- }
29
-
30
- .escape_regex <- function(x) {
31
- # Escape regex special characters
32
- gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", x)
33
- }
34
-
35
- #' Slugify a string
36
- #' Remember also update the one in gsea.R
37
- #' @param x A string
38
- #' @param non_alphanum_replace Replace non-alphanumeric characters
39
- #' @param collapse_replace Collapse consecutive non-alphanumeric character replacements
40
- #' @param tolower Convert to lowercase
41
- #' @return A slugified string
42
- slugify <- function(x, non_alphanum_replace="-", collapse_replace=TRUE, tolower=FALSE) {
43
- subs <- list(
44
- "š"="s", "œ"="oe", "ž"="z", "ß"="ss", "þ"="y", "à"="a", "á"="a", "â"="a",
45
- "ã"="a", "ä"="a", "å"="a", "æ"="ae", "ç"="c", "è"="e", "é"="e", "ê"="e",
46
- "ë"="e", "ì"="i", "í"="i", "î"="i", "ï"="i", "ð"="d", "ñ"="n", "ò"="o",
47
- "ó"="o", "ô"="o", "õ"="o", "ö"="o", "ø"="oe", "ù"="u", "ú"="u", "û"="u",
48
- "ü"="u", "ý"="y", "ÿ"="y", "ğ"="g", "ı"="i", "ij"="ij", "ľ"="l", "ň"="n",
49
- "ř"="r", "ş"="s", "ť"="t", "ų"="u", "ů"="u", "ý"="y", "ź"="z", "ż"="z",
50
- "ſ"="s", "α"="a", "β"="b", "γ"="g", "δ"="d", "ε"="e", "ζ"="z", "η"="h",
51
- "θ"="th", "ι"="i", "κ"="k", "λ"="l", "μ"="m", "ν"="n", "ξ"="x", "ο"="o",
52
- "π"="p", "ρ"="r", "σ"="s", "τ"="t", "υ"="u", "φ"="ph", "χ"="ch", "ψ"="ps",
53
- "ω"="o", "ά"="a", "έ"="e", "ή"="h", "ί"="i", "ό"="o", "ύ"="u", "ώ"="o",
54
- "ϐ"="b", "ϑ"="th", "ϒ"="y", "ϕ"="ph", "ϖ"="p", "Ϛ"="st", "ϛ"="st", "Ϝ"="f",
55
- "ϝ"="f", "Ϟ"="k", "ϟ"="k", "Ϡ"="k", "ϡ"="k", "ϰ"="k", "ϱ"="r", "ϲ"="s",
56
- "ϳ"="j", "ϴ"="th", "ϵ"="e", "϶"="p"
57
- )
58
- # replace latin and greek characters to the closest english character
59
- for (k in names(subs)) {
60
- x <- gsub(k, subs[[k]], x)
61
- }
62
- x <- gsub("[^[:alnum:]_]", non_alphanum_replace, x)
63
- if(collapse_replace) x <- gsub(
64
- paste0(gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", non_alphanum_replace), "+"),
65
- non_alphanum_replace,
66
- x
67
- )
68
- if(tolower) x <- tolower(x)
69
- x
70
- }
71
-
72
- do_call <- function (what, args, quote = FALSE, envir = parent.frame()) {
73
-
74
- # source: Gmisc
75
- # author: Max Gordon <max@gforge.se>
76
-
77
- if (quote)
78
- args <- lapply(args, enquote)
79
-
80
- if (is.null(names(args)) ||
81
- is.data.frame(args)){
82
- argn <- args
83
- args <- list()
84
- }else{
85
- # Add all the named arguments
86
- argn <- lapply(names(args)[names(args) != ""], as.name)
87
- names(argn) <- names(args)[names(args) != ""]
88
- # Add the unnamed arguments
89
- argn <- c(argn, args[names(args) == ""])
90
- args <- args[names(args) != ""]
91
- }
92
-
93
- if (inherits(x = what, what = "character")){
94
- if(is.character(what)){
95
- fn <- strsplit(what, "[:]{2,3}")[[1]]
96
- what <- if(length(fn)==1) {
97
- get(fn[[1]], envir=envir, mode="function")
98
- } else {
99
- get(fn[[2]], envir=asNamespace(fn[[1]]), mode="function")
100
- }
101
- }
102
- call <- as.call(c(list(what), argn))
103
- }else if (inherits(x = what, "function")){
104
- f_name <- deparse(substitute(what))
105
- call <- as.call(c(list(as.name(f_name)), argn))
106
- args[[f_name]] <- what
107
- }else if (inherits(x = what, what="name")){
108
- call <- as.call(c(list(what, argn)))
109
- }
110
-
111
- eval(call,
112
- envir = args,
113
- enclos = envir)
114
-
115
- }
116
-
117
- #' Save the plot into multiple formats
118
- #'
119
- #' @param plot The plot object
120
- #' @param prefix The prefix of the file
121
- #' @param formats The formats to save
122
- #' @param bg The background color
123
- #' @param devpars The device parameters
124
- #' @export
125
- save_plot <- function(plot, prefix, devpars = NULL, bg = "white", formats = c("png", "pdf")) {
126
- devpars <- devpars %||% list()
127
- devpars$res <- devpars$res %||% 100
128
- if (!is.null(attr(plot, "width"))) {
129
- devpars$width <- devpars$width %||% (attr(plot, "width") * devpars$res)
130
- devpars$height <- devpars$height %||% (attr(plot, "height") * devpars$res)
131
- } else {
132
- devpars$width <- devpars$width %||% 800
133
- devpars$height <- devpars$height %||% 600
134
- }
135
-
136
- old_dev <- grDevices::dev.cur()
137
- for (fmt in formats) {
138
- filename = paste0(prefix, ".", fmt)
139
- dev <- ggplot2:::plot_dev(fmt, filename, dpi = devpars$res)
140
- dim <- ggplot2:::plot_dim(c(devpars$width, devpars$height), units = "px", limitsize = FALSE, dpi = devpars$res)
141
- dev(filename = filename, width = dim[1], height = dim[2], bg = bg)
142
- print(plot)
143
- grDevices::dev.off()
144
- }
145
- on.exit(utils::capture.output({
146
- if (old_dev > 1) grDevices::dev.set(old_dev) # restore old device unless null device
147
- }))
148
- }
149
-
150
- #' Save the code to generate the data
151
- #'
152
- #' @param code The code
153
- #' @param plot The plot object
154
- #' @param setup The setup code to generate the plot
155
- #' @param prefix The prefix of the file
156
- #' @param ... Additional data frame to save
157
- #'
158
- #' @export
159
- save_plotcode <- function(...) UseMethod("save_plotcode")
160
-
161
- save_plotcode.character <- function(code, prefix, ..., envir = parent.frame()) {
162
- codedir <- paste0(prefix, ".code")
163
- dir.create(codedir, showWarnings = FALSE)
164
- codefile <- file.path(codedir, "plot.R")
165
- writeLines(code, codefile)
166
- save(..., file = file.path(codedir, "data.RData"), envir = envir)
167
-
168
- zip_file <- paste0(prefix, ".code.zip")
169
- zip::zip(zip_file, c("plot.R", "data.RData"), root = codedir)
170
- unlink(codedir, recursive = TRUE)
171
- }
172
-
173
- save_plotcode.ggplot <- function(plot, setup, prefix, ..., envir = parent.frame()) {
174
- if (is.null(plot$logs)) {
175
- stop("The plot object does not have logs, did you use gglogger?")
176
- }
177
- code <- plot$logs$gen_code(setup = setup)
178
- save_plotcode(code, prefix, ..., envir = envir)
179
- }
180
-
181
- #' Set the default value of a key in a list
182
- #'
183
- #' @param x A list
184
- #' @param ... A list of key-value pairs
185
- #' @return The updated list
186
- #' @export
187
- list_setdefault <- function(x, ...) {
188
- # Set the default value of a key in a list
189
- x <- x %||% list()
190
-
191
- stopifnot(is.list(x))
192
- y <- list(...)
193
- for (k in names(y)) {
194
- if (!k %in% names(x)) {
195
- # x[[k]] <- y[[k]]
196
- x <- c(x, y[k])
197
- }
198
- }
199
- x
200
- }
201
-
202
- #' Update a list with another list
203
- #'
204
- #' @param x A list
205
- #' @param y A list
206
- #' @param depth The depth to update, -1 means update all
207
- #' @return The updated list
208
- #' @export
209
- list_update <- function(x, y, depth = -1L) {
210
- # Update the value in x from y
211
- x <- x %||% list()
212
- y <- y %||% list()
213
-
214
- for (k in names(y)) {
215
- if (is.null(y[[k]])) {
216
- x[[k]] <- NULL
217
- x <- c(x, y[k])
218
- } else if (is.list(x[[k]]) && is.list(y[[k]]) && depth != 0L) {
219
- x[[k]] <- list_update(x[[k]], y[[k]], depth - 1L)
220
- } else {
221
- x[[k]] <- y[[k]]
222
- }
223
- }
224
- x
225
- }
226
-
227
- #’ Biopipen palette
228
- #'
229
- #’ @param alpha The alpha value
230
- #’ @return A palette function
231
- #' @export
232
- pal_biopipen <- function(alpha = 1) {
233
- if (alpha > 1L | alpha <= 0L) stop("alpha must be in (0, 1]")
234
- colors <- c(
235
- "#ec3f3f", "#009e73", "#008ad8", "#cc79a7",
236
- "#e69f00", "#50cada", "#f0e442", "#a76ce7",
237
- "#ff864d", "#45e645", "#3699b5", "#ffdcda",
238
- "#d55e00", "#778ba6", "#c37b35", "#bc28ff"
239
- )
240
- colors <- scales::alpha(colors, alpha)
241
- function(n) {
242
- if (n <= length(colors)) {
243
- colors[1:n]
244
- } else {
245
- out_colors <- colors
246
- out_alpha <- 1.0
247
- while(length(out_colors) < n) {
248
- out_alpha <- out_alpha - 0.3
249
- out_colors <- c(out_colors, scales::alpha(colors, out_alpha))
250
- }
251
- out_colors[1:n]
252
- }
253
- }
254
- }
255
-
256
- scale_color_biopipen <- function(alpha = 1, ...) {
257
- ggplot2::discrete_scale("colour", "biopipen", pal_biopipen(alpha), ...)
258
- }
259
-
260
- scale_colour_biopipen <- scale_color_biopipen
261
-
262
- scale_fill_biopipen <- function(alpha = 1, ...) {
263
- ggplot2::discrete_scale("fill", "biopipen", pal_biopipen(alpha), ...)
264
- }
265
-
266
- .report <- list(
267
- # h1 => list(
268
- # h2 => list(
269
- # h3#1 => list(ui1 => list(content11, content12)),
270
- # h3#2 => list(ui2 => list(content21, content22))
271
- # )
272
- # )
273
- )
274
-
275
- add_report <- function(..., h1, h2 = "#", h3 = "#", ui = "flat") {
276
- if (is.null(.report[[h1]])) {
277
- .report[[h1]] <<- list()
278
- }
279
- if (is.null(.report[[h1]][[h2]])) {
280
- .report[[h1]][[h2]] <<- list()
281
- }
282
- if (is.null(.report[[h1]][[h2]][[h3]])) {
283
- .report[[h1]][[h2]][[h3]] <<- list()
284
- }
285
- if (is.null(.report[[h1]][[h2]][[h3]][[ui]])) {
286
- .report[[h1]][[h2]][[h3]][[ui]] <<- list()
287
- }
288
- content = list(...)
289
- for (i in seq_along(content)) {
290
- .report[[h1]][[h2]][[h3]][[ui]] <<- c(
291
- .report[[h1]][[h2]][[h3]][[ui]],
292
- list(content[[i]])
293
- )
294
- }
295
- }
296
-
297
- save_report <- function(path, clear = TRUE) {
298
- if (dir.exists(path)) {
299
- path <- file.path(path, "report.json")
300
- }
301
-
302
- writeLines(toJSON(.report, pretty = TRUE, auto_unbox = TRUE), path)
303
- if (clear) {
304
- .report <<- list()
305
- }
306
- }
307
-
308
-
309
- # Escape html
310
- html_escape <- function(text) {
311
- if (is.null(text)) { return("") }
312
- text <- gsub("&", "&amp;", text)
313
- text <- gsub("<", "&lt;", text)
314
- text <- gsub(">", "&gt;", text)
315
- text <- gsub("\"", "&quot;", text)
316
- text <- gsub("'", "&#039;", text)
317
- text
318
- }
319
-
320
- #' Expand the cases with default values
321
- #' If a case has a key `each`, then it will be expanded by `expand_each`
322
- #'
323
- #' @param cases A list of cases
324
- #' @param defaults A list of default values
325
- #' @param expand_each A function to expand each case, if NULL, then the `each` key will be ignored.
326
- #' The function should take two arguments, `name` and `case`, and return a list of expanded cases.
327
- #' @return A list of expanded cases
328
- #' @export
329
- expand_cases <- function(cases, defaults, expand_each = NULL) {
330
- if (is.null(cases) || length(cases) == 0) {
331
- filled_cases <- list(DEFAULT = defaults)
332
- } else {
333
- filled_cases <- list()
334
- for (name in names(cases)) {
335
- case <- list_update(defaults, cases[[name]], depth = 5L)
336
- filled_cases[[name]] <- case
337
- }
338
- }
339
-
340
- if (is.null(expand_each)) {
341
- return(filled_cases)
342
- }
343
-
344
- stopifnot(is.function(expand_each))
345
-
346
- outcases <- list()
347
- for (name in names(filled_cases)) {
348
- case <- filled_cases[[name]]
349
- each_cases <- expand_each(name, case)
350
- outcases <- c(outcases, each_cases)
351
- }
352
- outcases
353
- }
354
-
355
- #' Create information for a casename
356
- #'
357
- #' @param casename A casename
358
- #' @param cases Used to check if there is only a single section in the cases
359
- #' @param section_key The key to check, default is `section`
360
- #' @param section The default section if no section if provided in the casename
361
- #' @param sep The separator in casename to split section and casename
362
- #' @param create Create the directory if not exists
363
- #' @return A list of information, including `casedir`, `section`, `case`,
364
- #' `section_slug`, `case_slug` and the original `casename`.
365
- #' @export
366
- casename_info <- function(
367
- casename, cases, outdir,
368
- section_key = "section",
369
- section = NULL,
370
- sep = "::",
371
- case_type = c("dir", "prefix"),
372
- create = FALSE
373
- ) {
374
- section <- section %||% "DEFAULT"
375
- case_type <- match.arg(case_type)
376
- # CR_vs_PD_in_BL:seurat_clusters - IM IL1
377
- sec_case_names <- strsplit(casename, sep)[[1]]
378
- # seurat_clusters - IM IL1
379
- # In case we have more than one colon
380
- cname <- paste(sec_case_names[-1], collapse = "::")
381
- if (length(cname) == 0 || nchar(cname) == 0) {
382
- # no sep
383
- cname <- casename
384
- } else {
385
- section <- sec_case_names[1]
386
- }
387
- single_section <- length(unique(sapply(cases, function(x) x[[section_key]]))) == 1
388
-
389
- out <- list(
390
- casename = casename,
391
- section = section,
392
- case = cname,
393
- section_slug = slugify(section),
394
- case_slug = slugify(cname),
395
- h1 = ifelse(
396
- single_section && section == "DEFAULT",
397
- html_escape(cname),
398
- html_escape(ifelse(single_section, paste0(section, ": ", cname), section))
399
- ),
400
- h2 = ifelse(
401
- single_section && section == "DEFAULT",
402
- "#",
403
- ifelse(single_section, "#", html_escape(cname))
404
- )
405
- )
406
-
407
- if (case_type == "dir") {
408
- if (single_section && section == "DEFAULT") {
409
- out$casedir <- file.path(outdir, out$case_slug)
410
- } else {
411
- out$casedir <- file.path(outdir, out$section_slug, out$case_slug)
412
- }
413
- if (create) {
414
- dir.create(out$casedir, showWarnings = FALSE, recursive = TRUE)
415
- }
416
- } else {
417
- if (single_section && section == "DEFAULT") {
418
- out$caseprefix <- file.path(outdir, out$case_slug)
419
- } else {
420
- out$caseprefix <- file.path(outdir, out$section_slug, out$case_slug)
421
- if (create) {
422
- dir.create(file.path(outdir, out$section_slug), showWarnings = FALSE, recursive = TRUE)
423
- }
424
- }
425
- }
426
- out
427
- }
428
-
429
- run_command <- function(
430
- cmd,
431
- fg = FALSE,
432
- wait = TRUE,
433
- print_command = TRUE,
434
- print_command_handler = cat,
435
- ...
436
- ) {
437
- if (print_command) {
438
- print_command_handler("RUNNING COMMAND:\n")
439
- print_command_handler(paste0(" ", paste(cmd, collapse = " "), "\n\n"))
440
- }
441
-
442
- kwargs <- list(...)
443
- stdin <- kwargs$stdin %||% ""
444
- stdout <- kwargs$stdout %||% ""
445
- stderr <- kwargs$stderr %||% ""
446
- input <- kwargs$input %||% NULL
447
- k_env <- kwargs$env %||% list()
448
- env <- ""
449
- if (is.list(k_env)) {
450
- for (k in names(env)) { env <- paste0(env, k, "=", k_env[[k]], ";")}
451
- } else {
452
- env <- k_env
453
- }
454
- if (fg) {
455
- stdout <- ""
456
- stderr <- ""
457
- } else {
458
- if (stdout == "") { stdout <- FALSE }
459
- }
460
-
461
- command = cmd[1]
462
- args = cmd[-1]
463
- out <- system2(
464
- command,
465
- args = args,
466
- stdout = stdout,
467
- stderr = stderr,
468
- stdin = stdin,
469
- env = env,
470
- wait = wait,
471
- input = input
472
- )
473
- if (!isTRUE(stdout) && !isTRUE(stderr)) {
474
- if(out != 0) stop(sprintf("Command failed with exit code %s", out))
475
- if (!fg) { return(out) }
476
- } else {
477
- status <- attr(out, "status")
478
- if (is.integer(status) && status != 0) {
479
- stop(sprintf("Command failed: code (%s): %s", status, out))
480
- }
481
- return(out)
482
- }
483
- }
484
-
485
- #' Expand the dims usually used in single-cell analysis to specific dimensions
486
- #'
487
- #' @param dims The dimensions to expand
488
- #' @return A vector of expanded dimensions
489
- #' @export
490
- #' @examples
491
- #' expand_dims(NULL) # c(1, 2)
492
- #' expand_dims(1:2) # c(1, 2)
493
- #' expand_dims(1) # c(1)
494
- #' expand_dims("1:2") # c(1, 2)
495
- #' expand_dims("1") # c(1)
496
- #' # dash works as the same as colon
497
- #' expand_dims("1-3") # c(1, 2, 3)
498
- #' expand_dims("1,3") # c(1, 3)
499
- #' expand_dims("1,3:5") # c(1, 3, 4, 5)
500
- #' expand_dims(c(1, "3:5", 7)) # c(1, 3, 4, 5, 7)
501
- expand_dims <- function(dims, default = 1:2) {
502
- if (is.null(dims)) {
503
- return(default)
504
- }
505
- if (is.numeric(dims)) {
506
- return(dims)
507
- }
508
- dims <- unlist(strsplit(dims, ","))
509
- out <- c()
510
- for (d in dims) {
511
- if (grepl(":", d)) {
512
- d <- unlist(strsplit(d, ":"))
513
- d <- as.integer(d[1]):as.integer(d[2])
514
- } else if (grepl("-", d)) {
515
- d <- unlist(strsplit(d, "-"))
516
- d <- as.integer(d[1]):as.integer(d[2])
517
- } else {
518
- d <- as.integer(d)
519
- }
520
- out <- c(out, d)
521
- }
522
- out
523
- }
524
-
525
-
526
- #' Get plotthis function from plot_type
527
- #'
528
- #' @param plot_type The plot type
529
- #' @param gglogger_register Register the plotthis function to gglogger
530
- #' @param return_name Return the name of the function instead of the function
531
- #' @return The plotthis function
532
- #' @export
533
- get_plotthis_fn <- function(plot_type, gglogger_register = TRUE, return_name = FALSE) {
534
- fn_name <- switch(plot_type,
535
- hist = "Histogram",
536
- histo = "Histogram",
537
- histogram = "Histogram",
538
- featuredim = "FeatureDimPlot",
539
- splitbar = "SplitBarPlot",
540
- enrichmap = "EnrichMap",
541
- enrichnet = "EnrichNetwork",
542
- enrichnetwork = "EnrichNetwork",
543
- gsea = "GSEAPlot",
544
- gseasummary = "GSEASummaryPlot",
545
- gseasum = "GSEASummaryPlot",
546
- heatmap = "Heatmap",
547
- network = "Network",
548
- pie = "PieChart",
549
- wordcloud = "WordCloudPlot",
550
- venn = "VennDiagram",
551
- paste0(tools::toTitleCase(plot_type), "Plot")
552
- )
553
- if (return_name) {
554
- return(fn_name)
555
- }
556
- fn <- tryCatch({
557
- utils::getFromNamespace(fn_name, "plotthis")
558
- }, error = function(e) {
559
- stop("Unknown plot type: ", plot_type)
560
- })
561
-
562
- if (gglogger_register) {
563
- gglogger::register(fn, fn_name)
564
- } else {
565
- fn
566
- }
567
- }
568
-
569
-
570
- #' Extract variables from a named list
571
- #'
572
- #' @param x A named list
573
- #' @param ... The names of the variables
574
- #' @param keep Keep the extracted variables in the list
575
- #' @param env The environment to assign the extracted variables
576
- #' @return The list with/ithout the extracted variables
577
- #'
578
- #' @export
579
- extract_vars <- function(x, ..., keep = FALSE, env = parent.frame()) {
580
- stopifnot("extract_vars: 'x' must be a named list" = is.list(x) && !is.null(names(x)))
581
- vars <- list(...)
582
- if (is.null(names(vars))) {
583
- names(vars) <- unlist(vars)
584
- }
585
- for (i in seq_along(vars)) {
586
- if (nchar(names(vars)[i]) == 0) {
587
- names(vars)[i] <- vars[[i]]
588
- }
589
- }
590
- # list2env?
591
- for (n in names(vars)) {
592
- if (!n %in% names(x)) {
593
- stop(sprintf("Variable '%s' not found in the list", n))
594
- }
595
- assign(vars[[n]], x[[n]], envir = env)
596
- if (!isTRUE(keep)) {
597
- x[[n]] <- NULL
598
- }
599
- }
600
-
601
- x
602
- }