Diff of /docs/roianalysis.html [000000] .. [413088]

Switch to side-by-side view

--- 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 &lt;- importGeoMx(dcc.path = &quot;DCC-20230427/&quot;, 
+                       pkc.file = &quot;Hs_R_NGS_WTA_v1.0.pkc&quot;,
+                       summarySegment = &quot;segmentSummary.csv&quot;,
+                       image = &quot;Lu1A1B5umtrueexp.tif&quot;,
+                       ome.tiff = &quot;Lu1A1B5umtrueexp.ome.tiff.xml&quot;,
+                       sample_name = &quot;GeoMxR1&quot;)</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 = &quot;-Xmx4g&quot;)
+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(&quot;Count&quot;, &quot;Nuclei.count&quot;, &quot;Sequencing.saturation&quot;),
+          x.label = &quot;ROI.name&quot;, group.by = &quot;ROI.type&quot;) + 
+  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 &lt;- GeoMxR1$Count/GeoMxR1$Nuclei.count
+vrBarPlot(GeoMxR1, 
+          features = c(&quot;Count&quot;, &quot;Nuclei.count&quot;, 
+                       &quot;Sequencing.saturation&quot;, &quot;CountPerNuclei&quot;),
+          x.label = &quot;ROI.name&quot;, group.by = &quot;ROI.type&quot;, 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 &lt;- subset(GeoMxR1, subset = CountPerNuclei &gt; 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 &lt;- vrData(GeoMxR1, norm = FALSE)
+feature_ind &lt;- apply(GeoMxR1_data, 1, function(x) max(x) &gt; 10)
+selected_features &lt;- vrFeatures(GeoMxR1)[feature_ind]
+GeoMxR1_lessfeatures &lt;- 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 &lt;- normalizeData(GeoMxR1, method = &quot;Q3Norm&quot;)</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 &lt;- 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 &lt;- 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 &lt;- GeoMxR1_subset$subsets
+GeoMxR1 &lt;- 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 &lt;- c(&quot;prolonged case 4&quot;, &quot;acute case 3&quot;, &quot;control case 2&quot;, 
+             &quot;acute case 1&quot;, &quot;acute case 2&quot;, &quot;prolonged case 5&quot;, 
+             &quot;prolonged case 3&quot;, &quot;control case 1&quot;)
+subset_info_list &lt;- GeoMxR1_subset$subset_info_list[[1]]
+GeoMxR1_subset_list &lt;- list()
+for(i in 1:length(subset_info_list)){
+  GeoMxR1_subset_list[[i]]  &lt;- subset(GeoMxR1, image = subset_info_list[i])
+  GeoMxR1_subset_list[[i]] &lt;- samples[i]
+}
+GeoMxR1 &lt;- 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 &lt;- subset(GeoMxR1, sample = c(&quot;prolonged case 4&quot;,&quot;acute case 3&quot;))
+vrSpatialPlot(GeoMxR1_subset, group.by = &quot;ROI.type&quot;, 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 &lt;- subset(GeoMxR1, sample = c(&quot;prolonged case 4&quot;,&quot;prolonged case 5&quot;))
+vrSpatialFeaturePlot(GeoMxR1_subset, features = c(&quot;COL1A1&quot;, &quot;C1S&quot;), group.by = &quot;ROI.name&quot;, 
+                     log = TRUE, label = TRUE, keep.scale = &quot;feature&quot;, 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 &lt;- getFeatures(GeoMxR1)
+GeoMxR1 &lt;- 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 &lt;- gsub(&quot; [0-9]+$&quot;, &quot;&quot;, GeoMxR1$Sample)
+vrEmbeddingPlot(GeoMxR1, group.by = c(&quot;Condition&quot;), embedding = &quot;pca&quot;, 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 &lt;- 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(&quot;Condition&quot;), embedding = &quot;pca&quot;, pt.size = 3)
+vrEmbeddingPlot(GeoMxR1, group.by = c(&quot;ROI.type&quot;), embedding = &quot;pca&quot;, pt.size = 3)
+vrEmbeddingPlot(GeoMxR1, group.by = c(&quot;ROI.type&quot;), embedding = &quot;umap&quot;, 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 &lt;- getDiffExp(GeoMxR1, group.by = &quot;ROI.type&quot;,
+                        group.base = &quot;vessel&quot;, method = &quot;DESeq2&quot;)
+DEresults_sig &lt;- DEresults %&gt;% filter(!is.na(padj)) %&gt;% 
+  filter(padj &lt; 0.05, abs(log2FoldChange) &gt; 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 = &quot;ROI.type&quot;, 
+              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 &lt;- vrSpatialPoints(GeoMxR1)[GeoMxR1$ROI.type == &quot;fibrotic&quot;]
+GeoMxR1_subset &lt;- subset(GeoMxR1, spatialpoints = fibrotic_ROI)
+vrSpatialPlot(GeoMxR1_subset, group.by = &quot;ROI.type&quot;, 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 &lt;- getDiffExp(GeoMxR1_subset, group.by = &quot;Sample&quot;, 
+                        group.base = &quot;prolonged case 5&quot;, method = &quot;DESeq2&quot;)
+DEresults_sig &lt;- DEresults %&gt;% filter(!is.na(padj)) %&gt;%
+  filter(padj &lt; 0.05, abs(log2FoldChange) &gt; 1)
+DEresults_sig &lt;- 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 &lt;- readRDS(&quot;GSE198864_lung.rds&quot;)
+scRNAlung &lt;- seu[,sample(1:ncol(seu), 10000, replace = FALSE)]
+
+# Visualize clusters
+DimPlot(scRNAlung, reduction = &quot;umap&quot;, label = T, group.by = &quot;Clusters&quot;) + 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 &lt;- getDeconvolution(GeoMxR1,
+                            sc.object = scRNAlung, sc.assay = &quot;RNA&quot;, 
+                            sc.cluster = &quot;Clusters&quot;, sc.samples = &quot;orig.ident&quot;)</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) &lt;- &quot;Decon&quot;
+vrProportionPlot(GeoMxR1, x.label = &quot;ROI.name&quot;)</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 &lt;- vrSpatialPoints(GeoMxR1)[GeoMxR1$ROI.type == &quot;fibrotic&quot;]
+GeoMxR1_subset &lt;- subset(GeoMxR1, spatialpoints = spatialpoints)
+
+# Proportion plot
+vrProportionPlot(GeoMxR1_subset, x.label = &quot;ROI.name&quot;, split.method = &quot;facet_grid&quot;, 
+                 split.by = &quot;Sample&quot;)
+
+# barplot 
+vrBarPlot(GeoMxR1_subset, features = c(&quot;stromal&quot;, &quot;macrophages&quot;), group.by = &quot;Sample&quot;,
+          x.label = &quot;ROI.name&quot;, split.by = &quot;Sample&quot;)</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&amp;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&amp;E images
+of from the same TMA blocks where GeoMx slides were established.</p>
+<p>We first import the H&amp;E image of the prolonged case 4 TMA section
+using the <strong>importImageData</strong> function. This will import
+the H&amp;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&amp;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 &lt;- importImageData(&quot;prolonged_case4_HE.tif&quot;, channel_names = &quot;H&amp;E&quot;)
+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&amp;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&amp;E image followed by a
+thin plate spline (TPS) alignment. The perspective transformation
+performs a global alignment between the H&amp;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&amp;E image and the GeoMx image for a more accurate</p>
+<pre class="r watch-out"><code>GeoMxR1_subset &lt;- subset(GeoMxR1, sample = c(&quot;prolonged case 4&quot;))
+GeoMxReg &lt;- 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&amp;E based VoltRon object.</p>
+<pre class="r watch-out"><code>vrHEimage_reg &lt;- GeoMxReg$registered_spat[[2]]</code></pre>
+<p>We can check the additional coordinate system now available for the
+registered H&amp;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] &quot;main&quot;     &quot;main_reg&quot;</code></pre>
+<p>We can also exchange images where the H&amp;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[[&quot;Assay1&quot;]], name = &quot;main&quot;, channel = &quot;H&amp;E&quot;) &lt;- vrImages(vrHEimage_reg, name = &quot;main_reg&quot;, channel = &quot;H&amp;E&quot;)</code></pre>
+<p>We can now observe the new channels (H&amp;E) available for the GeoMx
+assay using <strong>vrImageChannelNames</strong>. H&amp;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&amp;E visible in the background. We define the spatial key
+<strong>main</strong> and the channel name <strong>H&amp;E</strong>.</p>
+<pre class="r watch-out"><code>vrSpatialPlot(GeoMxR1_subset, group.by = &quot;ROI.type&quot;, alpha = 0.7, 
+              spatial = &quot;main&quot;, channel = &quot;H&amp;E&quot;)</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 = &quot;ROI.type&quot;, alpha = 0.7, 
+              spatial = &quot;main&quot;, channel = &quot;H&amp;E&quot;, 
+              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>