Diff of /docs/conversion.Rmd [000000] .. [413088]

Switch to unified view

a b/docs/conversion.Rmd
1
---
2
title: "Conversion"
3
output: 
4
  html_document:
5
    toc: true
6
    toc_float:
7
      collapsed: false
8
      smooth_scroll: false
9
---
10
11
<style>
12
.title{
13
  display: none;
14
}
15
body {
16
  text-align: justify   
17
}
18
.center {
19
  display: block;
20
  margin-left: auto;
21
  margin-right: auto;
22
}
23
</style>
24
25
```{css, echo=FALSE}
26
.watch-out {
27
  color: black;
28
}
29
```
30
31
```{r setup, include=FALSE}
32
# use rmarkdown::render_site(envir = knitr::knit_global())
33
knitr::opts_chunk$set(highlight = TRUE, echo = TRUE)
34
```
35
36
<br>
37
38
# Conversion to Other Platforms
39
40
VoltRon is capable of end-to-end spatial data analysis for all levels of spatial resolutions, including those of single cell resolution. However, VoltRon provides a ecosystem friendly infrastructure where VoltRon objects could be transformed into data structures used by popular computational platforms such as [Seurat](https://satijalab.org/seurat/), [Squidpy](https://squidpy.readthedocs.io/en/stable/) and even [Zarr](http://vitessce.io/docs/data-file-types/#anndata-zarr) for interactive spatial data visualizatiob with [Vitessce](http://vitessce.io/).
41
42
For both **Seurat (R)** and **Squidpy (Python)**, we analyse readouts of the experiments conducted on example tissue sections analysed by the [Xenium In Situ](https://www.10xgenomics.com/platforms/xenium) platform. For more information on processing and analyzing Xenium datasets, check the [Cell/Spot Analysis](spotanalysis.html) tutorial.
43
44
<br>
45
46
## Seurat
47
48
We will first see how we can transform VoltRon objects into Seurat object and use built-in functions such as **FindAllMarkers** to visualize marker genes of clusters found by VoltRon. You can find the clustered Xenium data using VoltRon [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Cellanalysis/Xenium/Xenium_data_clustered.rds). 
49
50
```{r class.source="watch-out", eval = FALSE}
51
Xen_data <- readRDS("Xenium_data_clustered.rds")
52
SampleMetadata(Xen_data)
53
```
54
55
```
56
        Assay    Layer   Sample
57
Assay1 Xenium Section1 XeniumR1
58
Assay3 Xenium Section1 XeniumR2
59
```
60
61
<br>
62
63
We use the **as.Seurat** function to convert spatial assays of VoltRon into Seurat objects. Here, a Seurat object defines spatial components of cellular and subcellular assays as **FOV** objects, and we use the **type = "image"** argument to convert spatial coordinates of cells and molecules into individual FOV objects for each Xenium assay/layer in the VoltRon object.  
64
65
Please check the [Analysis of Image-based Spatial Data in Seurat](https://satijalab.org/seurat/articles/seurat5_spatial_vignette_2) tutorial for more information on analyzing FOV-based spatial data sets with Seurat. 
66
67
note: Use VoltRon::as.Seurat to avoid conflict with Seurat package's as.Seurat function
68
69
70
```{r class.source="watch-out", eval = FALSE}
71
library(Seurat)
72
Xen_data_seu <- VoltRon::as.Seurat(Xen_data, cell.assay = "Xenium", type = "image")
73
Xen_data_seu <- NormalizeData(Xen_data_seu)
74
Xen_data_seu
75
```
76
77
```
78
An object of class Seurat 
79
313 features across 283298 samples within 1 assay 
80
Active assay: Xenium (313 features, 0 variable features)
81
 1 layers present: counts
82
 2 dimensional reductions calculated: pca, umap
83
 2 spatial fields of view present: fov_Assay1 fov_Assay3
84
```
85
86
<br>
87
88
### Marker Analysis
89
90
Now that we converted VoltRon into a Seurat object, we can pick the **Clusters** metadata column indicating the clustering of cells and test for marker genes of each individual cluster. 
91
92
```{r class.source="watch-out", eval = FALSE}
93
Idents(Xen_data_seu) <- "Clusters"
94
markers <- FindAllMarkers(Xen_data_seu)
95
head(markers[order(markers$avg_log2FC, decreasing = TRUE),])
96
```
97
98
<div><pre><code style="font-size: 13px;">         p_val avg_log2FC pct.1 pct.2 p_val_adj cluster   gene
99
CPA3         0   7.343881 0.977 0.029         0      16   CPA3
100
CTSG         0   7.114698 0.878 0.011         0      16   CTSG
101
LILRA4.1     0   6.992717 0.939 0.015         0      19 LILRA4
102
ADIPOQ       0   6.860190 0.974 0.025         0       5 ADIPOQ
103
MS4A1        0   6.763083 0.919 0.027         0      17  MS4A1
104
BANK1        0   6.082192 0.889 0.037         0      17  BANK1</code></pre></div>
105
106
<br>
107
108
### Visualization
109
110
We can now pick top positive markers from each of these clusters prior to visualization.
111
112
```{r class.source="watch-out", eval = FALSE}
113
library(dplyr)
114
topmarkers <- markers %>%
115
  group_by(cluster) %>%
116
  top_n(n = 5, wt = avg_log2FC)
117
```
118
119
Here, VoltRon incorporates the unique markers learned by the **FindAllMarkers** function from Seurat and uses them to visualize the expression of these markers on heatmaps, and now we can also use these markers for annotating the clusters.   
120
121
```{r class.source="watch-out", eval = FALSE}
122
library(ComplexHeatmap)
123
marker_features <- unique(topmarkers$gene)
124
vrHeatmapPlot(Xen_data, features = marker_features, group.by = "Clusters", 
125
              show_row_names = TRUE, font.size = 10)
126
```
127
128
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_seurat_heatmap.png" class="center">
129
130
<br>
131
132
### Convert with Molecule Data
133
134
If defined, the **as.Seurat** function may also convert the molecule assay of the VoltRon object into a Seurat FOV object and allow visualizing molecules. You can find the Xenium VoltRon object with the molecule assay [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Cellanalysis/Xenium/Xen_R1.rds). 
135
136
```{r class.source="watch-out", eval = FALSE}
137
Xen_R1 <- readRDS("Xen_R1.rds")
138
SampleMetadata(Xen_R1)
139
```
140
141
```
142
            Assay    Layer   Sample
143
Assay1     Xenium Section1 XeniumR1
144
Assay2 Xenium_mol Section1 XeniumR1
145
```
146
147
<br>
148
149
We define both the cell level assay and the molecule level assay. 
150
151
```{r class.source="watch-out", eval = FALSE}
152
Xen_R1_seu <- as.Seurat(Xen_R1, cell.assay = "Xenium", molecule.assay = "Xenium_mol", type = "image")
153
```
154
155
<br>
156
157
Now we can visualize molecules alongside with cells.
158
159
```{r class.source="watch-out", eval = FALSE}
160
ImageDimPlot(Xen_R1_seu, fov = "fovAssay1", molecules = "PGR", group.by = "orig.ident", cols = "lightgrey", mols.size = 1)
161
```
162
163
<img width="60%" height="60%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_seurat_imagedimplot.png" class="center">
164
165
<br>
166
167
## SpatialExperiment
168
169
VoltRon can also convert objects in [SpatialExperiment](https://www.bioconductor.org/packages/release/bioc/html/SpatialExperiment.html) objects. We are going to use the Xenium data clustered using VoltRon [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Cellanalysis/Xenium/Xenium_data_clustered.rds).
170
171
```{r class.source="watch-out", eval = FALSE}
172
Xen_data <- readRDS("Xenium_data_clustered.rds")
173
SampleMetadata(Xen_data)
174
```
175
176
We use the **as.SpatialExperiment** function to convert spatial assays of VoltRon into SpatialExperiment objects. Please check the [Introduction to the SpatialExperiment class](https://www.bioconductor.org/packages/release/bioc/vignettes/SpatialExperiment/inst/doc/SpatialExperiment.html) tutorial for more information. 
177
178
```{r class.source="watch-out", eval = FALSE}
179
library(SpatialExperiment)
180
spe <- as.SpatialExperiment(Xen_data, assay = "Xenium")
181
```
182
183
Here we can parse the image and visualize.
184
185
```{r class.source="watch-out", eval = FALSE}
186
img <- imgRaster(spe, 
187
                 sample_id = "Assay1", 
188
                 image_id = "main")
189
plot(img)
190
```
191
192
<br>
193
194
## Squidpy (Anndata, h5ad)
195
196
A true ecosystem friendly computational platform should support data types across multiple computing environments. By allowing users to convert VoltRon objects into annotated data matrix formats such as [anndata](https://github.com/scverse/anndata), we can use built-in spatial data analysis methods available on [squidpy](https://squidpy.readthedocs.io/en/stable/).
197
198
You can find the clustered and the annotated Xenium data using VoltRon [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Cellanalysis/Xenium/Xenium_data_clustered_annotated.rds). 
199
200
Anndata objects wrapped on h5ad files are commonly used by the [scverse](https://www.nature.com/articles/s41587-023-01733-8) ecosystem for single cell analysis which bring together numeruous tools maintained and distributed by a large community effort. Both squidpy and [scanpy](https://scanpy.readthedocs.io/en/stable/) are currently available on scverse. 
201
202
```{r class.source="watch-out", eval = FALSE}
203
Xen_data <- readRDS("Xenium_data_clustered_annotated.rds")
204
as.AnnData(Xen_data, assay = "Xenium", file = "Xen_adata_annotated.h5ad")
205
```
206
207
<br>
208
209
### Configure Squidpy (scverse)
210
211
Here, we use the [reticulate](https://rstudio.github.io/reticulate/) package to call **scverse** module in Python through a prebuilt anaconda environment. However, any python installation with the scverse module can be incorporated by reticulate.   
212
213
```{r class.source="watch-out", eval = FALSE}
214
library(reticulate)
215
use_condaenv("scverse", required = T)
216
```
217
218
We import some other necessary modules such as pandas, scanpy and squidpy.
219
220
```{python class.source="watch-out", eval = FALSE}
221
from pathlib import Path
222
import numpy as np
223
import pandas as pd
224
import matplotlib.pyplot as plt
225
import seaborn as sns
226
import scanpy as sc
227
import squidpy as sq
228
sc.logging.print_header()
229
```
230
231
<br>
232
233
### Filter and Normalize 
234
235
We read the annotated Xenium object that was saved as an h5ad file using the **as.Anndata** function in VoltRon, and process before analysis. For more information using scanpy and squidpy on Xenium datasets, check the [Analyzing Xenium data](https://squidpy.readthedocs.io/en/stable/notebooks/tutorials/tutorial_xenium.html) tutorial at squidpy webpage. 
236
237
```{python class.source="watch-out", eval = FALSE}
238
adata = sc.read_h5ad("Xen_adata_annotated.h5ad")
239
adata.layers["counts"] = adata.X.copy()
240
sc.pp.normalize_total(adata, inplace=True)
241
sc.pp.log1p(adata)
242
```
243
244
<br>
245
246
### Visualize
247
248
We use the **squidpy.pl.spatial_scatter** functions available in squidpy to visualize the spatial localization of cell types of both Xenium replicates.
249
250
```{python class.source="watch-out", eval = FALSE}
251
fig, ax = plt.subplots(1, 2, figsize=(10, 7))
252
sq.pl.spatial_scatter(adata, library_key = "library_id", library_id = "Assay1", 
253
                      color=["CellType"], shape=None, size=1, img = False, ax=ax[0])
254
sq.pl.spatial_scatter(adata, library_key = "library_id", library_id = "Assay3", 
255
                      color=["CellType"], shape=None, size=1, img = False, ax=ax[1])
256
plt.show(ax)
257
```
258
259
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_anndata_spatial_scatter.png" class="center">
260
261
<br>
262
263
### Neighborhood Enrichment
264
265
We can now use high level spatially-aware functions available in squidpy. We first establish spatial neighbors using the delaunay graphs. The spatial graph and distances will be stored under **.obsp** attribute/matrix. 
266
267
```{python class.source="watch-out", eval = FALSE}
268
sq.gr.spatial_neighbors(adata, coord_type="generic", delaunay=True)
269
adata
270
```
271
272
```
273
AnnData object with n_obs × n_vars = 283298 × 313
274
    obs: 'Count', 'Assay', 'Layer', 'Sample', 'Clusters', 'CellType', 'library_id'
275
    uns: 'log1p', 'spatial_neighbors'
276
    obsm: 'spatial'
277
    layers: 'counts'
278
    obsp: 'spatial_connectivities', 'spatial_distances'
279
```
280
281
We can now conduct the permutation test for neighborhood enrichment across cell type pairs. 
282
283
```{python class.source="watch-out", eval = FALSE}
284
sq.gr.nhood_enrichment(adata, cluster_key="CellType")
285
```
286
287
```{python class.source="watch-out", eval = FALSE}
288
fig, ax = plt.subplots(1, 2, figsize=(13, 7))
289
sq.pl.nhood_enrichment(adata, cluster_key="CellType", figsize=(8, 8), 
290
                       title="Neighborhood enrichment adata", ax=ax[0])
291
sq.pl.spatial_scatter(adata, color="CellType", library_key = "library_id", 
292
                      library_id = "Assay1", shape=None, size=2, ax=ax[1])
293
plt.show(ax)
294
```
295
296
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_anndata_neighborhood.png" class="center">
297
298
<br>
299
300
## Vitessce (Anndata, zarr) 
301
 
302
In this section, we will transform VoltRon objects of Xenium data into zarr arrays, and use them for interactive visualization in [Vitessce](http://vitessce.io/). We should first download the vitessceR package which incorporates wrapper function to visualize zarr arrays interactively in R.
303
304
```{r class.source="watch-out", eval = FALSE}
305
install.packages("devtools")
306
devtools::install_github("vitessce/vitessceR")
307
```
308
309
<br>
310
311
You can find the clustered and annotated Xenium data using VoltRon [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Cellanalysis/Xenium/Xenium_data_clustered_annotated.rds). 
312
313
```{r class.source="watch-out", eval = FALSE}
314
Xen_data <- readRDS("Xenium_data_clustered_annotated.rds")
315
SampleMetadata(Xen_data)
316
```
317
318
```
319
        Assay    Layer   Sample
320
Assay1 Xenium Section1 XeniumR1
321
Assay2 Xenium Section1 XeniumR2
322
```
323
324
<br>
325
326
### Interactive Visualization
327
328
Now we can convert the VoltRon object into a zarr array using the **as.Zarr** function which will create the array in a specified location.
329
330
```{r class.source="watch-out", eval = FALSE}
331
as.AnnData(Xen_data, assays = "Assay1", 
332
           file = "xendata_clustered_annotated.zarr", flip_coordinates = TRUE)
333
```
334
335
We can use the zarr file directly in the **vrSpatialPlot** function to visualize the zarr array interactively in Rstudio viewer. The **reduction** arguement allows the umap of the Xenium data to be visualized alongside with the spatial coordinates of the Xenium cells.
336
337
```{r class.source="watch-out", eval = FALSE}
338
vrSpatialPlot("xendata_clustered_annotated.zarr", group.by = "CellType", reduction = "umap")
339
```
340
341
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_interactive.png" class="center">
342
<br>
343
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/conversions_interactive_zoom.png" class="center">