--- a +++ b/docs/roianalysis.html @@ -0,0 +1,1063 @@ +<!DOCTYPE html> + +<html> + +<head> + +<meta charset="utf-8" /> +<meta name="generator" content="pandoc" /> +<meta http-equiv="X-UA-Compatible" content="IE=EDGE" /> + + + + +<title>ROI Analysis</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">ROI Analysis</h1> + +</div> + + +<style> +.title{ + display: none; +} +body { + text-align: justify +} +.center { + display: block; + margin-left: auto; + margin-right: auto; +} +table, th, td { + border-collapse: collapse; + align-self: center; + padding-right: 10px; + padding-left: 10px; +} +</style> +<style type="text/css"> +.watch-out { + color: black; +} +</style> +<p><br></p> +<div id="roi-analysis" class="section level1"> +<h1>ROI Analysis</h1> +<p>VoltRon is capable of analyzing readouts from distinct spatial +technologies including <strong>segmentation (ROI)-based transciptomics +assays</strong> that capture large polygonic regions on tissue sections. +VoltRon recognizes such readouts including ones from commercially +available tools and allows users to implement a workflow similar to ones +conducted on bulk RNA-Seq datasets. In this tutorial, we will analyze +morphological images and gene expression profiles provided by the +readouts of the <a +href="https://nanostring.com/products/geomx-digital-spatial-profiler/geomx-dsp-overview/">Nanostring’s +GeoMx Digital Spatial Profiler</a> platform, a high-plex spatial +profiling technology which produces segmentation-based protein and RNA +assays.</p> +<p>In this use case, <strong>eight tissue micro array (TMA) tissue +sections</strong> were fitted into the scan area of the slide loaded on +the GeoMx DSP instrument. These sections were cut from <strong>control +and COVID-19 lung tissues</strong> of donors categorized based on +disease durations (acute and prolonged). See <a +href="https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE190732">GSE190732</a> +for more information.</p> +<p>You can download these tutorial files from here:</p> +<table> +<tr> +<th> +File +</th> +<th> +Link +</th> +</tr> +<tr> +<td> +Counts +</td> +<td> +<a href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/DCC-20230427.zip">DDC +files</a> +</td> +</tr> +<tr> +<td> +GeoMx Human Whole Transcriptome Atlas +</td> +<td> +<a href="https://nanostring.com/wp-content/uploads/Hs_R_NGS_WTA_v1.0.pkc_.zip">Human +RNA WTA for NGS</a> +</td> +</tr> +<tr> +<td> +Segment Summary +</td> +<td> +<a href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/segmentSummary.csv"> +ROI Metadata file </a> +</td> +</tr> +<tr> +<td> +Morphology Image +</td> +<td> +<a href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/Lu1A1B5umtrueexp.tif"> +Image file </a> +</td> +</tr> +<tr> +<td> +OME.TIFF Image +</td> +<td> +<a href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/Lu1A1B5umtrueexp.ome.tiff"> +OME.TIFF file </a> +</td> +</tr> +<tr> +<td> +OME.TIFF Image (XML) +</td> +<td> +<a href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/Lu1A1B5umtrueexp.ome.tiff.xml" download target="_blank"> +OME.TIFF (XML) file </a> +</td> +</tr> +</table> +<p> +</p> +<p>We now import the GeoMx data, and start analyzing 87 user selected +segments (i.e. region of interests, <strong>ROI</strong>) to check +spatial localization of signals. The <strong>importGeoMx</strong> +function requires:</p> +<ul> +<li>The path to the Digital Count Conversion file, +<strong>dcc.path</strong>, and Probe Kit Configuration file, +<strong>pkc.file</strong>, which are both provided as the output of the +<a +href="https://emea.illumina.com/products/by-type/informatics-products/basespace-sequence-hub/apps/nanostring-geomxr-ngs-pipeline.html">GeoMx +NGS Pipeline</a>.</li> +<li>The path the to the metadata file, <strong>summarySegment</strong>, +and the specific excel sheet that the metadata is found, +<strong>summarySegmentSheetName</strong>, the path to the main +morphology <strong>image</strong> and the original <strong>ome.tiff +(xml)</strong> file, all of which are provided and imported from the DSP +Control Center. Please see <a +href="https://nanostring.com/support-documents/geomx-dsp-data-analysis-user-manual/">GeoMx +DSP Data Analysis User Manual</a> for more information.</li> +</ul> +<pre class="r watch-out"><code>library(VoltRon) +library(xlsx) +GeoMxR1 <- importGeoMx(dcc.path = "DCC-20230427/", + pkc.file = "Hs_R_NGS_WTA_v1.0.pkc", + summarySegment = "segmentSummary.csv", + image = "Lu1A1B5umtrueexp.tif", + ome.tiff = "Lu1A1B5umtrueexp.ome.tiff.xml", + sample_name = "GeoMxR1")</code></pre> +<p>We can import the GeoMx ROI segments from the +<strong>Lu1A1B5umtrueexp.ome.tiff</strong> image file directly by +replacing the .xml file with the .ome.tiff file in the +<strong>ome.tiff</strong> argument. Note that you need to call the +<strong>RBioFormats</strong> library. If you are getting a <strong>java +error</strong> when running importGeoMx, try increasing the maximum heap +size by supplying the <strong>-Xmx</strong> parameter. Run the code +below before rerunning <strong>importGeoMx</strong> again.</p> +<pre class="r watch-out"><code>options(java.parameters = "-Xmx4g") +library(RBioFormats)</code></pre> +<p><br></p> +<div id="quality-control" class="section level2"> +<h2>Quality Control</h2> +<p>Once the GeoMx data is imported, we can start off with examining key +quality control measures and statistics on each segment to investigate +each individual ROI such as sequencing saturation and the number of +cells (nuclei) within each segment. VoltRon also provides the total +number of unique transcripts per ROI and stores in the metadata.</p> +<pre class="r watch-out"><code>library(ggplot2) +vrBarPlot(GeoMxR1, + features = c("Count", "Nuclei.count", "Sequencing.saturation"), + x.label = "ROI.name", group.by = "ROI.type") + + theme(axis.text.x = element_text(size = 3))</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_barplot.png" class="center"></p> +<p>For measuring the quality of individual ROIs, we can add a new +metadata column, called <strong>CountPerNuclei</strong>, to check the +average quality of cells per ROI. It seems some number of ROIs with low +counts per nuclei also have low sequencing saturation.</p> +<pre class="r watch-out"><code>GeoMxR1$CountPerNuclei <- GeoMxR1$Count/GeoMxR1$Nuclei.count +vrBarPlot(GeoMxR1, + features = c("Count", "Nuclei.count", + "Sequencing.saturation", "CountPerNuclei"), + x.label = "ROI.name", group.by = "ROI.type", ncol = 2) + + theme(axis.text.x = element_text(size = 5))</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_barplot2.png" class="center"></p> +<p><br></p> +</div> +<div id="processing" class="section level2"> +<h2>Processing</h2> +<p>We can now filter ROIs based on our earlier observation of them +having low count per nuclei where some also have low sequencing +saturation.</p> +<pre class="r watch-out"><code># Filter for count per nuclei +GeoMxR1 <- subset(GeoMxR1, subset = CountPerNuclei > 500)</code></pre> +<p>We then filter genes with low counts by extracting the count matrix +and putting aside all genes whose maximum count across all 87 ROIs are +less than 10.</p> +<pre class="r watch-out"><code>GeoMxR1_data <- vrData(GeoMxR1, norm = FALSE) +feature_ind <- apply(GeoMxR1_data, 1, function(x) max(x) > 10) +selected_features <- vrFeatures(GeoMxR1)[feature_ind] +GeoMxR1_lessfeatures <- subset(GeoMxR1, features = selected_features)</code></pre> +<p>VoltRon is capable of normalizing data provided by a diverse set of +spatial technologies, including the quantile normalization method +suggested by the <a +href="https://nanostring.com/support-documents/geomx-dsp-data-analysis-user-manual/">GeoMx +DSP Data Analysis User Manual</a> which scales the ROI profiles to the +third quartile followed by the geometric mean of all third quartiles +multipled to the scaled profile.</p> +<pre class="r watch-out"><code>GeoMxR1 <- normalizeData(GeoMxR1, method = "Q3Norm")</code></pre> +<p><br></p> +</div> +<div id="interactive-subsetting" class="section level2"> +<h2>Interactive Subsetting</h2> +<p>Spatially informed genomic technologies heavily depend on image +manipulation as images provide an additional set of information. Hence, +VoltRon incorporates several interactive built-in utilities. One such +functionality allows manipulating images of VoltRon assays where users +can interactively choose subsets of images. However, we first resize the +morphology image by providing the width of the new image (thus height +will be reduced to preserve the aspect ratio).</p> +<pre class="r watch-out"><code># resizing the image +# GeoMxR1 <- resizeImage(GeoMxR1, size = 4000)</code></pre> +<p>VoltRon provides <strong>a mini Shiny app</strong> for subsetting +spatial points of a VoltRon object by using the image as a reference. +This app is particularly useful when multiple tissue sections were +fitted to a scan area of a slide, such as the one from GeoMx DSP +instrument. We use <strong>interactive = TRUE</strong> option in the +subset function to call the mini Shiny app, and select bounding boxes of +each newly created subset. <strong>Please continue until all eight +sections are selected and subsetted</strong>.</p> +<pre class="r watch-out"><code>GeoMxR1_subset <- subset(GeoMxR1, interactive = TRUE)</code></pre> +<p><img width="85%" height="85%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/interactivesubset.gif" class="center"></p> +<p>We can now merge the list of subsets, or samples, each associated +with one of eight sections. You can provide a list of names for the +newly subsetted samples.</p> +<pre class="r watch-out"><code>GeoMxR1_subset_list <- GeoMxR1_subset$subsets +GeoMxR1 <- merge(GeoMxR1_subset_list[[1]], GeoMxR1_subset_list[-1]) +GeoMxR1</code></pre> +<pre><code>VoltRon Object +prolonged case 4: + Layers: Section1 +acute case 3: + Layers: Section1 +control case 2: + Layers: Section1 +acute case 1: + Layers: Section1 +acute case 2: + Layers: Section1 +... +There are 8 samples in total +Assays: GeoMx(Main) </code></pre> +<p><br></p> +<p>You may also save the selected image subsets and reproduce the +interactive subsetting operation for later use.</p> +<pre class="r watch-out"><code>samples <- c("prolonged case 4", "acute case 3", "control case 2", + "acute case 1", "acute case 2", "prolonged case 5", + "prolonged case 3", "control case 1") +subset_info_list <- GeoMxR1_subset$subset_info_list[[1]] +GeoMxR1_subset_list <- list() +for(i in 1:length(subset_info_list)){ + GeoMxR1_subset_list[[i]] <- subset(GeoMxR1, image = subset_info_list[i]) + GeoMxR1_subset_list[[i]] <- samples[i] +} +GeoMxR1 <- merge(GeoMxR1_subset_list[[1]], GeoMxR1_subset_list[-1])</code></pre> +<p><br></p> +</div> +<div id="visualization" class="section level2"> +<h2>Visualization</h2> +<p>We will now select sections of interests from the VoltRon object, and +visualize ROIs and features for each of these sections.</p> +<p>The function <strong>vrSpatialPlot</strong> plots categorical +attributes associated with ROIs. In this case, we will visualize types +of ROIs that were labelled and annotated during ROI selection.</p> +<pre class="r watch-out"><code>GeoMxR1_subset <- subset(GeoMxR1, sample = c("prolonged case 4","acute case 3")) +vrSpatialPlot(GeoMxR1_subset, group.by = "ROI.type", ncol = 3, alpha = 0.6)</code></pre> +<p><img width="90%" height="90%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_spatialplot.png" class="center"></p> +<p>The function <strong>vrSpatialFeaturePlot</strong> detects the number +of assays within each VoltRon object and visualizes each feature per +each spatial image. A grid of images are visualized either the number of +assays or the number of features are larger than 1. Here, we visualize +the normalized expression of COL1A1 and C1S, two fibrotic markers, +across ROIs of two prolonged covid cases. One may observe that the +fibrotic regions of prolonged case 5 have considerably more COL1A1 and +C1S compared to prolonged case 4.</p> +<pre class="r watch-out"><code>GeoMxR1_subset <- subset(GeoMxR1, sample = c("prolonged case 4","prolonged case 5")) +vrSpatialFeaturePlot(GeoMxR1_subset, features = c("COL1A1", "C1S"), group.by = "ROI.name", + log = TRUE, label = TRUE, keep.scale = "feature", title.size = 15)</code></pre> +<p><img width="85%" height="85%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_featureplot.png" class="center"></p> +<p><br></p> +</div> +<div id="dimensionality-reduction" class="section level2"> +<h2>Dimensionality Reduction</h2> +<p>We can now process the normalized and demultiplexed samples to map +ROIs across all sections onto lower dimensional spaces. The functions +<strong>getFeatures</strong> and <strong>getPCA</strong> select features +(i.e. genes) of interest from the data matrix across all samples and +reduce it to a selected number of principal components.</p> +<pre class="r watch-out"><code>GeoMxR1 <- getFeatures(GeoMxR1) +GeoMxR1 <- getPCA(GeoMxR1, dims = 30)</code></pre> +<p>The function <strong>vrEmbeddingPlot</strong> can be used to +visualize embedding spaces (pca, umap, etc.) for any spatial point +supported by VoltRon, hence cells, spots and ROI are all visualized +using the same set of functions. Here we generate a new metadata column +that represents the <strong>disease durations (control, acute and +prolonged case)</strong>, then map gene profiles to the first two +principal components.</p> +<pre class="r watch-out"><code>GeoMxR1$Condition <- gsub(" [0-9]+$", "", GeoMxR1$Sample) +vrEmbeddingPlot(GeoMxR1, group.by = c("Condition"), embedding = "pca", pt.size = 3)</code></pre> +<p><img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_embeddingplotsingle.png" class="center"></p> +<p>VoltRon provides additional dimensionality reduction techniques such +as <strong>UMAP</strong>.</p> +<pre class="r watch-out"><code>GeoMxR1 <- getUMAP(GeoMxR1)</code></pre> +<p>Gene expression profiles of ROIs associated with prolonged case +sections seem to show some heterogeneity. We now color segments by +section (or replicate, <strong>Sample</strong>) to observe the sources +of variability. Three replicates of prolonged cases exhibit three +different clusters of ROIs.</p> +<pre class="r watch-out"><code>vrEmbeddingPlot(GeoMxR1, group.by = c("Condition"), embedding = "pca", pt.size = 3) +vrEmbeddingPlot(GeoMxR1, group.by = c("ROI.type"), embedding = "pca", pt.size = 3) +vrEmbeddingPlot(GeoMxR1, group.by = c("ROI.type"), embedding = "umap", pt.size = 3)</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_embeddingplot.png" class="center"></p> +</div> +<div id="differential-expression-analysis" class="section level2"> +<h2>Differential Expression Analysis</h2> +<p>VoltRon provides wrapping functions for calling tools and methods +from popular differential expression analysis package such as <a +href="https://genomebiology.biomedcentral.com/articles/10.1186/s13059-014-0550-8">DESeq2</a>. +We utilize <strong>DESeq2</strong> to find differentially expressed +genes across each pair of ROI types conditions.</p> +<pre class="r watch-out"><code># get DE for all conditions +library(DESeq2) +library(dplyr) +DEresults <- getDiffExp(GeoMxR1, group.by = "ROI.type", + group.base = "vessel", method = "DESeq2") +DEresults_sig <- DEresults %>% filter(!is.na(padj)) %>% + filter(padj < 0.05, abs(log2FoldChange) > 1) +head(DEresults_sig)</code></pre> +<div> +<pre><code style="font-size: 11.7px;"> baseMean log2FoldChange lfcSE stat pvalue padj gene comparison +ACTA2 33.48395 1.508701 0.3458464 4.362343 1.286768e-05 4.902586e-03 ACTA2 ROI.type_vessel_epithelium +ADAMTS1 22.29160 1.152556 0.2272085 5.072680 3.922515e-07 4.109815e-04 ADAMTS1 ROI.type_vessel_epithelium +C11orf96 27.48924 1.142085 0.3041057 3.755554 1.729585e-04 2.588819e-02 C11orf96 ROI.type_vessel_epithelium +CNN1 16.87670 1.112662 0.2680222 4.151381 3.304757e-05 9.766004e-03 CNN1 ROI.type_vessel_epithelium +CRYAB 21.85960 1.264747 0.2173272 5.819552 5.900570e-09 2.472929e-05 CRYAB ROI.type_vessel_epithelium +FLNA 44.50957 1.270025 0.3243115 3.916066 9.000548e-05 1.985331e-02 FLNA ROI.type_vessel_epithelium</code></pre> +</div> +<p><br></p> +<p>The <strong>vrHeatmapPlot</strong> takes a set of features for any +type of spatial point (cells, spots and ROIs) and visualizes scaled data +per each feature. We select <strong>highlight.some = TRUE</strong> to +annotate features which could be large in size where you can also select +the number of such highlighted genes with <strong>n_highlight</strong>. +There seems to be two groups of fibrotic regions that most likely +associated with two prolonged case samples.</p> +<pre class="r watch-out"><code># get DE for all conditions +library(ComplexHeatmap) +vrHeatmapPlot(GeoMxR1, features = unique(DEresults_sig$gene), group.by = "ROI.type", + highlight.some = TRUE, n_highlight = 40)</code></pre> +<p><img width="90%" height="90%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_heatmap.png" class="center"></p> +<p><br></p> +<p>In order to get a deeper understanding of differences between +fibrotic regions across two prolonged case replicates. We first subset +the GeoMx data to only sections with fibrotic ROIs.</p> +<pre class="r watch-out"><code>fibrotic_ROI <- vrSpatialPoints(GeoMxR1)[GeoMxR1$ROI.type == "fibrotic"] +GeoMxR1_subset <- subset(GeoMxR1, spatialpoints = fibrotic_ROI) +vrSpatialPlot(GeoMxR1_subset, group.by = "ROI.type", ncol = 3, alpha = 0.4)</code></pre> +<p><img width="90%" height="90%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_spatialplot_fibrotic.png" class="center"></p> +<p>The <strong>getDiffExp</strong> function is capable of testing +differential expression across all metadata columns, including the +<strong>Samples</strong> column that captures labels of different tissue +sections. Macrophage markers such as CD68 and CD163 are differentially +expressed in fibrotic regions of case 5 compared to case 4, including +FN1, a profibrotic gene whose expression can be found on +macrophages.</p> +<pre class="r watch-out"><code>DEresults <- getDiffExp(GeoMxR1_subset, group.by = "Sample", + group.base = "prolonged case 5", method = "DESeq2") +DEresults_sig <- DEresults %>% filter(!is.na(padj)) %>% + filter(padj < 0.05, abs(log2FoldChange) > 1) +DEresults_sig <- DEresults_sig[order(DEresults_sig$log2FoldChange, decreasing = TRUE),] +head(DEresults_sig)</code></pre> +<div> +<pre><code style="font-size: 10.7px;"> baseMean log2FoldChange lfcSE stat pvalue padj gene comparison +COL3A1 708.5599 6.635411 0.5198805 12.763338 2.626978e-37 1.596809e-33 COL3A1 Sample_prolonged case 5_prolonged case 4 +COL1A2 836.0790 5.237228 0.4407380 11.882861 1.453071e-32 4.416246e-29 COL1A2 Sample_prolonged case 5_prolonged case 4 +COL1A1 460.2184 5.175153 0.5237868 9.880267 5.069785e-23 3.081669e-20 COL1A1 Sample_prolonged case 5_prolonged case 4 +FN1 278.6594 5.083687 0.3717299 13.675754 1.417301e-42 1.723013e-38 FN1 Sample_prolonged case 5_prolonged case 4 +HBB 202.7693 4.944228 0.4884175 10.122955 4.370193e-24 3.794888e-21 HBB Sample_prolonged case 5_prolonged case 4 +A2M 466.4328 4.925236 0.4542682 10.842133 2.173435e-27 3.774636e-24 A2M Sample_prolonged case 5_prolonged case 4</code></pre> +</div> +<p><br></p> +<!-- Markers of each individual tissue section for each disease duration is shown on the Heatmap. --> +<!-- ```{r eval = FALSE, class.source="watch-out"} --> +<!-- # get DE for all conditions --> +<!-- vrHeatmapPlot(GeoMxR1, features = unique(DEresults_sig$gene), --> +<!-- group.by = "Sample", highlight.some = TRUE) --> +<!-- ``` --> +<!-- <img width="90%" height="90%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_heatmap2.png" class="center"> --> +<!-- <br> --> +</div> +<div id="roi-deconvolution" class="section level2"> +<h2>ROI Deconvolution</h2> +<p>VoltRon supports multiple bulk RNA deconvolution algorithms to +analyze the cellular composition of both ROIs and spots. In order to +integrate the scRNA data and the GeoMx data sets within the VoltRon +objects, we will use the <a +href="https://xuranw.github.io/MuSiC/articles/MuSiC.html">MuSiC</a> +package. We will use a human lung scRNA dataset (GSE198864) as +reference, which is found <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GSE198864_lung.rds">here</a>.</p> +<pre class="r watch-out"><code>set.seed(1) +library(Seurat) +library(SingleCellExperiment) +seu <- readRDS("GSE198864_lung.rds") +scRNAlung <- seu[,sample(1:ncol(seu), 10000, replace = FALSE)] + +# Visualize clusters +DimPlot(scRNAlung, reduction = "umap", label = T, group.by = "Clusters") + NoLegend()</code></pre> +<p><img width="60%" height="60%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_deconvolution_singlecell.png" class="center"></p> +<p>We utilize the <strong>getDeconvolution</strong> function to call +wrapper functions for deconvolution algorithms (see ). For all layers +with GoeMx assays, an additional assay within the same layer with +<strong>_decon</strong> postfix will be created. The +<strong>sc.object</strong> argument can either be a +<strong>Seurat</strong> or <strong>SingleCellExperiment</strong> +object.</p> +<pre class="r watch-out"><code>library(MuSiC) +GeoMxR1 <- getDeconvolution(GeoMxR1, + sc.object = scRNAlung, sc.assay = "RNA", + sc.cluster = "Clusters", sc.samples = "orig.ident")</code></pre> +<pre><code>VoltRon Object +prolonged case 4: + Layers: Section1 +acute case 3: + Layers: Section1 +control case 2: + Layers: Section1 +acute case 1: + Layers: Section1 +acute case 2: + Layers: Section1 +... +There are 8 samples in total +Assays: GeoMx(Main) +Features: RNA(Main) NegProbe Decon </code></pre> +<p>We can now visualize cell type compositions of each ROI. Before +running <strong>vrProportionPlot</strong> function, we need to set the +main feature type as <strong>Decon</strong>. One may see the increased +proportion of cells NK cells and T cells in immune ROIs.</p> +<pre class="r watch-out"><code>vrMainFeatureType(GeoMxR1) <- "Decon" +vrProportionPlot(GeoMxR1, x.label = "ROI.name")</code></pre> +<p><img width="100%" height="100%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_deconvolution.png" class="center"></p> +<p>Here, we can subset the GeoMx object further to dive deep into the +cellular proportions of each fibrotic region of prolonged cases. +Comparing prolonged case 5 against case 4, we see an increase in the +cellular population of the stromal cluster defined in <a +href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9922044/">Mothes et. +al 2023</a> (that are both vascular and airway smooth muscle cells), and +an increase abundance of macrophages which may indicate that these +macrophages are profibrotic being within and close to fibrotic regions +with increased gene expression of FN1.</p> +<pre class="r watch-out"><code># subsetting fibrotic regions +spatialpoints <- vrSpatialPoints(GeoMxR1)[GeoMxR1$ROI.type == "fibrotic"] +GeoMxR1_subset <- subset(GeoMxR1, spatialpoints = spatialpoints) + +# Proportion plot +vrProportionPlot(GeoMxR1_subset, x.label = "ROI.name", split.method = "facet_grid", + split.by = "Sample") + +# barplot +vrBarPlot(GeoMxR1_subset, features = c("stromal", "macrophages"), group.by = "Sample", + x.label = "ROI.name", split.by = "Sample")</code></pre> +<p><img width="80%" height="80%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_heatmap_fibrotic.png" class="center"></p> +<p><img width="80%" height="80%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_barplot_prop_fibrotic.png" class="center"></p> +</div> +<div id="he-image-integration" class="section level2"> +<h2>H&E Image Integration</h2> +<p>Questions may arise if in fact these ROIs are fibrotic even though +they were initially annotated as fibrotic regions. VoltRon provides +advanced image registration workflows which we can use to H&E images +of from the same TMA blocks where GeoMx slides were established.</p> +<p>We first import the H&E image of the prolonged case 4 TMA section +using the <strong>importImageData</strong> function. This will import +the H&E image as a standalone VoltRon object. For more information +on image-based VoltRon objects, see the <a +href="pixelanalysis.html">Downstream analysis of Pixels</a> section.</p> +<p>We will use the H&E image of TMA section taken from the same +block as the Prolonged case 4. You can download the image from <a +href="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/ROIanalysis/GeoMx/prolonged_case4_HE.tif">here</a>.</p> +<pre class="r watch-out"><code>vrHEimage <- importImageData("prolonged_case4_HE.tif", channel_names = "H&E") +vrImages(vrHEimage, scale.perc = 40)</code></pre> +<p><img width="50%" height="50%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/prolonged_case4_HE.png" class="center"></p> +<p><br></p> +<p>We can now register the GeoMx slide with the newly imported H&E +based VoltRon object. Since two images are associated with TMA sections +that are not adjacent, we have to rely on the localization of vessels +visible in both images for alignment. VoltRon allows manipulating +multiple channels of an image object two choose the best background +image for manual landmark selection. For more information on both manual +and automated registration of VoltRon objects, see <a +href="registration.html">here</a>.</p> +<p>VoltRon provides multiple registration methods to align images. Here, +after running the <strong>registerSpatialData</strong> function, we +choose the <strong>Homography + Non-rigid (TPS)</strong> method which +utilizes a perspective transformation on the H&E image followed by a +thin plate spline (TPS) alignment. The perspective transformation +performs a global alignment between the H&E image and the main GeoMx +image (here the scan image with combined antibody channels), and the TPS +method allows correct local deformations between the perspective +transformed H&E image and the GeoMx image for a more accurate</p> +<pre class="r watch-out"><code>GeoMxR1_subset <- subset(GeoMxR1, sample = c("prolonged case 4")) +GeoMxReg <- registerSpatialData(reference_spatdata = GeoMxR1_subset, + query_spatdata = vrHEimage)</code></pre> +<p><img width="80%" height="80%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_manualregistration.png" class="center"></p> +<p>The result of the registration is a list of registered VoltRon +objects which we can use for parsing the registered image as well. In +this case, the second element of the resulting list would be the +registered H&E based VoltRon object.</p> +<pre class="r watch-out"><code>vrHEimage_reg <- GeoMxReg$registered_spat[[2]]</code></pre> +<p>We can check the additional coordinate system now available for the +registered H&E image. One is the coordinate system with the original +image, and the other with the one that is registered.</p> +<pre class="r watch-out"><code>vrSpatialNames(vrHEimage_reg)</code></pre> +<pre><code>[1] "main" "main_reg"</code></pre> +<p>We can also exchange images where the H&E image now is registered +to the perspective of the GeoMx channels, and can be defined as a new +channel in the original GeoMx object.</p> +<pre class="r watch-out"><code>vrImages(GeoMxR1_subset[["Assay1"]], name = "main", channel = "H&E") <- vrImages(vrHEimage_reg, name = "main_reg", channel = "H&E")</code></pre> +<p>We can now observe the new channels (H&E) available for the GeoMx +assay using <strong>vrImageChannelNames</strong>. H&E is saved as a +separate channel along with the originally available antibody channels +of the original GeoMx experiment.</p> +<pre class="r watch-out"><code>vrImageChannelNames(GeoMxR1_subset)</code></pre> +<div> +<pre><code style="font-size: 12px;"> Assay Layer Sample Spatial Channels +Assay1 GeoMx Section1 prolonged case 4 main scanimage,DNA,PanCK,CD45,Alpha Smooth Muscle Actin,H&E</code></pre> +</div> +<p>We can now visualize the ROIs and their annotations where the +registered H&E visible in the background. We define the spatial key +<strong>main</strong> and the channel name <strong>H&E</strong>.</p> +<pre class="r watch-out"><code>vrSpatialPlot(GeoMxR1_subset, group.by = "ROI.type", alpha = 0.7, + spatial = "main", channel = "H&E")</code></pre> +<p><img width="70%" height="70%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_spatialplot_withHE.png" class="center"></p> +<p>Interactive Visualization can also be used to zoom in to ROIs and +investigate the pathology associated with GeoMx ROIs labeled as +fibrotic.</p> +<pre class="r watch-out"><code>vrSpatialPlot(GeoMxR1_subset, group.by = "ROI.type", alpha = 0.7, + spatial = "main", channel = "H&E", + interactive = TRUE)</code></pre> +<p><img width="60%" height="60%" src="https://bimsbstatic.mdc-berlin.de/landthaler/VoltRon/Package/images/roi_spatialplot_withHE_interactive.png" class="center"></p> +</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", + 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 = false; + + // 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>