/
run_app.R
288 lines (284 loc) · 11.7 KB
/
run_app.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#' Run the spatialLIBD Shiny Application
#'
#' This function runs the shiny application that allows users to interact
#' with the Visium spatial transcriptomics data from LIBD (by default) or
#' any other data that you have shaped according to our object structure.
#'
#' If you don't have the pseudo-bulked analysis results like we computed them
#' in our project <https://doi.org/10.1038/s41593-020-00787-0> you can
#' set `sce_layer`, `modeling_results` and `sig_genes` to `NULL`. Doing so
#' will disable the pseudo-bulked portion of the web application. See the
#' examples for one such case as well as the vignette that describes how
#' you can use `spatialLIBD` with public data sets provided by 10x Genomics.
#' That vignette is available at
#' <http://research.libd.org/spatialLIBD/articles/TenX_data_download.html>.
#'
#' @param spe Defaults to the output of
#' `fetch_data(type = 'spe')`. This is a
#' [SpatialExperiment-class][SpatialExperiment::SpatialExperiment-class]
#' object with the spot-level Visium data and information required for
#' visualizing the histology. See [fetch_data()] for more details.
#' @inheritParams sig_genes_extract
#' @param sig_genes The output of [sig_genes_extract_all()] which is a table
#' in long format with the modeling results. You can subset this if the object
#' requires too much memory.
#' @param docs_path A `character(1)` specifying the path to the directory
#' containing the website documentation files. The directory has to contain
#' the files: `documentation_sce_layer.md`, `documentation_spe.md`,
#' `favicon.ico`, `footer.html` and `README.md`.
#' @param title A character(1) specifying the title for the app.
#' @param spe_discrete_vars A `character()` vector of discrete variables that
#' will be available to visualize in the app. Basically, the set of variables
#' with spot-level groups. They will have to be present in `colData(spe)`.
#' @param spe_continuous_vars A `character()` vector of continuous variables
#' that will be available to visualize in the app using the same scale
#' as genes. They will have to be present in `colData(sce)`.
#' @param default_cluster A `character(1)` with the name of the main cluster
#' (discrete) variable to use. It will have to be present in both `colData(spe)`
#' and `colData(sce_layer)`.
#' @param auto_crop_default A `logical(1)` specifying the default value for
#' automatically cropping the images. Set this to `FALSE` if your images do not
#' follow the Visium grid size expectations, which are key for enabling
#' auto-cropping.
#' @param ... Other arguments passed to the list of golem options for running
#' the application.
#'
#' @export
#' @importFrom shiny shinyApp
#' @importFrom golem with_golem_options
#' @return A [shiny.appobj][shiny::shiny.appobj] that contains the input data.
#'
#' @examples
#' \dontrun{
#' ## The default arguments will download the data from the web
#' ## using fetch_data(). If this is the first time you have run this,
#' ## the files will need to be cached by ExperimentHub. Otherwise it
#' ## will re-use the files you have previously downloaded.
#' if (enough_ram(4e9)) {
#' ## Obtain the necessary data
#' if (!exists("spe")) spe <- fetch_data("spe")
#'
#' ## Create the interactive website
#' run_app(spe)
#'
#' ## You can also run a custom version without the pseudo-bulked
#' ## layer information. This is useful if you are only interested
#' ## in the spatial transcriptomics features.
#' run_app(spe,
#' sce_layer = NULL, modeling_results = NULL, sig_genes = NULL,
#' title = "spatialLIBD without layer info"
#' )
#'
#' ## When using shinyapps.io aim for less than 3 GB of RAM with your
#' ## objects. Check each input object with:
#' ## lobstr::obj_size(x)
#' ## Do not create the large input objects on the app.R script before
#' ## subsetting them. Do this outside app.R since the app.R script is
#' ## run at shinyapps.io, so subsetting on that script to reduce the
#' ## memory load is pointless. You have to do it outside of app.R.
#' }
#'
#' ## How to run locally the spatialDLPFC Sp09 spatialLIBD app. That is,
#' ## from http://research.libd.org/spatialDLPFC/#interactive-websites
#' ## how to run https://libd.shinyapps.io/spatialDLPFC_Visium_Sp09 locally.
#' if (enough_ram(9e9)) {
#' ## Download the 3 main objects needed
#' spe <- fetch_data("spatialDLPFC_Visium")
#' sce_pseudo <- fetch_data("spatialDLPFC_Visium_pseudobulk")
#' modeling_results <- fetch_data("spatialDLPFC_Visium_modeling_results")
#'
#' ## These are optional commands to further reduce the memory required.
#' #
#' ## Keep only the "lowres" images. Reduces the object from 6.97 GB to 4.59 GB
#' # imgData(spe) <- imgData(spe)[imgData(spe)$image_id == "lowres", ]
#' ## Drop the regular counts (keep only the logcounts). Reduces the object
#' ## from 4.59 GB to 2.45 GB.
#' # counts(spe) <- NULL
#'
#' ## For sig_genes_extract_all() to work
#' sce_pseudo$spatialLIBD <- sce_pseudo$BayesSpace
#' ## Compute the significant genes
#' sig_genes <- sig_genes_extract_all(
#' n = nrow(sce_pseudo),
#' modeling_results = modeling_results,
#' sce_layer = sce_pseudo
#' )
#' ## Reduce the memory from 423.73 MB to 78.88 MB
#' lobstr::obj_size(sig_genes)
#' sig_genes$in_rows <- NULL
#' sig_genes$in_rows_top20 <- NULL
#' lobstr::obj_size(sig_genes)
#'
#' ## Specify the default variable
#' spe$BayesSpace <- spe$BayesSpace_harmony_09
#' ## Get all variables
#' vars <- colnames(colData(spe))
#'
#' ## Set default cluster colors
#' colors_BayesSpace <- Polychrome::palette36.colors(28)
#' names(colors_BayesSpace) <- c(1:28)
#' m <- match(as.character(spe$BayesSpace_harmony_09), names(colors_BayesSpace))
#' stopifnot(all(!is.na(m)))
#' spe$BayesSpace_colors <- spe$BayesSpace_harmony_09_colors <- colors_BayesSpace[m]
#'
#' ## Download documentation files we use
#' temp_www <- file.path(tempdir(), "www")
#' dir.create(temp_www)
#' download.file(
#' "https://raw.githubusercontent.com/LieberInstitute/spatialDLPFC/main/README.md",
#' file.path(temp_www, "README.md")
#' )
#' download.file(
#' "https://raw.githubusercontent.com/LieberInstitute/spatialDLPFC/main/code/deploy_app_k09/www/documentation_sce_layer.md",
#' file.path(temp_www, "documentation_sce_layer.md")
#' )
#' download.file(
#' "https://raw.githubusercontent.com/LieberInstitute/spatialDLPFC/main/code/deploy_app_k09/www/documentation_spe.md",
#' file.path(temp_www, "documentation_spe.md")
#' )
#' download.file(
#' "https://raw.githubusercontent.com/LieberInstitute/spatialDLPFC/main/img/favicon.ico",
#' file.path(temp_www, "favicon.ico")
#' )
#' download.file(
#' "https://raw.githubusercontent.com/LieberInstitute/spatialDLPFC/main/code/deploy_app_k09/www/footer.html",
#' file.path(temp_www, "footer.html")
#' )
#' list.files(temp_www)
#'
#' ## Run the app locally
#' run_app(
#' spe,
#' sce_layer = sce_pseudo,
#' modeling_results = modeling_results,
#' sig_genes = sig_genes,
#' title = "spatialDLPFC, Visium, Sp09",
#' spe_discrete_vars = c( # this is the variables for the spe object not the sce_pseudo object
#' "BayesSpace",
#' "ManualAnnotation",
#' vars[grep("^SpaceRanger_|^scran_", vars)],
#' vars[grep("^BayesSpace_harmony", vars)],
#' vars[grep("^BayesSpace_pca", vars)],
#' "graph_based_PCA_within",
#' "PCA_SNN_k10_k7",
#' "Harmony_SNN_k10_k7",
#' "manual_layer_label",
#' "wrinkle_type",
#' "BayesSpace_colors"
#' ),
#' spe_continuous_vars = c(
#' "sum_umi",
#' "sum_gene",
#' "expr_chrM",
#' "expr_chrM_ratio",
#' vars[grep("^VistoSeg_", vars)],
#' vars[grep("^layer_", vars)],
#' vars[grep("^broad_", vars)]
#' ),
#' default_cluster = "BayesSpace",
#' docs_path = temp_www
#' )
#' }
#' ## See also:
#' ## * https://github.com/LieberInstitute/spatialDLPFC/tree/main/code/deploy_app_k09
#' ## * https://github.com/LieberInstitute/spatialDLPFC/tree/main/code/deploy_app_k09_position
#' ## * https://github.com/LieberInstitute/spatialDLPFC/tree/main/code/deploy_app_k09_position_noWM
#' ## * https://github.com/LieberInstitute/spatialDLPFC/tree/main/code/deploy_app_k16
#' ## * https://github.com/LieberInstitute/spatialDLPFC/tree/main/code/analysis_IF/03_spatialLIBD_app
#' }
run_app <- function(
spe = fetch_data(type = "spe"),
sce_layer = fetch_data(type = "sce_layer"),
modeling_results = fetch_data(type = "modeling_results"),
sig_genes = sig_genes_extract_all(
n = nrow(sce_layer),
modeling_results = modeling_results,
sce_layer = sce_layer
),
docs_path = system.file("app", "www", package = "spatialLIBD"),
title = "spatialLIBD",
spe_discrete_vars = c(
"spatialLIBD",
"GraphBased",
"ManualAnnotation",
"Maynard",
"Martinowich",
paste0("SNN_k50_k", 4:28),
"SpatialDE_PCA",
"SpatialDE_pool_PCA",
"HVG_PCA",
"pseudobulk_PCA",
"markers_PCA",
"SpatialDE_UMAP",
"SpatialDE_pool_UMAP",
"HVG_UMAP",
"pseudobulk_UMAP",
"markers_UMAP",
"SpatialDE_PCA_spatial",
"SpatialDE_pool_PCA_spatial",
"HVG_PCA_spatial",
"pseudobulk_PCA_spatial",
"markers_PCA_spatial",
"SpatialDE_UMAP_spatial",
"SpatialDE_pool_UMAP_spatial",
"HVG_UMAP_spatial",
"pseudobulk_UMAP_spatial",
"markers_UMAP_spatial"
),
spe_continuous_vars = c(
"cell_count",
"sum_umi",
"sum_gene",
"expr_chrM",
"expr_chrM_ratio"
),
default_cluster = "spatialLIBD",
auto_crop_default = TRUE,
...) {
## Run the checks in the relevant order
stopifnot(length(default_cluster) == 1)
stopifnot(default_cluster %in% spe_discrete_vars)
spe <-
check_spe(spe,
variables = c(spe_discrete_vars, spe_continuous_vars)
)
## Check sce_layer and modeling_results if needed
if (!is.null(sce_layer)) {
sce_layer <-
check_sce_layer(sce_layer, variables = default_cluster)
modeling_results <- check_modeling_results(modeling_results)
## No need to check sig_genes since sig_genes_extract_all() will fail
}
## Check that the required documentation files exist
stopifnot(all(file.exists(file.path(
docs_path,
c(
"documentation_spe.md",
"favicon.ico",
"footer.html",
"README.md"
)
))))
if (!is.null(sce_layer)) {
## Check required files when sce_layer is present
stopifnot(file.exists(file.path(
docs_path, "documentation_sce_layer.md"
)))
}
with_golem_options(
app = shinyApp(ui = app_ui, server = app_server),
golem_opts = list(
spe = spe,
sce_layer = sce_layer,
modeling_results = modeling_results,
sig_genes = sig_genes,
docs_path = docs_path,
title = title,
spe_discrete_vars = spe_discrete_vars,
spe_continuous_vars = spe_continuous_vars,
default_cluster = default_cluster,
auto_crop_default = auto_crop_default,
...
)
)
}