a b/docs/registration.Rmd
1
---
2
title: "Image Registration"
3
output: 
4
  html_document:
5
    toc: true
6
    toc_depth: 5
7
    toc_float:
8
      collapsed: false
9
      smooth_scroll: true
10
---
11
12
<style>
13
.title{
14
  display: none;
15
}
16
body {
17
  text-align: justify
18
}
19
.center {
20
  display: block;
21
  margin-left: auto;
22
  margin-right: auto;
23
}
24
</style>
25
26
```{css, echo=FALSE}
27
.watch-out {
28
  color: black;
29
}
30
```
31
32
```{r setup, include=FALSE}
33
# use rmarkdown::render_site(envir = knitr::knit_global())
34
knitr::opts_chunk$set(highlight = TRUE, echo = TRUE)
35
```
36
37
<br>
38
39
# Spatial Data Alignment
40
41
Spatial genomic technologies often generate diverse images and spatial readouts, even though the tissue slices are from adjacent sections of a single tissue block. Hence, the alignment of images and spatial coordinates across tissue sections are of utmost importance to dissect the correct spatial closeness across these sections. 
42
43
VoltRon allows users to **align spatial omics datasets of these serial sections** for data transfer and 3 dimensional stack alignment. The order of the tissue/sample slices should be provided by the user. VoltRon provides a fully embedded **shiny application** to either automatically or manually align images. The automatic alignment is achieved with the **OpenCV**'s C++ library fully embedded in the VoltRon package.
44
45
<table>
46
<tbody>
47
  <tr style = "vertical-align: center">
48
  <td style = "width:43%; vertical-align: center"> <img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/manualregistration.png" class="center"></td>
49
  <td style = "width:43%; vertical-align: center"> <img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/autoregistration.png" class="center"></td>
50
  </tr>
51
</tbody>
52
</table>
53
54
<br>
55
56
## Alignment of Xenium and Visium 
57
58
In this use case, we will align **immunofluorescence (IF)** and **H&E images** of the **Xenium In Situ** and **Visium CytAssist** platforms readouts. Three tissue sections are derived from a single formalin-fixed, paraffin-embedded (FFPE) breast cancer tissue block. A 5 $\mu$m section was taken for Visium CytAssist and two replicate 5 $\mu$m sections were taken for the Xenium replicates. More information on the spatial datasets and the study can be also be found on the [BioArxiv preprint](https://www.biorxiv.org/content/10.1101/2022.10.06.510405v1).
59
 
60
You can download the Xenium and Visium readouts from the [10x Genomics website](https://www.10xgenomics.com/products/xenium-in-situ/preview-dataset-human-breast) (specifically, import **In Situ Replicate 1/2 and Visium Spatial**). Alternatively, you can **download a zipped collection of three Visium and Xenium readouts** from [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/10X_Xenium_Visium.zip). 
61
62
VoltRon includes built-in functions for converting readouts from both Xenium and Visium platforms into VoltRon objects. We will import both Xenium replicates alongside with the Visium CytAssist data so that we can register images of these assays and merge them into one VoltRon object. 
63
64
```{r eval = FALSE, class.source="watch-out"}
65
library(VoltRon)
66
Xen_R1 <- importXenium("Xenium_R1/outs", sample_name = "XeniumR1")
67
Xen_R2 <- importXenium("Xenium_R2/outs", sample_name = "XeniumR2")
68
Vis <- importVisium("Visium/", sample_name = "VisiumR1")
69
```
70
71
Before moving on to image alignment, we can inspect both Xenium and Visium images. We use the **vrImages** function to call and visualize reference images of all VoltRon objects. 
72
73
```{r eval = FALSE, class.source="watch-out"}
74
vrImages(Xen_R1)
75
vrImages(Xen_R2)
76
vrImages(Vis)
77
```
78
79
<table>
80
<tbody>
81
  <tr style = "vertical-align: center">
82
  <td style = "width:33%; vertical-align: center"> <img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr1.png" class="center"></td>
83
  <td style = "width:33%; vertical-align: center"> <img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr2.png" class="center"></td>
84
  <td style = "width:33%; vertical-align: center"> <img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/visium.png" class="center"></td>
85
  </tr>
86
</tbody>
87
</table>
88
89
<br>
90
91
Although images of the first Xenium replicate and the Visium assay are workable, we have to adjust the brightness of the second Xenium replicate before image alignment. You can use **modulateImage** function to change the brightness and` saturation of the reference image of this VoltRon object. This functionality is optional for VoltRon objects and should be used when images require further adjustments. 
92
93
```{r eval = FALSE, class.source="watch-out"}
94
Xen_R2 <- modulateImage(Xen_R2, brightness = 800)
95
vrImages(Xen_R2)
96
```
97
98
<img width="40%" height="40%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr2_new.png" class="center">
99
100
<br>
101
102
### Automated Image Alignment
103
104
In order to achieve data transfer and integration across these two modalities, we need to first make sure that spatial coordinates of these three datasets are perfectly aligned. To this end, we will make use of the **registerSpatialData** function which calls a **shiny app** embedded into VoltRon. The function takes a single list as an input where the order of VoltRon objects in the list should be the same as the **order of serial sections**. 
105
106
We will make use of the **registerSpatialData** function to **automatically register two Xenium assays onto the Visium assay**. The Visium CytAssist image (or the **image on the center** of the list) would be taken as the image of reference, and hence all other images (or spatial datasets) are to be aligned to the Visium data. Then, registerSpatialData will return a list of VoltRon objects whose assays include both the original and registered versions of spatial coordinates. The shiny app will provide **two images** for this task: 
107
108
* An image that shows the matched points across two images, and 
109
* A slideshow with of the reference and registered images that demonstrates the alignment accuracy. 
110
111
We will select **FLANN** method for automated alignment which incorporates the **SIFT** method for automated keypoints selection and utilizes the **Fast library for Approximate Nearest Neighbors (FLANN) algorithm** for matching keypoints. **NOTE:** For better alignment performance, users can incorporate image manipulation tools above each image and sync images into the same orientation by rotating, flipping (horizontally and vertically) and negating these images. We always negate DAPI images to align them onto H&E images.  
112
113
```{r class.source="watch-out", eval = FALSE} 
114
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2))
115
```
116
117
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/XeniumVisiumRegistration_FLANN.gif" class="center">
118
119
<br>
120
121
You can save and use the same parameters later, and reproduce the alignment without choosing parameters the second time. 
122
123
```{r class.source="watch-out", eval = FALSE} 
124
mapping_parameters <- xen_reg$mapping_parameters
125
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
126
                               mapping_parameters = mapping_parameters)
127
```
128
129
You can find a presaved set of parameters [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/mapping_parameters.rds).
130
131
```{r class.source="watch-out", eval = FALSE} 
132
mapping_parameters <- readRDS("mapping_parameters.rds")
133
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
134
                               mapping_parameters = mapping_parameters)
135
```
136
137
If the pre-saved parameters are available, the registration can also be performed without using the shiny app. By using **interactive = FALSE**, we can register images and VoltRon objects directly. 
138
139
```{r class.source="watch-out", eval = FALSE} 
140
mapping_parameters <- xen_reg$mapping_parameters
141
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
142
                               mapping_parameters = mapping_parameters, 
143
                               interactive = FALSE)
144
```
145
146
In case there are only two images, **the first image will be taken as the image of reference**. Hence, in order to align the first Xenium Replicate to the Visium dataset, we can create a list of two VoltRon objects as given below. 
147
148
```{r class.source="watch-out", eval = FALSE} 
149
xen_reg <- registerSpatialData(object_list = list(Vis, Xen_R2))
150
```
151
152
<br>
153
154
### Manual Image Alignment
155
156
Given the diverse types of tissue sections and their complex morphology, we need an alternative alignment strategy if automated registration may fail. VoltRon allows **manually choosing keypoints (or landmarks)** on images that are locations on the tissue with structural/morphological similarity. Similar to the automated mode, **the image on the center** will be taken as reference and the users will be able to observe the quality of the registration and remove/reselect keypoints as they see fit. 
157
158
```{r class.source="watch-out", eval = FALSE} 
159
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2))
160
```
161
162
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/XeniumVisiumRegistration.gif" class="center">
163
164
<br>
165
166
You can save and use the same keypoints later, and reproduce the manual alignment without choosing keypoints for the second time. 
167
168
```{r class.source="watch-out", eval = FALSE} 
169
mapping_parameters <- xen_reg$mapping_parameters
170
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
171
                               mapping_parameters = mapping_parameters)
172
```
173
174
You can find a presaved set of parameters with selected manual keypoints  [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/mapping_parameters_manual.rds).
175
176
```{r class.source="watch-out", eval = FALSE} 
177
mapping_parameters <- readRDS("mapping_parameters_manual.rds")
178
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
179
                               mapping_parameters = mapping_parameters)
180
```
181
182
If the pre-saved keypoints are available with parameters, the registration can also be performed without using the shiny app. By using **interactive = FALSE**, we can register images and VoltRon objects directly. 
183
184
```{r class.source="watch-out", eval = FALSE} 
185
mapping_parameters <- xen_reg$mapping_parameters
186
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), 
187
                               mapping_parameters = mapping_parameters, 
188
                               interactive = FALSE)
189
```
190
191
In case there are only two images, **the first image will be taken as the image of reference**. Hence, in order to align the first Xenium Replicate to the Visium dataset. We can create a list of two VoltRon objects as given below. 
192
193
```{r class.source="watch-out", eval = FALSE} 
194
xen_reg <- registerSpatialData(object_list = list(Vis, Xen_R2))
195
```
196
197
<br>
198
199
### Combine VoltRon object
200
201
Now that the VoltRon objects of Xenium and Visium datasets are accurately aligned, we can combine these objects to create **one VoltRon object with three layers**. Since all sections are derived from the same tissue block, we want them to be associated with the same sample, hence we define the sample name as well. VoltRon will recognize that all layers are originated from the same sample/block, and choose the majority assay as the main assay. 
202
203
```{r class.source="watch-out", eval = FALSE}
204
merge_list <- xen_reg$registered_spat
205
VRBlock <- merge(merge_list[[1]], merge_list[-1], samples = "10XBlock")
206
VRBlock
207
```
208
```
209
10XBlock: 
210
  Layers: Section1 Section2 Section3 
211
Assays: Xenium(Main) Visium
212
Features: RNA(Main) 
213
```
214
215
Here, we can quickly check the change in spatial coordinate systems in the new tissue block. The `registerSpatialData` function syncronizes the coordinate systems of all VoltRon objects in the list before merging. Both Xenium sections have now two coordinate system where the registered system **main_reg** is the default one.
216
217
```{r class.source="watch-out", eval = FALSE}
218
vrSpatialNames(VRBlock, assay = "all")
219
```
220
221
```
222
        Assay    Layer   Sample       Spatial     Main
223
Assay1 Xenium Section1 10XBlock main,main_reg main_reg
224
Assay2 Visium Section2 10XBlock          main     main
225
Assay3 Xenium Section3 10XBlock main,main_reg main_reg
226
```
227
228
<br>
229
230
### Data/Label Transfer Across Layers
231
232
The combined VoltRon object of Visium and Xenium datasets can be used to transfer information across layers and assays. This is accomplished by aggregating and summarizing, for example, gene counts of cells from the Xenium assay aligned to Visium spots. Either labels or cell types can be summarized to generate: 
233
234
* pseudo cell type abundance assays or
235
* pseudo gene expression assays. 
236
237
<br>
238
239
#### Data Transfer (Cells->Spots)
240
241
We must first determine the names of the assays where labels are transfered **from** one **to** the other. For the sake of this tutorial, we can select Assay1 of **Xenium as the source** assay and the Assay2 of **Visium as the destination** assay. 
242
243
```{r class.source="watch-out", eval = FALSE}
244
SampleMetadata(VRBlock)
245
```
246
247
```
248
        Assay    Layer   Sample
249
Assay1 Xenium Section1 10XBlock
250
Assay2 Visium Section2 10XBlock
251
Assay3 Xenium Section3 10XBlock
252
```
253
254
The **transferData** function detects the types of both the **source (from)** and the **destination (to)** assays and determines the how the data should be transfered. We can first transfer data from the Xenium assay to the Visium assay (hence **Cells -> Spots**), the raw count data of each cell in the source Xenium assay will be aggregated into spots in a newly create pseudo Visium assay. The new assay with aggregated counts will be named **Visium_pseudo**. 
255
256
```{r class.source="watch-out", eval = FALSE}
257
VRBlock <- transferData(VRBlock, from = "Assay1", to = "Assay2")
258
```
259
260
VoltRon supports multiple feature type within each assay. Now, the Visium assay includes two spot-type features:
261
262
* the original Visium spot feature counts,
263
* a pseudo Visium feature count matrix with aggregated Xenium raw counts.
264
265
```{r class.source="watch-out", eval = FALSE}
266
vrMainAssay(VRBlock) <- "Visium"
267
VRBlock
268
```
269
270
```
271
VoltRon Object 
272
10XBlock: 
273
  Layers: Section1 Section2 Section3 
274
Assays: Visium(Main) Xenium 
275
Features: RNA(Main) RNA_pseudo 
276
```
277
278
We can now visualize both the original and aggregated counts of a gene, such as ERBB2 and ESR1 that marks ductal carcinoma in situ (DCIS) regions, to validate the correlation of gene signatures across adjacent tissue sections, and to validate the accuracy of the automated image alignment. Here, PGR is also expressed at a small DCIS region found on adipocyte niche of the tissue. 
279
280
```{r class.source="watch-out", eval = FALSE}
281
library(patchwork)
282
vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA"
283
g1 <- vrSpatialFeaturePlot(VRBlock,  
284
                           features = c("ERBB2", "ESR1", "PGR"), crop = FALSE, 
285
                           norm = FALSE, ncol = 3)
286
vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA_pseudo"
287
g2 <- vrSpatialFeaturePlot(VRBlock, 
288
                           features = c("ERBB2", "ESR1", "PGR"), crop = FALSE, 
289
                           norm = FALSE, ncol = 3)
290
g1 / g2
291
```
292
293
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_TACSTD2.png" class="center">
294
295
#### Data Transfer (Spots->Cells)
296
297
A similar transfer can be achieved on the opposite direction. We can select Assay2 of **Visium as the source** assay and Assay1 of **Xenium as the destination**, thus we can transfer whole transcriptome counts of the Visium assays to Xenium to create new feature sets for Xenium data with more features originally available in the Xenium panel.
298
299
```{r class.source="watch-out", eval = FALSE}
300
vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA"
301
VRBlock <- transferData(VRBlock, from = "Assay2", to = "Assay1")
302
```
303
304
We now set the main feature set of the Xenium assays.
305
306
```{r class.source="watch-out", eval = FALSE}
307
vrMainFeatureType(VRBlock, assay = "Xenium") <- "RNA_pseudo"
308
vrMainFeatureType(VRBlock, assay = "all")
309
```
310
311
```
312
   Assay    Feature
313
1 Assay1 RNA_pseudo
314
2 Assay2        RNA
315
3 Assay3        RNA
316
```
317
318
```{r class.source="watch-out", eval = FALSE}
319
library(patchwork)
320
g1 <- vrSpatialFeaturePlot(VRBlock, 
321
                           assay = "Assay1", features = c("ERBB2", "ESR1", "PGR"), 
322
                           crop = TRUE, norm = FALSE, alpha = 1, n.tile = 300, ncol = 3)
323
g2 <- vrSpatialFeaturePlot(VRBlock, 
324
                           assay = "Assay2", features = c("ERBB2", "ESR1", "PGR"), 
325
                           crop = TRUE, norm = FALSE, alpha = 1, ncol = 3)
326
g1 / g2
327
```
328
329
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_spot2cell.png" class="center">
330
331
#### Label Transfer (Cells->Spots)
332
333
The **transferData** function can also transfer **metadata features** across layers and assays. In this case, we will transfer cell type labels that were trained on the Xenium sections onto the Visium sections. We will use the cluster labels generated at the end of the Xenium analysis section of workflow from [Cell/Spot Analysis](spotanalysis.html). You can download the VoltRon object with clustered and annotated Xenium cells along with the Visium assay from [here](https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/VRBlock_data_clustered.rds). 
334
335
```{r class.source="watch-out", eval = FALSE}
336
VRBlock <- readRDS("VRBlock_data_clustered.rds")
337
vrSpatialPlot(VRBlock, assay = "Xenium", group.by = "CellType", pt.size = 0.4)
338
```
339
340
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/cellspot_spatial_xenium_annotated.png" class="center">
341
342
Here, we can see that both Xenium layers are clustered and annotated where we can use these cell annotations and transfer them to the Visium assay to create an assay of **estimated cell type abundances**. If the features argument is specified, and if its a single metadata feature with, e.g. cell types, then the each spot at the new pseudo Visium will be collection of abundances of the categories within that metadata feature. 
343
344
```{r class.source="watch-out", eval = FALSE}
345
VRBlock <- transferData(VRBlock, from = "Assay1", to = "Assay2", features = "CellType", 
346
                        new_assay_name = "Visium_CellType")
347
VRBlock
348
```
349
350
```
351
VoltRon Object 
352
10XBlock: 
353
  Layers: Section1 Section2 Section3 
354
Assays: Visium(Main) Xenium 
355
Features: RNA_pseudo(Main) RNA Visium_CellType 
356
```
357
358
By visualizing the transferred labels on the Visium spots, we can see abundance of some DCIS and invasive tumor subtypes. 
359
360
```{r class.source="watch-out", eval = FALSE}
361
vrMainFeatureType(VRBlock) <- "Visium_CellType"
362
vrSpatialFeaturePlot(VRBlock, assay = "Visium",
363
                     features = c("IT_1","DCIS_2"), 
364
                     crop = TRUE, alpha = 1, ncol = 3)
365
```
366
367
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_CellType.png" class="center">
368
369
<br>
370
371
#### Label Transfer (ROIs->...)
372
373
VoltRon allows users to annotate regions of interests (ROIs) in a given assay and transfer the annotations to these ROIs across other assays within the same tissue block. Let us annotate two specific tumor regions in the Visium section. In the process, a new assay called **ROIAnnotation** will be added to the VoltRon object. 
374
375
```{r class.source="watch-out", eval = FALSE}
376
VRBlock <- annotateSpatialData(VRBlock, assay = "Visium", 
377
                               label = "annotation", use.image.only = TRUE)
378
```
379
380
<img width="80%" height="80%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROIAnnotation.png" class="center">
381
382
<br>
383
384
You can observe the changes in the object and check the assay ID of this new ROI type assay using `SampleMetadata` function.
385
386
```{r class.source="watch-out", eval = FALSE}
387
VRBlock
388
```
389
390
```
391
VoltRon Object 
392
10XBlock: 
393
  Layers: Section1 Section2 Section3 
394
Assays: Xenium(Main) Visium ROIAnnotation 
395
Features: RNA(Main) 
396
```
397
398
```{r class.source="watch-out", eval = FALSE}
399
SampleMetadata(VRBlock)
400
```
401
402
```
403
               Assay    Layer   Sample
404
Assay1        Xenium Section1 10XBlock
405
Assay2        Visium Section2 10XBlock
406
Assay3        Xenium Section3 10XBlock
407
Assay4 ROIAnnotation Section2 10XBlock
408
```
409
410
The metadata of the ROI assay will include the annotation of the ROIs as well.
411
412
```{r class.source="watch-out", eval = FALSE}
413
Metadata(VRBlock, assay = "ROIAnnotation")
414
```
415
416
```
417
                               Assay    Layer   Sample      annotation
418
InvasiveTumor_Assay4   ROIAnnotation Section2 10XBlock   InvasiveTumor
419
DuctalCarcinoma_Assay4 ROIAnnotation Section2 10XBlock DuctalCarcinoma
420
```
421
422
Now we can transfer the ROI labels from the **annotation** metadata column and define the same metadata column in the remaining assays.
423
424
```{r class.source="watch-out", eval = FALSE}
425
VRBlock <- transferData(object = VRBlock, from = "Assay4", to = "Assay1", 
426
                        features = "annotation")
427
VRBlock <- transferData(object = VRBlock, from = "Assay4", to = "Assay3", 
428
                        features = "annotation")
429
```
430
431
Let us observe the changes across all assays.
432
433
```{r class.source="watch-out", eval = FALSE}
434
vrSpatialPlot(VRBlock, group.by = "annotation", assay = "Xenium", crop = TRUE)
435
vrSpatialPlot(VRBlock, group.by = "annotation", assay = "Visium", crop = TRUE)
436
```
437
438
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_xenium.png" class="center">
439
440
<img width="50%" height="50%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_visium.png" class="center">
441
442
<br>
443
444
You can also use the **addSpatialLayer** function to overlay annotation segments to the spatial plot of the Xenium data.
445
 
446
```{r class.source="watch-out", eval = FALSE}
447
vrSpatialPlot(VRBlock_new2, group.by = "CellType", assay = "Assay1", crop = TRUE) |>
448
  addSpatialLayer(VRBlock_new2, assay = "ROIAnnotation", group.by = "annotation", spatial = "main", alpha = 0.4)
449
```
450
451
<img width="50%" height="50%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_xenium_overlay.png" class="center">
452
453
<br>
454
455
## Alignment of Xenium and H&E
456
457
In this use case, we will align **immunofluorescence (IF)** of the **Xenium In Situ** platform to an **H&E images** generated from the same sections as the Xenium. VoltRon provides built-in utilities to import images as spatial datasets where **tiles** are the spatial points. We will import both Xenium and H&E images into two separate VoltRon objects and overlay H&E images. 
458
459
You can download the Xenium readout and the H&E image of the same tissue section from the [10x Genomics website](https://www.10xgenomics.com/products/xenium-in-situ/preview-dataset-human-breast) (specifically, import **In Situ Replicate 1** and **Supplemental: Post-Xenium H&E image (TIFF)**). 
460
461
```{r eval = FALSE, class.source="watch-out"}
462
library(VoltRon)
463
464
# import Xenium 
465
Xen_R1 <- importXenium("Xenium_R1/outs", sample_name = "XeniumR1")
466
467
# import H&E image and build a VoltRon object
468
Xen_R1_image <- importImageData("Xenium_FFPE_Human_Breast_Cancer_Rep1_he_image.tif",
469
                                sample_name = "XeniumR1image", 
470
                                channel_names = "H&E")
471
Xen_R1_image
472
```
473
474
```
475
VoltRon Object 
476
XeniumR1image: 
477
  Layers: Section1 
478
Assays: ImageData(Main) 
479
```
480
481
Lets take a look at the image of the Xen_R1_image object
482
483
```{r eval = FALSE, class.source="watch-out"}
484
vrImages(Xen_R1_image)
485
```
486
487
<img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/importdata_HE.png" class="center">
488
489
<br>
490
491
### Automated Image Alignment
492
493
We can use the **registerSpatialData** function to warp/align images across multiple VoltRon objects and define these aligned images additional channels of existing coordinate systems of assays in one of these VoltRon objects. 
494
495
First we align the H&E image to the DAPI image of the Xenium replicate. Similar to the first use case, we need to negate the DAPI image and change the alignment of the image to match it with the H&E image. We can also scale the resolution of the H&E image to 9103.71x6768.63.
496
497
```{r eval = FALSE, class.source="watch-out"}
498
xen_reg <- registerSpatialData(object_list = list(Xen_R1, Xen_R1_image))
499
```
500
501
<img width="92%" height="92%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_HE_function.png" class="center">
502
503
<br>
504
505
Now we create a new channel for the existing coordinate system of the Xenium data. Here, the spatial key of the registered H&E image will be **main_reg**. We choose the destination of the registered image which is the first Assay of the Xenium data (i.e. **Assay1**). The original DAPI coordinate system, and we give a name for the new image/channel which is **H&E**.
506
507
```{r eval = FALSE, class.source="watch-out"}
508
Xen_R1_image_reg <- xen_reg$registered_spat[[2]]
509
vrImages(Xen_R1[["Assay1"]], channel = "H&E") <- vrImages(Xenium_reg, name = "main_reg", channel = "H&E")
510
```
511
512
We can now observe the new channels (H&E) available for the Xenium assay using **vrImageChannelNames**.
513
514
```{r eval = FALSE, class.source="watch-out"}
515
vrImageChannelNames(Xen_R1)
516
```
517
518
```
519
       Assay    Layer           Sample Spatial                                               Channels
520
Assay1 GeoMx Section1 prolonged case 4    main scanimage,DNA,PanCK,CD45,Alpha Smooth Muscle Actin,H&E
521
```
522
523
We can call the registered H&E image of the Xenium data or later put the aligned H&E when calling **vrSpatialPlot** or **vrSpatialFeaturePlot**. 
524
525
```{r eval = FALSE, class.source="watch-out"}
526
vrImages(Xen_R1, channel = "H&E", scale.perc = 5)
527
```
528
529
<img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_HE.png" class="center">
530
531
<br>
532
533
## Alignment of Visium and Visium
534
535
In the next use case, we will align **H&E images** associated with Visium data generated from tissue block sections of **adult humans with postmortem dorsolateral prefrontal cortex (DLPFC)**. Two pairs of adjacent sections was obtained from the tissue block of the third donor. Each pair are composed of two 10 $\mu$m serial tissue sections, and pairs are located 300 $\mu$m apart from each other. Hence, we align each pair individually. The datasets can be downloaded from [here](https://research.libd.org/spatialLIBD/). 
536
537
```{r class.source="watch-out", eval = FALSE} 
538
library(VoltRon)
539
DLPFC_1 <- importVisium("DLPFC/151673", sample_name = "DLPFC_1")
540
DLPFC_2 <- importVisium("DLPFC/151674", sample_name = "DLPFC_2")
541
DLPFC_3 <- importVisium("DLPFC/151675", sample_name = "DLPFC_3")
542
DLPFC_4 <- importVisium("DLPFC/151676", sample_name = "DLPFC_4")
543
```
544
545
<br>
546
547
### Automated Image Alignment
548
549
We will again use the registerSpatialData function to **automatically register two Visium assays (two H&E images)**. This time, we will use the **BRUTE-FORCE** method for automated alignment which we found to be more accurate compared to FLANN when aligning two H&E images. The shiny app also provides two tuning parameters that used by the the BRUTE-FORCE workflow:
550
551
* **# of Features** option specifies the number of maximum image features spotted within each image which later be used to match to the other image.
552
* **Match %** specifies the percentage of these features matching at max which in turn used to compute the registration/transformation matrix. 
553
554
We will use **1000 features** for this alignment, set **Match %** to 20\% of the features to be matched across images. The quality of the alignment will be determined by the fine tuning of these parameters where users will immediately observe the alignment quality looking at the slideshow. 
555
556
```{r class.source="watch-out", eval = FALSE} 
557
DLPFC_list <- list(DLPFC_1, DLPFC_2)
558
reg1and2 <- registerSpatialData(object_list = DLPFC_list)
559
```
560
561
<img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/VisiumDLFPCRegistration.gif" class="center">
562
563
<br>
564
565
We can now apply a similar alignment across the second pair of VoltRon objects. We will use **800 features** for this alignment,  set **Match %** to 50\% of the features to be matched across images.
566
567
```{r class.source="watch-out", eval = FALSE} 
568
DLPFC_list <- list(DLPFC_3, DLPFC_4)
569
reg3and4 <- registerSpatialData(object_list = DLPFC_list)
570
```
571
572
<br>
573
574
### 3D Spot Clustering 
575
576
We can now combine all sections into one VoltRon object. There are two pairs of serial tissue sections, but both pairs (thus 4 sections) are from the same tissue block. Hence, we can combine these two lists into one list and merge VoltRon objects even though sections were aligned separately. 
577
578
```{r class.source="watch-out", eval = FALSE} 
579
merge_list <- c(reg1and2$registered_spat, reg3and4$registered_spat)
580
SRBlock <- merge(merge_list[[1]], merge_list[-1], samples = "DLPFC_Block")
581
SRBlock
582
```
583
584
```
585
VoltRon Object 
586
DLPFC_Block: 
587
  Layers: Section1 Section2 Section3 Section4 
588
Assays: Visium(Main) 
589
```
590
591
<br>
592
593
Aligning spots along the z dimension allows us to cluster these spots using both the gene expression similarities and spatial adjacency (both along the x-y direction and in the z direction). We first generate a spatial neighborhood graph and use this graph along with the gene expression neighborhood graph **(under development)**.
594