This vignette demonstrates how to use OME-TIFF files generated by the NanoString GeoMx® instrument to enhance the data visualization for a NanoString GeoMx experiment. SpatialOmicsOverlay was specifically made to visualize and analyze the free-handed nature of Region of Interest (ROI) selection in a GeoMx experiment, and the immunofluorescent-guided segmentation process. The overlay from the instrument is recreated in the R environment allowing for plotting overlays with data like ROI type or gene expression.
In this vignette, we will be walking through a mouse brain dataset from the Spatial Organ Atlas
Open Chrome and access your GeoMx workspace remotely:
In the GeoMx Scan Workspace, click the “Export Image” tab and export the image as an OME-TIFF. This will have to be done for each individual scan.
Files needed:
Reading in the SpatialOverlay object can be done with or without the image. We will start without the image as that can be added later.
If outline = TRUE
, only ROI outline points are saved.
This decreases memory needed and figure rendering time downstream. If
ANY ROIs are segmented in the study, outline will be FALSE. In this
particular example, there are segmented ROIs, so we set
outline = FALSE
.
In this example, we are downloading a TIFF image from AWS S3 but this variable is simply the file path to a OME-TIFF.
This function will be downloading a 13 GB file and will keep a 4 GB file in BiocFileCache. This download will take ~15 minutes but you will only have to download once
## [1] "/github/home/.cache/R/SpatialOmicsOverlay/205eb7f059c_mu_brain_004.ome.tiff"
muBrainLW <- system.file("extdata", "muBrain_LabWorksheet.txt",
package = "SpatialOmicsOverlay")
muBrain <- readSpatialOverlay(ometiff = tifFile, annots = muBrainLW,
slideName = "D5761 (3)", image = FALSE,
saveFile = FALSE, outline = FALSE)
The readSpatialOverlay function is a wrapper to walk through all of
the necessary steps to store the OME-TIFF file components. This function
automates XML extraction & parsing, image extraction, and coordinate
generation. These functions can also be run separately if desired
(xmlExtraction
, parseScanMetadata
,
parseOverlayAttrs
, addImageOmeTiff
,
createCoordFile
).
If you are getting a
java.lang.OutOfMemoryError: Java heap space
when running
readSpatialOverlay()
, restart your R session and try
increasing the maximum heap size by supplying the -Xmx parameter before
the Java Virtual Machine is initialized used by a dependency package
RBioFormats. Run the code below before loading any other libraries. RBioFormats
source
options(java.parameters = "-Xmx4g")
library(RBioFormats)
SpatialOverlay objects hold data specific to the image and the ROIs. Here are a couple of functions to access the most important parts.
## SpatialOverlay
## Slide Name: D5761 (3)
## Overlay Data: 93 samples
## Overlay Names: DSP-1012999073013-A-A02 ... DSP-1012999073013-A-H09 ( 93 total )
## Scan Metadata
## Panels: TAP Mouse Whole Transcriptome Atlas
## Segmentation: Segmented
## Outline: FALSE
## [1] "DSP-1012999073013-A-A02" "DSP-1012999073013-A-A03"
## [3] "DSP-1012999073013-A-A04" "DSP-1012999073013-A-A05"
## [5] "DSP-1012999073013-A-A06" "DSP-1012999073013-A-A07"
## [1] "D5761 (3)"
## ROILabel Sample_ID Height Width X Y Segmentation
## 1 001 DSP-1012999073013-A-A02 751 751 10363 15008 Geometric
## 2 002 DSP-1012999073013-A-A03 1239 782 14346 16630 Geometric
## 3 003 DSP-1012999073013-A-A04 1272 902 15664 16603 Geometric
## 4 004 DSP-1012999073013-A-A05 1119 1276 13707 16135 Geometric
## 5 005 DSP-1012999073013-A-A06 1054 1124 15932 16228 Geometric
## 6 006 DSP-1012999073013-A-A07 751 751 10756 14259 Geometric
## sampleID ycoor xcoor
## 1 DSP-1012999073013-A-A02 15383 10363
## 2 DSP-1012999073013-A-A02 15356 10364
## 3 DSP-1012999073013-A-A02 15357 10364
## 4 DSP-1012999073013-A-A02 15358 10364
## 5 DSP-1012999073013-A-A02 15359 10364
## 6 DSP-1012999073013-A-A02 15360 10364
After parsing, ROIs can be plotted without the image in the object. These plots are the highest resolution versions since there is no scaling down to the image size, and might take a little time to render. If the image is attached to the object, coordinates are automatically scaled down to the image size and plotted as if they are on top of the image.
While manipulating the figure, there is a low-resolution option for faster rendering times.
A scale bar is automatically calculated when plotting. This
functionality can be turned off using scaleBar = FALSE
.
Scale bars can be fully customized using corner
,
textDistance
, and variables that start with scaleBar:
scaleBarWidth
, scaleBarColor
, etc.
colorBy
, by default, is Sample_ID but almost any
annotation or data can be added instead, including gene expression,
tissue morphology annotations, pathway score, etc. These annotations can
come from a data.frame, matrix, GeomxSet object, or vector. Below we
attach the gene expression for CALM1 from a GeomxSet object and color
the segments by that value.
muBrainAnnots <- readLabWorksheet(lw = muBrainLW, slideName = "D5761 (3)")
muBrainGeomxSet <- readRDS(unzip(system.file("extdata", "muBrain_GxT.zip",
package = "SpatialOmicsOverlay")))
muBrain <- addPlottingFactor(overlay = muBrain, annots = muBrainAnnots,
plottingFactor = "segment")
muBrain <- addPlottingFactor(overlay = muBrain, annots = muBrainGeomxSet,
plottingFactor = "Calm1")
muBrain <- addPlottingFactor(overlay = muBrain, annots = 1:length(sampNames(muBrain)),
plottingFactor = "ROILabel")
muBrain
## SpatialOverlay
## Slide Name: D5761 (3)
## Overlay Data: 93 samples
## Overlay Names: DSP-1012999073013-A-A02 ... DSP-1012999073013-A-H09 ( 93 total )
## Scan Metadata
## Panels: TAP Mouse Whole Transcriptome Atlas
## Segmentation: Segmented
## Plotting Factors:
## varLabels: segment Calm1 ROILabel
## Outline: FALSE
## segment Calm1 ROILabel
## DSP-1012999073013-A-A02 Full ROI 1177 1
## DSP-1012999073013-A-A03 Full ROI 765 2
## DSP-1012999073013-A-A04 Full ROI 1045 3
## DSP-1012999073013-A-A05 Full ROI 1730 4
## DSP-1012999073013-A-A06 Full ROI 1119 5
## DSP-1012999073013-A-A07 Full ROI 600 6
All generated figures are ggplot based so they can be easily customized using functions from that or similar grammar of graphs packages. For example, we can change the color scale to the viridis color palette.
Note: hiRes and outline figures use fill, lowRes uses color
Images can be added automatically using
readSpatialOverlay(image = TRUE)
or added after reading in
the object.
An OME-TIFF file is a pyramidal file, meaning that many sizes of an image are saved. The largest having the highest resolution and decreasing as the image gets smaller. Images are 1/2 the size as the previous resolution.
The res
variable says which resolution of the image to
extract. 1 = largest image and the higher values get smaller. Each
OME-TIFF has a different number of layers, with most having around 8. It
is suggested to use the smallest res
value, and highest
resolution, your environment can handle. This is a trial and error
process.
Using too big of an image will cause a java memory error. If this
error occurs, increase your res
value. Below is an example
of the error you will receive if the resolution is too high for your
system.
Error in .jcall("RBioFormats", "Ljava/lang/Object;", "readPixels", i, :
java.lang.NegativeArraySizeException: -2147483648
The resolution size will affect speed and image resolution through
the rest of the analysis. To check the smallest resolution size
available, for the fastest speeds, use checkValidRes()
.
For the rest of this tutorial we will be using res = 8 for
vignette size restrictions, but res 4-6 is recommended.
## [1] 8
## SpatialOverlay
## Slide Name: D5761 (3)
## Overlay Data: 93 samples
## Overlay Names: DSP-1012999073013-A-A02 ... DSP-1012999073013-A-H09 ( 93 total )
## Scan Metadata
## Panels: TAP Mouse Whole Transcriptome Atlas
## Segmentation: Segmented
## Plotting Factors:
## varLabels: segment Calm1 ROILabel
## Outline: FALSE
## Image: /github/home/.cache/R/SpatialOmicsOverlay/205eb7f059c_mu_brain_004.ome.tiff
plotSpatialOverlay(overlay = muBrain, colorBy = "segment", corner = "topcenter",
scaleBarWidth = 0.5, textDistance = 130, scaleBarColor = "cyan")
There are 2 ways to add a legend to the graph showing the immunofluorescent visualization markers used.
The first is an easy way for data exploration, adding a legend to the
ggplot object directly by setting flourLegend = TRUE
.
plotSpatialOverlay(overlay = muBrain, colorBy = "segment", corner = "topcenter",
scaleBarWidth = 0.5, textDistance = 130, scaleBarColor = "cyan",
fluorLegend = TRUE)
The second requires more user manipulation but creates a more
publication-ready figure. The flourLegend
function creates
a separate plot that can be added to the graph. The legend shape can be
changed with nrow
and the background can be changed using
boxColor
and alpha
.
See ?draw_plot
for more instructions on how to
manipulate the legend position and scale.
library(cowplot)
gp <- plotSpatialOverlay(overlay = muBrain, colorBy = "segment",
corner = "bottomright")
legend <- fluorLegend(muBrain, nrow = 2, textSize = 4,
boxColor = "grey85", alpha = 0.3)
cowplot::ggdraw() +
cowplot::draw_plot(gp) +
cowplot::draw_plot(legend, scale = 0.105, x = 0.1, y = -0.25)
Images and overlays can be flipped across either axis to reorient the
image. To flip both axes use flipY(flipX(overlay))
. These
functions update the coordinates and image rather than just affecting
the figure. In this example, the original image is reversed from the
traditional view of the mouse brain, so we shall flip the Y-axis.
Images can be cropped 2 ways. The amount of area added to the cropped
area in both methods can be defined by buffer
. This adds a
percentage of the final image size to each edge.
cropTissue
automatically detects where the tissue is
and removes non-tissue area from around the tissue.muBrain <- cropTissue(overlay = muBrain, buffer = 0.05)
plotSpatialOverlay(overlay = muBrain, colorBy = "ROILabel", legend = FALSE, scaleBar = FALSE)+
viridis::scale_fill_viridis(option = "C")
2. cropSamples
automatically crops the image around the
ROIs given. Other ROIs in the cropped image can be kept in or ignored.
Below we will crop to only ROIs that are unsegmented, hiding ROIs
profiled which are segmented. Setting sampsOnly = TRUE
hides the segmented ROIs which are within the plotted region.
samps <- muBrainAnnots$Sample_ID[muBrainAnnots$segment == "Full ROI" &
muBrainAnnots$slide.name == slideName(muBrain)]
muBrainCrop <- cropSamples(overlay = muBrain, sampleIDs = samps, sampsOnly = TRUE)
plotSpatialOverlay(overlay = muBrainCrop, colorBy = "Calm1", scaleBar = TRUE,
corner = "bottomleft", textDistance = 5)+
ggplot2::scale_fill_gradient2(low = "grey", high = "red",
mid = "yellow", midpoint = 2500)
Image colors are typically determined before downloading the OME-TIFF from the instrument but can be recolored here.
This recoloring must be done on the 4 channel image before converting
to RGB. The color code and min/max intensities determine the coloring of
the RGB image. To view the current color definition use the
fluor
function.
The color can be a hex color or a valid R color name. The dye can
either come from the Dye or DisplayName columns from fluor(overlay). To
change a color use the changeImageColoring
function.
## Dye DisplayName Color WaveLength Target ExposureTime MinIntensity
## 1 Alexa 488 FITC Blue 525nm GFAP 200.0 µs 50
## 2 SYTO 83 Cy3 Green 568nm DNA 50.0 µs 4
## 3 Alexa 594 Texas Red Yellow 615nm Iba-1 300.0 µs 33
## 4 Alexa 647 Cy5 Red 666nm NeuN 100.0 µs 88
## MaxIntensity ColorCode
## 1 18509 #0000feff
## 2 805 #00fe00ff
## 3 3174 #fefe00ff
## 4 30000 #fe0000ff
chan4 <- changeImageColoring(overlay = chan4, color = "#32a8a4", dye = "FITC")
chan4 <- changeImageColoring(overlay = chan4, color = "magenta", dye = "Alexa 647")
chan4 <- changeColoringIntensity(overlay = chan4, minInten = 500,
maxInten = 10000, dye = "Cy5")
fluor(chan4)
## Dye DisplayName Color WaveLength Target ExposureTime
## 1 Alexa 488 FITC Lightseagreen 525nm GFAP 200.0 µs
## 2 SYTO 83 Cy3 Green 568nm DNA 50.0 µs
## 3 Alexa 594 Texas Red Yellow 615nm Iba-1 300.0 µs
## 4 Alexa 647 Cy5 Magenta 666nm NeuN 100.0 µs
## MinIntensity MaxIntensity ColorCode
## 1 50 18509 #32a8a4
## 2 4 805 #00fe00ff
## 3 33 3174 #fefe00ff
## 4 500 10000 magenta
In future releases of SpatialOmicsOverlay, we will be
## R version 4.4.2 (2024-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=en_US.UTF-8
## [9] LC_ADDRESS=en_US.UTF-8 LC_TELEPHONE=en_US.UTF-8
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=en_US.UTF-8
##
## time zone: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] cowplot_1.1.3 GeomxTools_3.11.0
## [3] NanoStringNCTools_1.15.0 ggplot2_3.5.1
## [5] S4Vectors_0.45.2 Biobase_2.67.0
## [7] BiocGenerics_0.53.3 generics_0.1.3
## [9] SpatialOmicsOverlay_1.7.0 RBioFormats_1.7.0
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 sys_3.4.3 jsonlite_1.8.9
## [4] magrittr_2.0.3 magick_2.8.5 ggbeeswarm_0.7.2
## [7] farver_2.1.2 nloptr_2.1.1 rmarkdown_2.29
## [10] zlibbioc_1.52.0 vctrs_0.6.5 memoise_2.0.1
## [13] minqa_1.2.8 RCurl_1.98-1.16 base64enc_0.1-3
## [16] htmltools_0.5.8.1 plotrix_3.8-4 curl_6.0.1
## [19] cellranger_1.1.0 sass_0.4.9 parallelly_1.39.0
## [22] bslib_0.8.0 htmlwidgets_1.6.4 plyr_1.8.9
## [25] cachem_1.1.0 uuid_1.2-1 commonmark_1.9.2
## [28] buildtools_1.0.0 lifecycle_1.0.4 pkgconfig_2.0.3
## [31] Matrix_1.7-1 R6_2.5.1 fastmap_1.2.0
## [34] GenomeInfoDbData_1.2.13 future_1.34.0 digest_0.6.37
## [37] numDeriv_2016.8-1.1 colorspace_2.1-1 GGally_2.2.1
## [40] RSQLite_2.3.8 labeling_0.4.3 filelock_1.0.3
## [43] progressr_0.15.1 fansi_1.0.6 httr_1.4.7
## [46] abind_1.4-8 compiler_4.4.2 withr_3.0.2
## [49] bit64_4.5.2 tiff_0.1-12 viridis_0.6.5
## [52] DBI_1.2.3 ggstats_0.7.0 MASS_7.3-61
## [55] rjson_0.2.23 tools_4.4.2 vipor_0.4.7
## [58] beeswarm_0.4.0 future.apply_1.11.3 glue_1.8.0
## [61] nlme_3.1-166 EBImage_4.49.0 gridtext_0.1.5
## [64] grid_4.4.2 reshape2_1.4.4 gtable_0.3.6
## [67] tidyr_1.3.1 data.table_1.16.2 sp_2.1-4
## [70] xml2_1.3.6 utf8_1.2.4 XVector_0.47.0
## [73] markdown_1.13 pillar_1.9.0 stringr_1.5.1
## [76] spam_2.11-0 rJava_1.0-11 splines_4.4.2
## [79] dplyr_1.1.4 ggtext_0.1.2 BiocFileCache_2.15.0
## [82] lattice_0.22-6 bit_4.5.0 tidyselect_1.2.1
## [85] locfit_1.5-9.10 pbapply_1.7-2 maketools_1.3.1
## [88] Biostrings_2.75.1 knitr_1.49 gridExtra_2.3
## [91] IRanges_2.41.1 scattermore_1.2 xfun_0.49
## [94] pheatmap_1.0.12 stringi_1.8.4 UCSC.utils_1.3.0
## [97] fftwtools_0.9-11 yaml_2.3.10 boot_1.3-31
## [100] evaluate_1.0.1 codetools_0.2-20 tibble_3.2.1
## [103] cli_3.6.3 systemfonts_1.1.0 munsell_0.5.1
## [106] jquerylib_0.1.4 Rcpp_1.0.13-1 GenomeInfoDb_1.43.2
## [109] readxl_1.4.3 globals_0.16.3 EnvStats_3.0.0
## [112] dbplyr_2.5.0 png_0.1-8 XML_3.99-0.17
## [115] parallel_4.4.2 blob_1.2.4 dotCall64_1.2
## [118] jpeg_0.1-10 bitops_1.0-9 lme4_1.1-35.5
## [121] listenv_0.9.1 viridisLite_0.4.2 ggthemes_5.1.0
## [124] ggiraph_0.8.11 lmerTest_3.1-3 scales_1.3.0
## [127] SeuratObject_5.0.2 purrr_1.0.2 crayon_1.5.3
## [130] rlang_1.1.4