--- a +++ b/docs/registration.html @@ -0,0 +1,1081 @@ +<!DOCTYPE html> + +<html> + +<head> + +<meta charset="utf-8" /> +<meta name="generator" content="pandoc" /> +<meta http-equiv="X-UA-Compatible" content="IE=EDGE" /> + + + + +<title>Image Registration</title> + +<script src="site_libs/header-attrs-2.29/header-attrs.js"></script> +<script src="site_libs/jquery-3.6.0/jquery-3.6.0.min.js"></script> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<link href="site_libs/bootstrap-3.3.5/css/flatly.min.css" rel="stylesheet" /> +<script src="site_libs/bootstrap-3.3.5/js/bootstrap.min.js"></script> +<script src="site_libs/bootstrap-3.3.5/shim/html5shiv.min.js"></script> +<script src="site_libs/bootstrap-3.3.5/shim/respond.min.js"></script> +<style>h1 {font-size: 34px;} + h1.title {font-size: 38px;} + h2 {font-size: 30px;} + h3 {font-size: 24px;} + h4 {font-size: 18px;} + h5 {font-size: 16px;} + h6 {font-size: 12px;} + code {color: inherit; background-color: rgba(0, 0, 0, 0.04);} + pre:not([class]) { background-color: white }</style> +<script src="site_libs/jqueryui-1.13.2/jquery-ui.min.js"></script> +<link href="site_libs/tocify-1.9.1/jquery.tocify.css" rel="stylesheet" /> +<script src="site_libs/tocify-1.9.1/jquery.tocify.js"></script> +<script src="site_libs/navigation-1.1/tabsets.js"></script> +<link href="site_libs/highlightjs-9.12.0/textmate.css" rel="stylesheet" /> +<script src="site_libs/highlightjs-9.12.0/highlight.js"></script> +<link href="site_libs/font-awesome-6.5.2/css/all.min.css" rel="stylesheet" /> +<link href="site_libs/font-awesome-6.5.2/css/v4-shims.min.css" rel="stylesheet" /> + +<style type="text/css"> + code{white-space: pre-wrap;} + span.smallcaps{font-variant: small-caps;} + span.underline{text-decoration: underline;} + div.column{display: inline-block; vertical-align: top; width: 50%;} + div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} + ul.task-list{list-style: none;} + </style> + +<style type="text/css">code{white-space: pre;}</style> +<script type="text/javascript"> +if (window.hljs) { + hljs.configure({languages: []}); + hljs.initHighlightingOnLoad(); + if (document.readyState && document.readyState === "complete") { + window.setTimeout(function() { hljs.initHighlighting(); }, 0); + } +} +</script> + + + + + + + + + +<style type = "text/css"> +.main-container { + max-width: 940px; + margin-left: auto; + margin-right: auto; +} +img { + max-width:100%; +} +.tabbed-pane { + padding-top: 12px; +} +.html-widget { + margin-bottom: 20px; +} +button.code-folding-btn:focus { + outline: none; +} +summary { + display: list-item; +} +details > summary > p:only-child { + display: inline; +} +pre code { + padding: 0; +} +</style> + + +<style type="text/css"> +.dropdown-submenu { + position: relative; +} +.dropdown-submenu>.dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + border-radius: 0 6px 6px 6px; +} +.dropdown-submenu:hover>.dropdown-menu { + display: block; +} +.dropdown-submenu>a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #cccccc; + margin-top: 5px; + margin-right: -10px; +} +.dropdown-submenu:hover>a:after { + border-left-color: #adb5bd; +} +.dropdown-submenu.pull-left { + float: none; +} +.dropdown-submenu.pull-left>.dropdown-menu { + left: -100%; + margin-left: 10px; + border-radius: 6px 0 6px 6px; +} +</style> + +<script type="text/javascript"> +// manage active state of menu based on current page +$(document).ready(function () { + // active menu anchor + href = window.location.pathname + href = href.substr(href.lastIndexOf('/') + 1) + if (href === "") + href = "index.html"; + var menuAnchor = $('a[href="' + href + '"]'); + + // mark the anchor link active (and if it's in a dropdown, also mark that active) + var dropdown = menuAnchor.closest('li.dropdown'); + if (window.bootstrap) { // Bootstrap 4+ + menuAnchor.addClass('active'); + dropdown.find('> .dropdown-toggle').addClass('active'); + } else { // Bootstrap 3 + menuAnchor.parent().addClass('active'); + dropdown.addClass('active'); + } + + // Navbar adjustments + var navHeight = $(".navbar").first().height() + 15; + var style = document.createElement('style'); + var pt = "padding-top: " + navHeight + "px; "; + var mt = "margin-top: -" + navHeight + "px; "; + var css = ""; + // offset scroll position for anchor links (for fixed navbar) + for (var i = 1; i <= 6; i++) { + css += ".section h" + i + "{ " + pt + mt + "}\n"; + } + style.innerHTML = "body {" + pt + "padding-bottom: 40px; }\n" + css; + document.head.appendChild(style); +}); +</script> + +<!-- tabsets --> + +<style type="text/css"> +.tabset-dropdown > .nav-tabs { + display: inline-table; + max-height: 500px; + min-height: 44px; + overflow-y: auto; + border: 1px solid #ddd; + border-radius: 4px; +} + +.tabset-dropdown > .nav-tabs > li.active:before, .tabset-dropdown > .nav-tabs.nav-tabs-open:before { + content: "\e259"; + font-family: 'Glyphicons Halflings'; + display: inline-block; + padding: 10px; + border-right: 1px solid #ddd; +} + +.tabset-dropdown > .nav-tabs.nav-tabs-open > li.active:before { + content: "\e258"; + font-family: 'Glyphicons Halflings'; + border: none; +} + +.tabset-dropdown > .nav-tabs > li.active { + display: block; +} + +.tabset-dropdown > .nav-tabs > li > a, +.tabset-dropdown > .nav-tabs > li > a:focus, +.tabset-dropdown > .nav-tabs > li > a:hover { + border: none; + display: inline-block; + border-radius: 4px; + background-color: transparent; +} + +.tabset-dropdown > .nav-tabs.nav-tabs-open > li { + display: block; + float: none; +} + +.tabset-dropdown > .nav-tabs > li { + display: none; +} +</style> + +<!-- code folding --> + + + +<style type="text/css"> + +#TOC { + margin: 25px 0px 20px 0px; +} +@media (max-width: 768px) { +#TOC { + position: relative; + width: 100%; +} +} + +@media print { +.toc-content { + /* see https://github.com/w3c/csswg-drafts/issues/4434 */ + float: right; +} +} + +.toc-content { + padding-left: 30px; + padding-right: 40px; +} + +div.main-container { + max-width: 1200px; +} + +div.tocify { + width: 20%; + max-width: 260px; + max-height: 85%; +} + +@media (min-width: 768px) and (max-width: 991px) { + div.tocify { + width: 25%; + } +} + +@media (max-width: 767px) { + div.tocify { + width: 100%; + max-width: none; + } +} + +.tocify ul, .tocify li { + line-height: 20px; +} + +.tocify-subheader .tocify-item { + font-size: 0.90em; +} + +.tocify .list-group-item { + border-radius: 0px; +} + +.tocify-subheader { + display: inline; +} +.tocify-subheader .tocify-item { + font-size: 0.95em; +} + +</style> + + + +</head> + +<body> + + +<div class="container-fluid main-container"> + + +<!-- setup 3col/9col grid for toc_float and main content --> +<div class="row"> +<div class="col-xs-12 col-sm-4 col-md-3"> +<div id="TOC" class="tocify"> +</div> +</div> + +<div class="toc-content col-xs-12 col-sm-8 col-md-9"> + + + + +<div class="navbar navbar-default navbar-fixed-top" role="navigation"> + <div class="container"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-bs-toggle="collapse" data-target="#navbar" data-bs-target="#navbar"> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="index.html">VoltRon</a> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav"> + <li> + <a href="tutorials.html">Explore</a> +</li> +<li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + Vignette + + <span class="caret"></span> + </a> + <ul class="dropdown-menu" role="menu"> + <li class="dropdown-submenu"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">Spatial Data Integration</a> + <ul class="dropdown-menu" role="menu"> + <li> + <a href="registration.html">Spatial Data Alignment</a> + </li> + <li> + <a href="multiomic.html">Multi-omic Integration</a> + </li> + <li> + <a href="nicheclustering.html">Niche Clustering</a> + </li> + </ul> + </li> + <li class="dropdown-submenu"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">Downstream Analysis</a> + <ul class="dropdown-menu" role="menu"> + <li> + <a href="roianalysis.html">ROI Analysis</a> + </li> + <li> + <a href="spotanalysis.html">Cell/Spot Analysis</a> + </li> + <li> + <a href="moleculeanalysis.html">Molecule Analysis</a> + </li> + <li> + <a href="pixelanalysis.html">Pixels (Image Only) Analysis</a> + </li> + </ul> + </li> + <li class="dropdown-submenu"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">Utilities</a> + <ul class="dropdown-menu" role="menu"> + <li> + <a href="interactive.html">Interactive Utilities</a> + </li> + <li> + <a href="importingdata.html">Importing Spatial Data</a> + </li> + <li> + <a href="voltronobjects.html">Working with VoltRon Objects</a> + </li> + <li> + <a href="conversion.html">Converting VoltRon Objects</a> + </li> + <li> + <a href="ondisk.html">OnDisk-based Analysis Utilities</a> + </li> + </ul> + </li> + </ul> +</li> + </ul> + <ul class="nav navbar-nav navbar-right"> + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + <span class="fa fa-envelope-o"></span> + + Contact + + <span class="caret"></span> + </a> + <ul class="dropdown-menu" role="menu"> + <li> + <a href="https://bioinformatics.mdc-berlin.de">Altuna Lab/BIMSB Bioinfo</a> + </li> + <li> + <a href="https://www.mdc-berlin.de/landthaler">Landthaler Lab/BIMSB</a> + </li> + </ul> +</li> +<li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> + <span class="fa fa-github"></span> + + GitHub + + <span class="caret"></span> + </a> + <ul class="dropdown-menu" role="menu"> + <li> + <a href="https://github.com/BIMSBbioinfo/VoltRon">VoltRon</a> + </li> + <li> + <a href="https://github.com/BIMSBbioinfo">BIMSB Bioinfo</a> + </li> + </ul> +</li> + </ul> + </div><!--/.nav-collapse --> + </div><!--/.container --> +</div><!--/.navbar --> + +<div id="header"> + + + +<h1 class="title toc-ignore">Image Registration</h1> + +</div> + + +<style> +.title{ + display: none; +} +body { + text-align: justify +} +.center { + display: block; + margin-left: auto; + margin-right: auto; +} +</style> +<style type="text/css"> +.watch-out { + color: black; +} +</style> +<p><br></p> +<div id="spatial-data-alignment" class="section level1"> +<h1>Spatial Data Alignment</h1> +<p>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.</p> +<p>VoltRon allows users to <strong>align spatial omics datasets of these +serial sections</strong> 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 <strong>shiny +application</strong> to either automatically or manually align images. +The automatic alignment is achieved with the <strong>OpenCV</strong>’s +C++ library fully embedded in the VoltRon package.</p> +<table> +<tbody> +<tr style="vertical-align: center"> +<td style="width:43%; vertical-align: center"> +<img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/manualregistration.png" class="center"> +</td> +<td style="width:43%; vertical-align: center"> +<img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/autoregistration.png" class="center"> +</td> +</tr> +</tbody> +</table> +<p><br></p> +<div id="alignment-of-xenium-and-visium" class="section level2"> +<h2>Alignment of Xenium and Visium</h2> +<p>In this use case, we will align <strong>immunofluorescence +(IF)</strong> and <strong>H&E images</strong> of the <strong>Xenium +In Situ</strong> and <strong>Visium CytAssist</strong> platforms +readouts. Three tissue sections are derived from a single +formalin-fixed, paraffin-embedded (FFPE) breast cancer tissue block. A 5 +<span class="math inline">\(\mu\)</span>m section was taken for Visium +CytAssist and two replicate 5 <span class="math inline">\(\mu\)</span>m +sections were taken for the Xenium replicates. More information on the +spatial datasets and the study can be also be found on the <a +href="https://www.biorxiv.org/content/10.1101/2022.10.06.510405v1">BioArxiv +preprint</a>.</p> +<p>You can download the Xenium and Visium readouts from the <a +href="https://www.10xgenomics.com/products/xenium-in-situ/preview-dataset-human-breast">10x +Genomics website</a> (specifically, import <strong>In Situ Replicate 1/2 +and Visium Spatial</strong>). Alternatively, you can <strong>download a +zipped collection of three Visium and Xenium readouts</strong> from <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/10X_Xenium_Visium.zip">here</a>.</p> +<p>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.</p> +<pre class="r watch-out"><code>library(VoltRon) +Xen_R1 <- importXenium("Xenium_R1/outs", sample_name = "XeniumR1") +Xen_R2 <- importXenium("Xenium_R2/outs", sample_name = "XeniumR2") +Vis <- importVisium("Visium/", sample_name = "VisiumR1")</code></pre> +<p>Before moving on to image alignment, we can inspect both Xenium and +Visium images. We use the <strong>vrImages</strong> function to call and +visualize reference images of all VoltRon objects.</p> +<pre class="r watch-out"><code>vrImages(Xen_R1) +vrImages(Xen_R2) +vrImages(Vis)</code></pre> +<table> +<tbody> +<tr style="vertical-align: center"> +<td style="width:33%; vertical-align: center"> +<img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr1.png" class="center"> +</td> +<td style="width:33%; vertical-align: center"> +<img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr2.png" class="center"> +</td> +<td style="width:33%; vertical-align: center"> +<img src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/visium.png" class="center"> +</td> +</tr> +</tbody> +</table> +<p><br></p> +<p>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 +<strong>modulateImage</strong> 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.</p> +<pre class="r watch-out"><code>Xen_R2 <- modulateImage(Xen_R2, brightness = 800) +vrImages(Xen_R2)</code></pre> +<p><img width="40%" height="40%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/xeniumr2_new.png" class="center"></p> +<p><br></p> +<div id="automated-image-alignment" class="section level3"> +<h3>Automated Image Alignment</h3> +<p>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 <strong>registerSpatialData</strong> function which calls a +<strong>shiny app</strong> 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 <strong>order of serial sections</strong>.</p> +<p>We will make use of the <strong>registerSpatialData</strong> function +to <strong>automatically register two Xenium assays onto the Visium +assay</strong>. The Visium CytAssist image (or the <strong>image on the +center</strong> 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 <strong>two +images</strong> for this task:</p> +<ul> +<li>An image that shows the matched points across two images, and</li> +<li>A slideshow with of the reference and registered images that +demonstrates the alignment accuracy.</li> +</ul> +<p>We will select <strong>FLANN</strong> method for automated alignment +which incorporates the <strong>SIFT</strong> method for automated +keypoints selection and utilizes the <strong>Fast library for +Approximate Nearest Neighbors (FLANN) algorithm</strong> for matching +keypoints. <strong>NOTE:</strong> 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.</p> +<pre class="r watch-out"><code>xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2))</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/XeniumVisiumRegistration_FLANN.gif" class="center"></p> +<p><br></p> +<p>You can save and use the same parameters later, and reproduce the +alignment without choosing parameters the second time.</p> +<pre class="r watch-out"><code>mapping_parameters <- xen_reg$mapping_parameters +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters)</code></pre> +<p>You can find a presaved set of parameters <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/mapping_parameters.rds">here</a>.</p> +<pre class="r watch-out"><code>mapping_parameters <- readRDS("mapping_parameters.rds") +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters)</code></pre> +<p>If the pre-saved parameters are available, the registration can also +be performed without using the shiny app. By using <strong>interactive = +FALSE</strong>, we can register images and VoltRon objects directly.</p> +<pre class="r watch-out"><code>mapping_parameters <- xen_reg$mapping_parameters +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters, + interactive = FALSE)</code></pre> +<p>In case there are only two images, <strong>the first image will be +taken as the image of reference</strong>. 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.</p> +<pre class="r watch-out"><code>xen_reg <- registerSpatialData(object_list = list(Vis, Xen_R2))</code></pre> +<p><br></p> +</div> +<div id="manual-image-alignment" class="section level3"> +<h3>Manual Image Alignment</h3> +<p>Given the diverse types of tissue sections and their complex +morphology, we need an alternative alignment strategy if automated +registration may fail. VoltRon allows <strong>manually choosing +keypoints (or landmarks)</strong> on images that are locations on the +tissue with structural/morphological similarity. Similar to the +automated mode, <strong>the image on the center</strong> 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.</p> +<pre class="r watch-out"><code>xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2))</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/XeniumVisiumRegistration.gif" class="center"></p> +<p><br></p> +<p>You can save and use the same keypoints later, and reproduce the +manual alignment without choosing keypoints for the second time.</p> +<pre class="r watch-out"><code>mapping_parameters <- xen_reg$mapping_parameters +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters)</code></pre> +<p>You can find a presaved set of parameters with selected manual +keypoints <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/mapping_parameters_manual.rds">here</a>.</p> +<pre class="r watch-out"><code>mapping_parameters <- readRDS("mapping_parameters_manual.rds") +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters)</code></pre> +<p>If the pre-saved keypoints are available with parameters, the +registration can also be performed without using the shiny app. By using +<strong>interactive = FALSE</strong>, we can register images and VoltRon +objects directly.</p> +<pre class="r watch-out"><code>mapping_parameters <- xen_reg$mapping_parameters +xen_reg <- registerSpatialData(object_list = list(Xen_R1, Vis, Xen_R2), + mapping_parameters = mapping_parameters, + interactive = FALSE)</code></pre> +<p>In case there are only two images, <strong>the first image will be +taken as the image of reference</strong>. 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.</p> +<pre class="r watch-out"><code>xen_reg <- registerSpatialData(object_list = list(Vis, Xen_R2))</code></pre> +<p><br></p> +</div> +<div id="combine-voltron-object" class="section level3"> +<h3>Combine VoltRon object</h3> +<p>Now that the VoltRon objects of Xenium and Visium datasets are +accurately aligned, we can combine these objects to create <strong>one +VoltRon object with three layers</strong>. 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.</p> +<pre class="r watch-out"><code>merge_list <- xen_reg$registered_spat +VRBlock <- merge(merge_list[[1]], merge_list[-1], samples = "10XBlock") +VRBlock</code></pre> +<pre><code>10XBlock: + Layers: Section1 Section2 Section3 +Assays: Xenium(Main) Visium +Features: RNA(Main) </code></pre> +<p>Here, we can quickly check the change in spatial coordinate systems +in the new tissue block. The <code>registerSpatialData</code> 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 <strong>main_reg</strong> is the default +one.</p> +<pre class="r watch-out"><code>vrSpatialNames(VRBlock, assay = "all")</code></pre> +<pre><code> Assay Layer Sample Spatial Main +Assay1 Xenium Section1 10XBlock main,main_reg main_reg +Assay2 Visium Section2 10XBlock main main +Assay3 Xenium Section3 10XBlock main,main_reg main_reg</code></pre> +<p><br></p> +</div> +<div id="datalabel-transfer-across-layers" class="section level3"> +<h3>Data/Label Transfer Across Layers</h3> +<p>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:</p> +<ul> +<li>pseudo cell type abundance assays or</li> +<li>pseudo gene expression assays.</li> +</ul> +<p><br></p> +<div id="data-transfer-cells-spots" class="section level4"> +<h4>Data Transfer (Cells->Spots)</h4> +<p>We must first determine the names of the assays where labels are +transfered <strong>from</strong> one <strong>to</strong> the other. For +the sake of this tutorial, we can select Assay1 of <strong>Xenium as the +source</strong> assay and the Assay2 of <strong>Visium as the +destination</strong> assay.</p> +<pre class="r watch-out"><code>SampleMetadata(VRBlock)</code></pre> +<pre><code> Assay Layer Sample +Assay1 Xenium Section1 10XBlock +Assay2 Visium Section2 10XBlock +Assay3 Xenium Section3 10XBlock</code></pre> +<p>The <strong>transferData</strong> function detects the types of both +the <strong>source (from)</strong> and the <strong>destination +(to)</strong> assays and determines the how the data should be +transfered. We can first transfer data from the Xenium assay to the +Visium assay (hence <strong>Cells -> Spots</strong>), 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 <strong>Visium_pseudo</strong>.</p> +<pre class="r watch-out"><code>VRBlock <- transferData(VRBlock, from = "Assay1", to = "Assay2")</code></pre> +<p>VoltRon supports multiple feature type within each assay. Now, the +Visium assay includes two spot-type features:</p> +<ul> +<li>the original Visium spot feature counts,</li> +<li>a pseudo Visium feature count matrix with aggregated Xenium raw +counts.</li> +</ul> +<pre class="r watch-out"><code>vrMainAssay(VRBlock) <- "Visium" +VRBlock</code></pre> +<pre><code>VoltRon Object +10XBlock: + Layers: Section1 Section2 Section3 +Assays: Visium(Main) Xenium +Features: RNA(Main) RNA_pseudo </code></pre> +<p>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.</p> +<pre class="r watch-out"><code>library(patchwork) +vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA" +g1 <- vrSpatialFeaturePlot(VRBlock, + features = c("ERBB2", "ESR1", "PGR"), crop = FALSE, + norm = FALSE, ncol = 3) +vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA_pseudo" +g2 <- vrSpatialFeaturePlot(VRBlock, + features = c("ERBB2", "ESR1", "PGR"), crop = FALSE, + norm = FALSE, ncol = 3) +g1 / g2</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_TACSTD2.png" class="center"></p> +</div> +<div id="data-transfer-spots-cells" class="section level4"> +<h4>Data Transfer (Spots->Cells)</h4> +<p>A similar transfer can be achieved on the opposite direction. We can +select Assay2 of <strong>Visium as the source</strong> assay and Assay1 +of <strong>Xenium as the destination</strong>, 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.</p> +<pre class="r watch-out"><code>vrMainFeatureType(VRBlock, assay = "Visium") <- "RNA" +VRBlock <- transferData(VRBlock, from = "Assay2", to = "Assay1")</code></pre> +<p>We now set the main feature set of the Xenium assays.</p> +<pre class="r watch-out"><code>vrMainFeatureType(VRBlock, assay = "Xenium") <- "RNA_pseudo" +vrMainFeatureType(VRBlock, assay = "all")</code></pre> +<pre><code> Assay Feature +1 Assay1 RNA_pseudo +2 Assay2 RNA +3 Assay3 RNA</code></pre> +<pre class="r watch-out"><code>library(patchwork) +g1 <- vrSpatialFeaturePlot(VRBlock, + assay = "Assay1", features = c("ERBB2", "ESR1", "PGR"), + crop = TRUE, norm = FALSE, alpha = 1, n.tile = 300, ncol = 3) +g2 <- vrSpatialFeaturePlot(VRBlock, + assay = "Assay2", features = c("ERBB2", "ESR1", "PGR"), + crop = TRUE, norm = FALSE, alpha = 1, ncol = 3) +g1 / g2</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_spot2cell.png" class="center"></p> +</div> +<div id="label-transfer-cells-spots" class="section level4"> +<h4>Label Transfer (Cells->Spots)</h4> +<p>The <strong>transferData</strong> function can also transfer +<strong>metadata features</strong> 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 <a +href="spotanalysis.html">Cell/Spot Analysis</a>. You can download the +VoltRon object with clustered and annotated Xenium cells along with the +Visium assay from <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/SpatialDataAlignment/Xenium_vs_Visium/VRBlock_data_clustered.rds">here</a>.</p> +<pre class="r watch-out"><code>VRBlock <- readRDS("VRBlock_data_clustered.rds") +vrSpatialPlot(VRBlock, assay = "Xenium", group.by = "CellType", pt.size = 0.4)</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/cellspot_spatial_xenium_annotated.png" class="center"></p> +<p>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 <strong>estimated cell type +abundances</strong>. 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.</p> +<pre class="r watch-out"><code>VRBlock <- transferData(VRBlock, from = "Assay1", to = "Assay2", features = "CellType", + new_assay_name = "Visium_CellType") +VRBlock</code></pre> +<pre><code>VoltRon Object +10XBlock: + Layers: Section1 Section2 Section3 +Assays: Visium(Main) Xenium +Features: RNA_pseudo(Main) RNA Visium_CellType </code></pre> +<p>By visualizing the transferred labels on the Visium spots, we can see +abundance of some DCIS and invasive tumor subtypes.</p> +<pre class="r watch-out"><code>vrMainFeatureType(VRBlock) <- "Visium_CellType" +vrSpatialFeaturePlot(VRBlock, assay = "Visium", + features = c("IT_1","DCIS_2"), + crop = TRUE, alpha = 1, ncol = 3)</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_CellType.png" class="center"></p> +<p><br></p> +</div> +<div id="label-transfer-rois-" class="section level4"> +<h4>Label Transfer (ROIs->…)</h4> +<p>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 +<strong>ROIAnnotation</strong> will be added to the VoltRon object.</p> +<pre class="r watch-out"><code>VRBlock <- annotateSpatialData(VRBlock, assay = "Visium", + label = "annotation", use.image.only = TRUE)</code></pre> +<p><img width="80%" height="80%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROIAnnotation.png" class="center"></p> +<p><br></p> +<p>You can observe the changes in the object and check the assay ID of +this new ROI type assay using <code>SampleMetadata</code> function.</p> +<pre class="r watch-out"><code>VRBlock</code></pre> +<pre><code>VoltRon Object +10XBlock: + Layers: Section1 Section2 Section3 +Assays: Xenium(Main) Visium ROIAnnotation +Features: RNA(Main) </code></pre> +<pre class="r watch-out"><code>SampleMetadata(VRBlock)</code></pre> +<pre><code> Assay Layer Sample +Assay1 Xenium Section1 10XBlock +Assay2 Visium Section2 10XBlock +Assay3 Xenium Section3 10XBlock +Assay4 ROIAnnotation Section2 10XBlock</code></pre> +<p>The metadata of the ROI assay will include the annotation of the ROIs +as well.</p> +<pre class="r watch-out"><code>Metadata(VRBlock, assay = "ROIAnnotation")</code></pre> +<pre><code> Assay Layer Sample annotation +InvasiveTumor_Assay4 ROIAnnotation Section2 10XBlock InvasiveTumor +DuctalCarcinoma_Assay4 ROIAnnotation Section2 10XBlock DuctalCarcinoma</code></pre> +<p>Now we can transfer the ROI labels from the +<strong>annotation</strong> metadata column and define the same metadata +column in the remaining assays.</p> +<pre class="r watch-out"><code>VRBlock <- transferData(object = VRBlock, from = "Assay4", to = "Assay1", + features = "annotation") +VRBlock <- transferData(object = VRBlock, from = "Assay4", to = "Assay3", + features = "annotation")</code></pre> +<p>Let us observe the changes across all assays.</p> +<pre class="r watch-out"><code>vrSpatialPlot(VRBlock, group.by = "annotation", assay = "Xenium", crop = TRUE) +vrSpatialPlot(VRBlock, group.by = "annotation", assay = "Visium", crop = TRUE)</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_xenium.png" class="center"></p> +<p><img width="50%" height="50%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_visium.png" class="center"></p> +<p><br></p> +<p>You can also use the <strong>addSpatialLayer</strong> function to +overlay annotation segments to the spatial plot of the Xenium data.</p> +<pre class="r watch-out"><code>vrSpatialPlot(VRBlock_new2, group.by = "CellType", assay = "Assay1", crop = TRUE) |> + addSpatialLayer(VRBlock_new2, assay = "ROIAnnotation", group.by = "annotation", spatial = "main", alpha = 0.4)</code></pre> +<p><img width="50%" height="50%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_ROI_xenium_overlay.png" class="center"></p> +<p><br></p> +</div> +</div> +</div> +<div id="alignment-of-xenium-and-he" class="section level2"> +<h2>Alignment of Xenium and H&E</h2> +<p>In this use case, we will align <strong>immunofluorescence +(IF)</strong> of the <strong>Xenium In Situ</strong> platform to an +<strong>H&E images</strong> generated from the same sections as the +Xenium. VoltRon provides built-in utilities to import images as spatial +datasets where <strong>tiles</strong> are the spatial points. We will +import both Xenium and H&E images into two separate VoltRon objects +and overlay H&E images.</p> +<p>You can download the Xenium readout and the H&E image of the same +tissue section from the <a +href="https://www.10xgenomics.com/products/xenium-in-situ/preview-dataset-human-breast">10x +Genomics website</a> (specifically, import <strong>In Situ Replicate +1</strong> and <strong>Supplemental: Post-Xenium H&E image +(TIFF)</strong>).</p> +<pre class="r watch-out"><code>library(VoltRon) + +# import Xenium +Xen_R1 <- importXenium("Xenium_R1/outs", sample_name = "XeniumR1") + +# import H&E image and build a VoltRon object +Xen_R1_image <- importImageData("Xenium_FFPE_Human_Breast_Cancer_Rep1_he_image.tif", + sample_name = "XeniumR1image", + channel_names = "H&E") +Xen_R1_image</code></pre> +<pre><code>VoltRon Object +XeniumR1image: + Layers: Section1 +Assays: ImageData(Main) </code></pre> +<p>Lets take a look at the image of the Xen_R1_image object</p> +<pre class="r watch-out"><code>vrImages(Xen_R1_image)</code></pre> +<p><img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/importdata_HE.png" class="center"></p> +<p><br></p> +<div id="automated-image-alignment-1" class="section level3"> +<h3>Automated Image Alignment</h3> +<p>We can use the <strong>registerSpatialData</strong> 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.</p> +<p>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.</p> +<pre class="r watch-out"><code>xen_reg <- registerSpatialData(object_list = list(Xen_R1, Xen_R1_image))</code></pre> +<p><img width="92%" height="92%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_HE_function.png" class="center"></p> +<p><br></p> +<p>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 <strong>main_reg</strong>. We choose the destination of the +registered image which is the first Assay of the Xenium data +(i.e. <strong>Assay1</strong>). The original DAPI coordinate system, and +we give a name for the new image/channel which is +<strong>H&E</strong>.</p> +<pre class="r watch-out"><code>Xen_R1_image_reg <- xen_reg$registered_spat[[2]] +vrImages(Xen_R1[["Assay1"]], channel = "H&E") <- vrImages(Xenium_reg, name = "main_reg", channel = "H&E")</code></pre> +<p>We can now observe the new channels (H&E) available for the +Xenium assay using <strong>vrImageChannelNames</strong>.</p> +<pre class="r watch-out"><code>vrImageChannelNames(Xen_R1)</code></pre> +<pre><code> Assay Layer Sample Spatial Channels +Assay1 GeoMx Section1 prolonged case 4 main scanimage,DNA,PanCK,CD45,Alpha Smooth Muscle Actin,H&E</code></pre> +<p>We can call the registered H&E image of the Xenium data or later +put the aligned H&E when calling <strong>vrSpatialPlot</strong> or +<strong>vrSpatialFeaturePlot</strong>.</p> +<pre class="r watch-out"><code>vrImages(Xen_R1, channel = "H&E", scale.perc = 5)</code></pre> +<p><img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/registration_HE.png" class="center"></p> +<p><br></p> +</div> +</div> +<div id="alignment-of-visium-and-visium" class="section level2"> +<h2>Alignment of Visium and Visium</h2> +<p>In the next use case, we will align <strong>H&E images</strong> +associated with Visium data generated from tissue block sections of +<strong>adult humans with postmortem dorsolateral prefrontal cortex +(DLPFC)</strong>. Two pairs of adjacent sections was obtained from the +tissue block of the third donor. Each pair are composed of two 10 <span +class="math inline">\(\mu\)</span>m serial tissue sections, and pairs +are located 300 <span class="math inline">\(\mu\)</span>m apart from +each other. Hence, we align each pair individually. The datasets can be +downloaded from <a +href="https://research.libd.org/spatialLIBD/">here</a>.</p> +<pre class="r watch-out"><code>library(VoltRon) +DLPFC_1 <- importVisium("DLPFC/151673", sample_name = "DLPFC_1") +DLPFC_2 <- importVisium("DLPFC/151674", sample_name = "DLPFC_2") +DLPFC_3 <- importVisium("DLPFC/151675", sample_name = "DLPFC_3") +DLPFC_4 <- importVisium("DLPFC/151676", sample_name = "DLPFC_4")</code></pre> +<p><br></p> +<div id="automated-image-alignment-2" class="section level3"> +<h3>Automated Image Alignment</h3> +<p>We will again use the registerSpatialData function to +<strong>automatically register two Visium assays (two H&E +images)</strong>. This time, we will use the +<strong>BRUTE-FORCE</strong> 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:</p> +<ul> +<li><strong># of Features</strong> option specifies the number of +maximum image features spotted within each image which later be used to +match to the other image.</li> +<li><strong>Match %</strong> specifies the percentage of these features +matching at max which in turn used to compute the +registration/transformation matrix.</li> +</ul> +<p>We will use <strong>1000 features</strong> for this alignment, set +<strong>Match %</strong> 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.</p> +<pre class="r watch-out"><code>DLPFC_list <- list(DLPFC_1, DLPFC_2) +reg1and2 <- registerSpatialData(object_list = DLPFC_list)</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/VisiumDLFPCRegistration.gif" class="center"></p> +<p><br></p> +<p>We can now apply a similar alignment across the second pair of +VoltRon objects. We will use <strong>800 features</strong> for this +alignment, set <strong>Match %</strong> to 50% of the features to be +matched across images.</p> +<pre class="r watch-out"><code>DLPFC_list <- list(DLPFC_3, DLPFC_4) +reg3and4 <- registerSpatialData(object_list = DLPFC_list)</code></pre> +<p><br></p> +</div> +<div id="d-spot-clustering" class="section level3"> +<h3>3D Spot Clustering</h3> +<p>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.</p> +<pre class="r watch-out"><code>merge_list <- c(reg1and2$registered_spat, reg3and4$registered_spat) +SRBlock <- merge(merge_list[[1]], merge_list[-1], samples = "DLPFC_Block") +SRBlock</code></pre> +<pre><code>VoltRon Object +DLPFC_Block: + Layers: Section1 Section2 Section3 Section4 +Assays: Visium(Main) </code></pre> +<p><br></p> +<p>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 <strong>(under development)</strong>.</p> +</div> +</div> +</div> + + + +</div> +</div> + +</div> + +<script> + +// add bootstrap table styles to pandoc tables +function bootstrapStylePandocTables() { + $('tr.odd').parent('tbody').parent('table').addClass('table table-condensed'); +} +$(document).ready(function () { + bootstrapStylePandocTables(); +}); + + +</script> + +<!-- tabsets --> + +<script> +$(document).ready(function () { + window.buildTabsets("TOC"); +}); + +$(document).ready(function () { + $('.tabset-dropdown > .nav-tabs > li').click(function () { + $(this).parent().toggleClass('nav-tabs-open'); + }); +}); +</script> + +<!-- code folding --> + +<script> +$(document).ready(function () { + + // temporarily add toc-ignore selector to headers for the consistency with Pandoc + $('.unlisted.unnumbered').addClass('toc-ignore') + + // move toc-ignore selectors from section div to header + $('div.section.toc-ignore') + .removeClass('toc-ignore') + .children('h1,h2,h3,h4,h5').addClass('toc-ignore'); + + // establish options + var options = { + selectors: "h1,h2,h3,h4,h5", + theme: "bootstrap3", + context: '.toc-content', + hashGenerator: function (text) { + return text.replace(/[.\\/?&!#<>]/g, '').replace(/\s/g, '_'); + }, + ignoreSelector: ".toc-ignore", + scrollTo: 0 + }; + options.showAndHide = false; + options.smoothScroll = true; + + // tocify + var toc = $("#TOC").tocify(options).data("toc-tocify"); +}); +</script> + +<!-- dynamically load mathjax for compatibility with self-contained --> +<script> + (function () { + var script = document.createElement("script"); + script.type = "text/javascript"; + script.src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; + document.getElementsByTagName("head")[0].appendChild(script); + })(); +</script> + +</body> +</html>