forked from drieslab/giotto_workshop_2024
-
Notifications
You must be signed in to change notification settings - Fork 0
/
03_session4.Rmd
395 lines (280 loc) · 13.8 KB
/
03_session4.Rmd
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# Interoperability with other frameworks
Iqra
August 7th 2024
Giotto facilitates seamless interoperability with various tools, including Seurat, AnnData, and SpatialExperiment. Below is a comprehensive tutorial on how Giotto interoperates with these other tools.
## Load Giotto object
To begin demonstrating the interoperability of a Giotto object with other frameworks, we first load the required libraries and a Giotto mini object. We then proceed with the conversion process:
```{r, eval = FALSE}
library(Giotto)
library(GiottoData)
```
Load a Giotto mini Visium object, which will be used for demonstrating interoperability.
```{r, eval = FALSE}
gobject <- GiottoData::loadGiottoMini("visium")
```
## Seurat
Giotto Suite provides interoperability between Seurat and Giotto, supporting both older and newer versions of Seurat objects. The four tailored functions are `giottoToSeuratV4()`, `seuratToGiottoV4()` for older versions, and `giottoToSeuratV5()`, `seuratToGiottoV5()` for Seurat v5, which includes subcellular and image information. These functions map Giotto's metadata, dimension reductions, spatial locations, and images to the corresponding slots in Seurat.
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/seurat.png")
```
### Conversion of Giotto Object to Seurat Object
To convert Giotto object to Seurat V5 object, we first load required libraries and use the function `giottoToSeuratV5()` function
```{r eval=FALSE}
library(Seurat)
library(SeuratData)
library(ggplot2)
library(patchwork)
library(dplyr)
```
Now we convert the Giotto object to a Seurat V5 object and create violin and spatial feature plots to visualize the RNA count data.
```{r eval=FALSE}
gToS <- giottoToSeuratV5(gobject = gobject,
spat_unit = "cell")
plot1 <- VlnPlot(gToS,
features = "nCount_rna",
pt.size = 0.1) +
NoLegend()
plot2 <- SpatialFeaturePlot(gToS,
features = "nCount_rna",
pt.size.factor = 2) +
theme(legend.position = "right")
wrap_plots(plot1, plot2)
```
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/1.png")
```
#### Apply SCTransform
We apply SCTransform to perform data transformation on the RNA assay: `SCTransform()` function.
```{r, eval=FALSE}
gToS <- SCTransform(gToS, assay = "rna", verbose = FALSE)
```
#### Dimension Reduction
We perform Principal Component Analysis (PCA), find neighbors, and run UMAP for dimensionality reduction and clustering on the transformed Seurat object:
```{r, eval=FALSE}
gToS <- RunPCA(gToS, assay = "SCT")
gToS <- FindNeighbors(gToS, reduction = "pca", dims = 1:30)
gToS <- RunUMAP(gToS, reduction = "pca", dims = 1:30)
```
### Conversion of Seurat object Back to Giotto Object
To Convert the Seurat Object back to Giotto object, we use the funcion `seuratToGiottoV5()`, specifying the spatial assay, dimensionality reduction techniques, and spatial and nearest neighbor networks.
```{r eval=FALSE}
giottoFromSeurat <- seuratToGiottoV5(sobject = gToS,
spatial_assay = "rna",
dim_reduction = c("pca", "umap"),
sp_network = "Delaunay_network",
nn_network = c("sNN.pca", "custom_NN" ))
```
#### Clustering and Plotting UMAP
Here we perform K-means clustering on the UMAP results obtained from the Seurat object:
```{r, eval=FALSE}
## k-means clustering
giottoFromSeurat <- doKmeans(gobject = giottoFromSeurat,
dim_reduction_to_use = "pca")
#Plot UMAP post-clustering to visualize kmeans
graph2 <- Giotto::plotUMAP(
gobject = giottoFromSeurat,
cell_color = "kmeans",
show_NN_network = TRUE,
point_size = 2.5
)
```
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/2.png")
```
#### Spatial CoExpression
We can also use the `binSpect` function to analyze spatial co-expression using the spatial network `Delaunay network` from the Seurat object and then visualize the spatial co-expression using the `heatmSpatialCorFeat()` function:
```{r eval=FALSE}
ranktest <- binSpect(giottoFromSeurat,
bin_method = "rank",
calc_hub = TRUE,
hub_min_int = 5,
spatial_network_name = "Delaunay_network")
ext_spatial_genes <- ranktest[1:300,]$feats
spat_cor_netw_DT <- detectSpatialCorFeats(
giottoFromSeurat,
method = "network",
spatial_network_name = "Delaunay_network",
subset_feats = ext_spatial_genes)
top10_genes <- showSpatialCorFeats(spat_cor_netw_DT,
feats = "Dsp",
show_top_feats = 10)
spat_cor_netw_DT <- clusterSpatialCorFeats(spat_cor_netw_DT,
name = "spat_netw_clus",
k = 7)
heatmSpatialCorFeats(
giottoFromSeurat,
spatCorObject = spat_cor_netw_DT,
use_clus_name = "spat_netw_clus",
heatmap_legend_param = list(title = NULL),
save_plot = TRUE,
show_plot = TRUE,
return_plot = FALSE,
save_param = list(base_height = 6, base_width = 8, units = 'cm'))
```
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/3.png")
```
## SpatialExperiment
For the Bioconductor group of packages, the SpatialExperiment data container handles data from spatial-omics experiments, including spatial coordinates, images, and metadata. Giotto Suite provides `giottoToSpatialExperiment()` and `spatialExperimentToGiotto()`, mapping Giotto's slots to the corresponding SpatialExperiment slots. Since SpatialExperiment can only store one spatial unit at a time, giottoToSpatialExperiment() returns a list of SpatialExperiment objects, each representing a distinct spatial unit.
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/spe.png")
```
To start the conversion of a Giotto mini Visium object to a SpatialExperiment object, we first load the required libraries.
```{r eval=FALSE}
library(SpatialExperiment)
library(ggspavis)
library(pheatmap)
library(scater)
library(scran)
library(nnSVG)
```
### Convert Giotto Object to SpatialExperiment Object
To convert the Giotto object to a SpatialExperiment object, we use the `giottoToSpatialExperiment()` function.
```{r eval=FALSE}
gspe <- giottoToSpatialExperiment(gobject)
```
The conversion function returns a separate SpatialExperiment object for each spatial unit. We select the first object for downstream use:
```{r eval=FALSE}
spe <- gspe[[1]]
```
#### Identify top spatially variable genes with nnSVG
We employ the nnSVG package to identify the top spatially variable genes in our SpatialExperiment object. Covariates can be added to our model; in this example, we use Leiden clustering labels as a covariate:
```{r eval=FALSE}
# One of the assays should be "logcounts"
# We rename the normalized assay to "logcounts"
assayNames(spe)[[2]] <- "logcounts"
# Create model matrix for leiden clustering labels
X <- model.matrix(~ colData(spe)$leiden_clus)
dim(X)
```
- Run nnSVG
This step will take several minutes to run
```{r eval=FALSE}
spe <- nnSVG(spe, X = X)
# Show top 10 features
rowData(spe)[order(rowData(spe)$rank)[1:10], ]$feat_ID
```
### Conversion of SpatialExperiment object back to Giotto
We then convert the processed SpatialExperiment object back into a Giotto object for further downstream analysis using the Giotto suite. This is done using the `spatialExperimentToGiotto` function, where we explicitly specify the spatial network from the SpatialExperiment object.
```{r, eval=FALSE}
giottoFromSPE <- spatialExperimentToGiotto(spe = spe,
python_path = NULL,
sp_network = "Delaunay_network")
giottoFromSPE <- spatialExperimentToGiotto(spe = spe,
python_path = NULL,
sp_network = "Delaunay_network")
print(giottoFromSPE)
```
#### Plotting top genes from nnSVG in Giotto
Now, we visualize the genes previously identified in the SpatialExperiment object using the nnSVG package within the Giotto toolkit, leveraging the converted Giotto object.
```{r, eval=FALSE}
ext_spatial_genes <- getFeatureMetadata(giottoFromSPE,
output = "data.table")
ext_spatial_genes <- ext_spatial_genes[order(ext_spatial_genes$rank)[1:10], ]$feat_ID
```
```{r, eval=FALSE}
spatFeatPlot2D(giottoFromSPE,
expression_values = "scaled_rna_cell",
feats = ext_spatial_genes[1:4],
point_size = 2)
```
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/4.png")
```
## AnnData
The `anndataToGiotto()` and `giottoToAnnData()` functions map the slots of the Giotto object to the corresponding locations in a Squidpy-flavored AnnData object. Specifically, Giotto’s expression slot maps to `adata.X`, spatial_locs to `adata.obsm`, cell_metadata to `adata.obs`, feat_metadata to `adata.var`, dimension_reduction to `adata.obsm`, and nn_network and spat_network to `adata.obsp`.
Images are currently not mapped between both classes. Notably, Giotto stores expression matrices within separate spatial units and feature types, while AnnData does not support this hierarchical data storage. Consequently, multiple AnnData objects are created from a Giotto object when there are multiple spatial unit and feature type pairs.
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/anndata.png")
```
### Load Required Libraries
To start, we need to load the necessary libraries, including `reticulate` for interfacing with Python.
```{r eval=FALSE}
library(reticulate)
```
### Specify Path for Results
First, we specify the directory where the results will be saved. Additionally, we retrieve and update Giotto instructions.
```{r eval=FALSE}
# Specify path to which results may be saved
results_directory <- "results/03_session4/giotto_anndata_conversion/"
instrs <- showGiottoInstructions(gobject)
mini_gobject <- replaceGiottoInstructions(gobject = gobject,
instructions = instrs)
```
#### Create Default kNN Network
We will create a k-nearest neighbor (kNN) network using mostly default parameters.
```{r eval=FALSE}
gobject <- createNearestNetwork(gobject = gobject,
spat_unit = "cell",
feat_type = "rna",
type = "kNN",
dim_reduction_to_use = "umap",
dim_reduction_name = "umap",
k = 15,
name = "kNN.umap")
```
### Giotto To AnnData
To convert the giotto object to AnnData, we use the Giotto's function `giottoToAnnData()`
```{r, eval=FALSE}
gToAnnData <- giottoToAnnData(gobject = gobject,
save_directory = results_directory)
```
Next, we import scanpy and perform a series of preprocessing steps on the AnnData object.
```{r, eval=FALSE}
scanpy <- import("scanpy")
adata <- scanpy$read_h5ad("results/03_session4/giotto_anndata_conversion/cell_rna_converted_gobject.h5ad")
# Normalize total counts per cell
scanpy$pp$normalize_total(adata, target_sum=1e4)
# Log-transform the data
scanpy$pp$log1p(adata)
# Perform PCA
scanpy$pp$pca(adata, n_comps=40L)
# Compute the neighborhood graph
scanpy$pp$neighbors(adata, n_neighbors=10L, n_pcs=40L)
# Run UMAP
scanpy$tl$umap(adata)
# Save the processed AnnData object
adata$write("results/03_session4/cell_rna_converted_gobject2.h5ad")
processed_file_path <- "results/03_session4/cell_rna_converted_gobject2.h5ad"
```
### Convert AnnData to Giotto
Finally, we convert the processed AnnData object back into a Giotto object for further analysis using Giotto.
```{r eval=FALSE}
giottoFromAnndata <- anndataToGiotto(anndata_path = processed_file_path)
```
#### UMAP Visualization
Now we plot the UMAP using the `GiottoVisuals::plotUMAP()` function that was calculated using Scanpy on the AnnData object.
```{r eval=FALSE}
Giotto::plotUMAP(
gobject = giottoFromAnndata,
dim_reduction_name = "umap.ad",
cell_color = "leiden_clus",
point_size = 3
)
```
```{r, echo=FALSE, out.width="80%", fig.align="center"}
knitr::include_graphics("img/03_session4/5.png")
```
## Create mini Vizgen object
```{r eval=FALSE}
mini_gobject <- loadGiottoMini(dataset = "vizgen",
python_path = NULL)
mini_gobject <- replaceGiottoInstructions(gobject = mini_gobject,
instructions = instrs)
```
```{r eval=FALSE}
mini_gobject <- createNearestNetwork(gobject = mini_gobject,
spat_unit = "aggregate",
feat_type = "rna",
type = "kNN",
dim_reduction_to_use = "umap",
dim_reduction_name = "umap",
k = 6,
name = "new_network")
```
Since we have multiple `spat_unit` and `feat_type` pairs, this function will create multiple `.h5ad` files, with their names returned. Non-default nearest or spatial network names will have their `key_added` terms recorded and saved in corresponding `.txt` files; refer to the documentation for details.
```{r eval=FALSE}
anndata_conversions <- giottoToAnnData(gobject = mini_gobject,
save_directory = results_directory,
python_path = NULL)
```