This tutorial demonstrates how to coerce GeoMxSet objects into Seurat or SpatialExperiment objects and the subsequent analyses. For more examples of what analyses are available in these objects, look at these Seurat or SpatialExperiment vignettes.
Data Processing should occur in GeomxTools. Due to the unique nature of the regions of interest (ROIs), it is recommended to use the preproccesing steps available in GeomxTools rather than the single-cell made preprocessing available in Seurat.
library(GeomxTools)
library(Seurat)
library(SpatialDecon)
library(patchwork)
datadir <- system.file("extdata", "DSP_NGS_Example_Data",
package="GeomxTools")
DCCFiles <- dir(datadir, pattern=".dcc$", full.names=TRUE)
PKCFiles <- unzip(zipfile = file.path(datadir, "/pkcs.zip"))
SampleAnnotationFile <- file.path(datadir, "annotations.xlsx")
demoData <-
suppressWarnings(readNanoStringGeoMxSet(dccFiles = DCCFiles,
pkcFiles = PKCFiles,
phenoDataFile = SampleAnnotationFile,
phenoDataSheet = "CW005",
phenoDataDccColName = "Sample_ID",
protocolDataColNames = c("aoi",
"cell_line",
"roi_rep",
"pool_rep",
"slide_rep")))
After reading in the object, we will do a couple of QC steps.
demoData <- shiftCountsOne(demoData, useDALogic=TRUE)
demoData <- setSegmentQCFlags(demoData, qcCutoffs = list(percentSaturation = 45))
demoData <- setBioProbeQCFlags(demoData)
# low sequenced ROIs
lowSaturation <- which(protocolData(demoData)[["QCFlags"]]$LowSaturation)
# probes that are considered outliers
lowQCprobes <- which(featureData(demoData)[["QCFlags"]]$LowProbeRatio |
featureData(demoData)[["QCFlags"]]$GlobalGrubbsOutlier)
# remove low quality ROIs and probes
passedQC <- demoData[-lowQCprobes, -lowSaturation]
dim(demoData)
## Features Samples
## 8707 88
dim(passedQC)
## Features Samples
## 8698 83
Objects must be aggregated to Target level data before coercing. This changes the row (gene) information to be the gene name rather than the probe ID.
featureType(passedQC)
## [1] "Probe"
data.frame(assayData(passedQC)[["exprs"]][seq_len(3), seq_len(3)])
DSP.1001250002642.A02.dcc | DSP.1001250002642.A03.dcc | DSP.1001250002642.A04.dcc | |
---|---|---|---|
RTS0039454 | 294 | 239 | 6 |
RTS0039455 | 270 | 281 | 6 |
RTS0039456 | 255 | 238 | 3 |
target_demoData <- aggregateCounts(passedQC)
featureType(target_demoData)
## [1] "Target"
data.frame(assayData(target_demoData)[["exprs"]][seq_len(3), seq_len(3)])
DSP.1001250002642.A02.dcc | DSP.1001250002642.A03.dcc | DSP.1001250002642.A04.dcc | |
---|---|---|---|
ACTA2 | 328.286182 | 323.490808 | 6.081111 |
FOXA2 | 4.919019 | 4.919019 | 6.942503 |
NANOG | 2.954177 | 4.128918 | 8.359554 |
It is recommended to normalize using a GeoMx specific model before coercing. The normalized data is now in the assayData slot called “q_norm”.
norm_target_demoData <- normalize(target_demoData, norm_method="quant",
desiredQuantile = .75, toElt = "q_norm")
assayDataElementNames(norm_target_demoData)
## [1] "exprs" "q_norm"
data.frame(assayData(norm_target_demoData)[["q_norm"]][seq_len(3), seq_len(3)])
DSP.1001250002642.A02.dcc | DSP.1001250002642.A03.dcc | DSP.1001250002642.A04.dcc | |
---|---|---|---|
ACTA2 | 349.571598 | 344.257297 | 3.968122 |
FOXA2 | 5.237958 | 5.234795 | 4.530208 |
NANOG | 3.145720 | 4.393974 | 5.454880 |
The three errors that can occur when trying to coerce to Seurat are:
as.Seurat(demoData)
## Error in as.Seurat.NanoStringGeoMxSet(demoData): Data must be on Target level before converting to a Seurat Object
as.Seurat(target_demoData, normData = "exprs")
## Error in as.Seurat.NanoStringGeoMxSet(target_demoData, normData = "exprs"): It is NOT recommended to use Seurat's normalization for GeoMx data.
## Normalize using GeomxTools::normalize() or set forceRaw to TRUE if you want to continue with Raw data
as.Seurat(norm_target_demoData, normData = "exprs_norm")
## Error in as.Seurat.NanoStringGeoMxSet(norm_target_demoData, normData = "exprs_norm"): The normData name "exprs_norm" is not a valid assay name. Valid names are: exprs, q_norm
After coercing to a Seurat object all of the metadata is still accessible.
demoSeurat <- as.Seurat(x = norm_target_demoData, normData = "q_norm")
demoSeurat # overall data object
## An object of class Seurat
## 1821 features across 83 samples within 1 assay
## Active assay: GeoMx (1821 features, 0 variable features)
## 2 layers present: counts, data
head(demoSeurat, 3) # most important ROI metadata
orig.ident | nCount_GeoMx | nFeature_GeoMx | slide name | scan name | panel | roi | segment | area | NegGeoMean_Six-gene_test_v1_v1.1 | NegGeoMean_VnV_GeoMx_Hs_CTA_v1.2 | NegGeoSD_Six-gene_test_v1_v1.1 | NegGeoSD_VnV_GeoMx_Hs_CTA_v1.2 | q_norm_qFactors | SampleID | aoi | cell_line | roi_rep | pool_rep | slide_rep | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | GeoMx | 63524.55 | 1821 | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 1 | Geometric Segment | 31318.73 | 1.487738 | 3.722752 | 1.560397 | 1.796952 | 0.9391100 | DSP-1001250002642-A02 | Geometric Segment-aoi-001 | HS578T | 1 | 1 | 1 |
DSP-1001250002642-A03.dcc | GeoMx | 62357.01 | 1821 | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 2 | Geometric Segment | 31318.73 | 2.518775 | 3.068217 | 1.820611 | 1.806070 | 0.9396774 | DSP-1001250002642-A03 | Geometric Segment-aoi-001 | HS578T | 2 | 1 | 1 |
DSP-1001250002642-A04.dcc | GeoMx | 82370.45 | 1821 | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 3 | Geometric Segment | 31318.73 | 2.847315 | 3.556275 | 1.654831 | 1.762066 | 1.5324910 | DSP-1001250002642-A04 | Geometric Segment-aoi-001 | HEL | 1 | 1 | 1 |
demoSeurat@misc[1:8] # experiment data
## $PKCFileName
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "VnV Cancer Transcriptome Atlas" "Six gene test custom"
##
## $PKCModule
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "VnV_GeoMx_Hs_CTA" "Six-gene_test_v1"
##
## $PKCFileVersion
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 1.2 1.1
##
## $PKCFileDate
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "200518" "200707"
##
## $AnalyteType
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "RNA" "RNA"
##
## $MinArea
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 16000 16000
##
## $MinNuclei
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 200 200
##
## $shiftedByOne
## [1] TRUE
head(demoSeurat@misc$sequencingMetrics) # sequencing metrics
FileVersion | SoftwareVersion | Date | Plate_ID | Well | SeqSetId | Raw | Trimmed | Stitched | Aligned | umiQ30 | rtsQ30 | DeduplicatedReads | NTC_ID | NTC | Trimmed (%) | Stitched (%) | Aligned (%) | Saturated (%) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A02 | VH00121:3:AAAG2YWM5 | 646250 | 646250 | 616150 | 610390 | 0.9785 | 0.9804 | 312060 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.34236 | 94.45106 | 48.87531 |
DSP-1001250002642-A03.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A03 | VH00121:3:AAAG2YWM5 | 629241 | 629241 | 603243 | 597280 | 0.9784 | 0.9811 | 305528 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.86836 | 94.92071 | 48.84677 |
DSP-1001250002642-A04.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A04 | VH00121:3:AAAG2YWM5 | 831083 | 831083 | 798188 | 791804 | 0.9785 | 0.9801 | 394981 | DSP-1001250002642-A01.dcc | 7 | 100 | 96.04191 | 95.27376 | 50.11632 |
DSP-1001250002642-A05.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A05 | VH00121:3:AAAG2YWM5 | 884485 | 884485 | 849060 | 842133 | 0.9796 | 0.9814 | 424162 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.99484 | 95.21168 | 49.63242 |
DSP-1001250002642-A06.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A06 | VH00121:3:AAAG2YWM5 | 781936 | 781936 | 751930 | 744669 | 0.9779 | 0.9803 | 355121 | DSP-1001250002642-A01.dcc | 7 | 100 | 96.16260 | 95.23401 | 52.31156 |
DSP-1001250002642-A07.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A07 | VH00121:3:AAAG2YWM5 | 703034 | 703034 | 674815 | 668726 | 0.9776 | 0.9797 | 341008 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.98611 | 95.12001 | 49.00632 |
head(demoSeurat@misc$QCMetrics$QCFlags) # QC metrics
LowReads | LowTrimmed | LowStitched | LowAligned | LowSaturation | LowNegatives | HighNTC | LowArea | |
---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A03.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A04.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A05.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A06.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A07.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
head(demoSeurat@assays$GeoMx@meta.data) # gene metadata
TargetName | Module | CodeClass | GeneID | SystematicName | Negative |
---|---|---|---|---|---|
ACTA2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 59 | ACTA2 | FALSE |
FOXA2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 3170 | FOXA2 | FALSE |
NANOG | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 79923, 388112 | NANOG, NANOGP8 | FALSE |
TRAC | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRAC | FALSE |
TRBC1/2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRBC1 | FALSE |
TRDC | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRDC | FALSE |
All Seurat functionality is available after coercing. Outputs might differ if the ident value is set or not.
VlnPlot(demoSeurat, features = "nCount_GeoMx", pt.size = 0.1)
demoSeurat <- as.Seurat(norm_target_demoData, normData = "q_norm", ident = "cell_line")
VlnPlot(demoSeurat, features = "nCount_GeoMx", pt.size = 0.1)
Here is an example of a typical dimensional reduction workflow.
demoSeurat <- FindVariableFeatures(demoSeurat)
demoSeurat <- ScaleData(demoSeurat)
demoSeurat <- RunPCA(demoSeurat, assay = "GeoMx", verbose = FALSE)
demoSeurat <- FindNeighbors(demoSeurat, reduction = "pca", dims = seq_len(30))
demoSeurat <- FindClusters(demoSeurat, verbose = FALSE)
demoSeurat <- RunUMAP(demoSeurat, reduction = "pca", dims = seq_len(30))
DimPlot(demoSeurat, reduction = "umap", label = TRUE, group.by = "cell_line")
Here is a work through of a more indepth DSP dataset. This is a non-small cell lung cancer (nsclc) tissue sample that has an ROI strategy to simulate a visium dataset (55 um circles evenly spaced apart). It was segmented on tumor and non-tumor.
data("nsclc", package = "SpatialDecon")
nsclc
## NanoStringGeoMxSet (storageMode: lockedEnvironment)
## assayData: 1700 features, 199 samples
## element names: exprs, exprs_norm
## protocolData
## sampleNames: ROI01Tumor ROI01TME ... ROI100TME (199 total)
## varLabels: Mask.type Raw ... hkFactors (17 total)
## varMetadata: labelDescription
## phenoData
## sampleNames: ROI01Tumor ROI01TME ... ROI100TME (199 total)
## varLabels: Sample_ID Tissue ... istumor (10 total)
## varMetadata: labelDescription
## featureData
## featureNames: ABCF1 ABL1 ... LAG3 (1700 total)
## fvarLabels: TargetName HUGOSymbol ... Negative (9 total)
## fvarMetadata: labelDescription
## experimentData: use 'experimentData(object)'
## Annotation: kiloplex with cell type spike-in [legacy panel]
## signature: none
## feature: Target
## analyte: RNA
dim(nsclc)
## Features Samples
## 1700 199
data.frame(exprs(nsclc)[seq_len(5), seq_len(5)])
ROI01Tumor | ROI01TME | ROI02Tumor | ROI02TME | ROI03Tumor | |
---|---|---|---|---|---|
ABCF1 | 55 | 26 | 47 | 30 | 102 |
ABL1 | 21 | 22 | 27 | 18 | 47 |
ACVR1B | 89 | 30 | 57 | 29 | 122 |
ACVR1C | 9 | 7 | 4 | 8 | 14 |
ACVR2A | 14 | 15 | 9 | 12 | 22 |
head(pData(nsclc))
Sample_ID | Tissue | Slide.name | ROI | AOI.name | AOI.annotation | x | y | nuclei | istumor | |
---|---|---|---|---|---|---|---|---|---|---|
ROI01Tumor | ICP20th-L11-ICPKilo-ROI01-Tumor-A02 | L11 | ICPKilo | ROI01 | Tumor | PanCK | 0 | 8000 | 572 | TRUE |
ROI01TME | ICP20th-L11-ICPKilo-ROI01-TME-A03 | L11 | ICPKilo | ROI01 | TME | TME | 0 | 8000 | 733 | FALSE |
ROI02Tumor | ICP20th-L11-ICPKilo-ROI02-Tumor-A04 | L11 | ICPKilo | ROI02 | Tumor | PanCK | 600 | 8000 | 307 | TRUE |
ROI02TME | ICP20th-L11-ICPKilo-ROI02-TME-A05 | L11 | ICPKilo | ROI02 | TME | TME | 600 | 8000 | 697 | FALSE |
ROI03Tumor | ICP20th-L11-ICPKilo-ROI03-Tumor-A06 | L11 | ICPKilo | ROI03 | Tumor | PanCK | 1200 | 8000 | 583 | TRUE |
ROI03TME | ICP20th-L11-ICPKilo-ROI03-TME-A07 | L11 | ICPKilo | ROI03 | TME | TME | 1200 | 8000 | 484 | FALSE |
When coercing, we can add the coordinate columns allowing for spatial graphing using Seurat.
nsclcSeurat <- as.Seurat(nsclc, normData = "exprs_norm", ident = "AOI.annotation",
coordinates = c("x", "y"))
nsclcSeurat
## An object of class Seurat
## 1700 features across 199 samples within 1 assay
## Active assay: GeoMx (1700 features, 0 variable features)
## 2 layers present: counts, data
## 1 image present: image
VlnPlot(nsclcSeurat, features = "nCount_GeoMx", pt.size = 0.1)
nsclcSeurat <- FindVariableFeatures(nsclcSeurat)
nsclcSeurat <- ScaleData(nsclcSeurat)
nsclcSeurat <- RunPCA(nsclcSeurat, assay = "GeoMx", verbose = FALSE)
nsclcSeurat <- FindNeighbors(nsclcSeurat, reduction = "pca", dims = seq_len(30))
nsclcSeurat <- FindClusters(nsclcSeurat, verbose = FALSE)
nsclcSeurat <- RunUMAP(nsclcSeurat, reduction = "pca", dims = seq_len(30))
DimPlot(nsclcSeurat, reduction = "umap", label = TRUE, group.by = "AOI.name")
Because this dataset is segmented, we need to separate the tumor and TME sections before using the spatial graphing. These Seurat functions were created for Visium data, so they can only plot the same sized circles.
Here we are showing the gene counts in each ROI separated by segment.
tumor <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "Tumor"],
features = "nCount_GeoMx", pt.size.factor = 12) +
labs(title = "Tumor") +
theme(legend.position = "none") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat$nCount_GeoMx),
max(nsclcSeurat$nCount_GeoMx))))
TME <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "TME"],
features = "nCount_GeoMx", pt.size.factor = 12) +
labs(title = "TME") +
theme(legend.position = "right") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat$nCount_GeoMx),
max(nsclcSeurat$nCount_GeoMx))))
wrap_plots(tumor, TME)
Here we show the count for A2M
tumor <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "Tumor"],
features = "A2M", pt.size.factor = 12) +
labs(title = "Tumor") +
theme(legend.position = "none") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat@assays$GeoMx$data["A2M",]),
max(nsclcSeurat@assays$GeoMx$data["A2M",]))))
TME <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "TME"],
features = "A2M", pt.size.factor = 12) +
labs(title = "TME") +
theme(legend.position = "right") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat@assays$GeoMx$data["A2M",]),
max(nsclcSeurat@assays$GeoMx$data["A2M",]))))
wrap_plots(tumor, TME)
Using the FindMarkers built in function from Seurat, we can determine the most differentially expressed genes in Tumor and TME
Idents(nsclcSeurat) <- nsclcSeurat$AOI.name
de_genes <- FindMarkers(nsclcSeurat, ident.1 = "Tumor", ident.2 = "TME")
de_genes <- de_genes[order(abs(de_genes$avg_log2FC), decreasing = TRUE),]
de_genes <- de_genes[is.finite(de_genes$avg_log2FC) & de_genes$p_val < 1e-25,]
for(i in rownames(de_genes)[1:2]){
print(data.frame(de_genes[i,]))
tumor <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "Tumor"],
features = i, pt.size.factor = 12) +
labs(title = "Tumor") +
theme(legend.position = "none") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat@assays$GeoMx$data[i,]),
max(nsclcSeurat@assays$GeoMx$data[i,]))))
TME <- suppressMessages(SpatialFeaturePlot(nsclcSeurat[,nsclcSeurat$AOI.name == "TME"],
features = i, pt.size.factor = 12) +
labs(title = "TME") +
theme(legend.position = "right") +
scale_fill_continuous(type = "viridis",
limits = c(min(nsclcSeurat@assays$GeoMx$data[i,]),
max(nsclcSeurat@assays$GeoMx$data[i,]))))
print(wrap_plots(tumor, TME))
}
## p_val avg_log2FC pct.1 pct.2 p_val_adj
## CEACAM6 1.756187e-31 754.903 1 1 2.985517e-28
## p_val avg_log2FC pct.1 pct.2 p_val_adj
## LYZ 9.276639e-32 -615.2034 1 1 1.577029e-28
SpatialExperiment is an S4 class inheriting from SingleCellExperiment. It is meant as a data storage object rather than an analysis suite like Seurat. Because of this, this section won’t have the fancy analysis outputs like the Seurat section had but will show where in the object all the pieces are stored.
library(SpatialExperiment)
The three errors that can occur when trying to coerce to SpatialExperiment are:
as.SpatialExperiment(demoData)
## Error in as.SpatialExperiment.NanoStringGeoMxSet(demoData): Data must be on Target level before converting to a SpatialExperiment Object
as.SpatialExperiment(target_demoData, normData = "exprs")
## Error in as.SpatialExperiment.NanoStringGeoMxSet(target_demoData, normData = "exprs"): It is NOT recommended to use Seurat's normalization for GeoMx data.
## Normalize using GeomxTools::normalize() or set forceRaw to TRUE if you want to continue with Raw data
as.SpatialExperiment(norm_target_demoData, normData = "exprs_norm")
## Error in as.SpatialExperiment.NanoStringGeoMxSet(norm_target_demoData, : The normData name "exprs_norm" is not a valid assay name. Valid names are: exprs, q_norm
After coercing to a SpatialExperiment object all of the metadata is still accessible.
demoSPE <- as.SpatialExperiment(norm_target_demoData, normData = "q_norm")
demoSPE # overall data object
## class: SpatialExperiment
## dim: 1821 83
## metadata(11): PKCFileName PKCModule ... sequencingMetrics QCMetrics
## assays(1): GeoMx
## rownames(1821): ACTA2 FOXA2 ... C1orf43 SNRPD3
## rowData names(6): TargetName Module ... SystematicName Negative
## colnames(83): DSP-1001250002642-A02.dcc DSP-1001250002642-A03.dcc ...
## DSP-1001250002642-H04.dcc DSP-1001250002642-H05.dcc
## colData names(18): slide name scan name ... slide_rep sample_id
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(0) :
## imgData names(0):
data.frame(head(colData(demoSPE))) # most important ROI metadata
slide.name | scan.name | panel | roi | segment | area | NegGeoMean_Six.gene_test_v1_v1.1 | NegGeoMean_VnV_GeoMx_Hs_CTA_v1.2 | NegGeoSD_Six.gene_test_v1_v1.1 | NegGeoSD_VnV_GeoMx_Hs_CTA_v1.2 | q_norm_qFactors | SampleID | aoi | cell_line | roi_rep | pool_rep | slide_rep | sample_id | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 1 | Geometric Segment | 31318.73 | 1.487738 | 3.722752 | 1.560397 | 1.796952 | 0.9391100 | DSP-1001250002642-A02 | Geometric Segment-aoi-001 | HS578T | 1 | 1 | 1 | sample01 |
DSP-1001250002642-A03.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 2 | Geometric Segment | 31318.73 | 2.518775 | 3.068217 | 1.820611 | 1.806070 | 0.9396774 | DSP-1001250002642-A03 | Geometric Segment-aoi-001 | HS578T | 2 | 1 | 1 | sample01 |
DSP-1001250002642-A04.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 3 | Geometric Segment | 31318.73 | 2.847315 | 3.556275 | 1.654831 | 1.762066 | 1.5324910 | DSP-1001250002642-A04 | Geometric Segment-aoi-001 | HEL | 1 | 1 | 1 | sample01 |
DSP-1001250002642-A05.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 4 | Geometric Segment | 31318.73 | 2.632148 | 3.785600 | 2.042222 | 1.793823 | 1.6725916 | DSP-1001250002642-A05 | Geometric Segment-aoi-001 | HEL | 2 | 1 | 1 | sample01 |
DSP-1001250002642-A06.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 5 | Geometric Segment | 31318.73 | 2.275970 | 4.064107 | 1.812577 | 1.839165 | 1.2351225 | DSP-1001250002642-A06 | Geometric Segment-aoi-001 | U118MG | 1 | 1 | 1 | sample01 |
DSP-1001250002642-A07.dcc | 6panel-old-slide1 (PTL-10891) | cw005 (PTL-10891) Slide1 | (v1.2) VnV Cancer Transcriptome Atlas, (v1.0) Six gene test custom | 6 | Geometric Segment | 31318.73 | 2.059767 | 4.153701 | 1.952628 | 1.626391 | 1.2229991 | DSP-1001250002642-A07 | Geometric Segment-aoi-001 | U118MG | 2 | 1 | 1 | sample01 |
demoSPE@metadata[1:8] # experiment data
## $PKCFileName
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "VnV Cancer Transcriptome Atlas" "Six gene test custom"
##
## $PKCModule
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "VnV_GeoMx_Hs_CTA" "Six-gene_test_v1"
##
## $PKCFileVersion
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 1.2 1.1
##
## $PKCFileDate
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "200518" "200707"
##
## $AnalyteType
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## "RNA" "RNA"
##
## $MinArea
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 16000 16000
##
## $MinNuclei
## VnV_GeoMx_Hs_CTA_v1.2 Six-gene_test_v1_v1.1
## 200 200
##
## $shiftedByOne
## [1] TRUE
head(demoSPE@metadata$sequencingMetrics) # sequencing metrics
FileVersion | SoftwareVersion | Date | Plate_ID | Well | SeqSetId | Raw | Trimmed | Stitched | Aligned | umiQ30 | rtsQ30 | DeduplicatedReads | NTC_ID | NTC | Trimmed (%) | Stitched (%) | Aligned (%) | Saturated (%) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A02 | VH00121:3:AAAG2YWM5 | 646250 | 646250 | 616150 | 610390 | 0.9785 | 0.9804 | 312060 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.34236 | 94.45106 | 48.87531 |
DSP-1001250002642-A03.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A03 | VH00121:3:AAAG2YWM5 | 629241 | 629241 | 603243 | 597280 | 0.9784 | 0.9811 | 305528 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.86836 | 94.92071 | 48.84677 |
DSP-1001250002642-A04.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A04 | VH00121:3:AAAG2YWM5 | 831083 | 831083 | 798188 | 791804 | 0.9785 | 0.9801 | 394981 | DSP-1001250002642-A01.dcc | 7 | 100 | 96.04191 | 95.27376 | 50.11632 |
DSP-1001250002642-A05.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A05 | VH00121:3:AAAG2YWM5 | 884485 | 884485 | 849060 | 842133 | 0.9796 | 0.9814 | 424162 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.99484 | 95.21168 | 49.63242 |
DSP-1001250002642-A06.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A06 | VH00121:3:AAAG2YWM5 | 781936 | 781936 | 751930 | 744669 | 0.9779 | 0.9803 | 355121 | DSP-1001250002642-A01.dcc | 7 | 100 | 96.16260 | 95.23401 | 52.31156 |
DSP-1001250002642-A07.dcc | 0.1 | 1.0.0 | 2020-07-14 | 1001250002642 | A07 | VH00121:3:AAAG2YWM5 | 703034 | 703034 | 674815 | 668726 | 0.9776 | 0.9797 | 341008 | DSP-1001250002642-A01.dcc | 7 | 100 | 95.98611 | 95.12001 | 49.00632 |
head(demoSPE@metadata$QCMetrics$QCFlags) # QC metrics
LowReads | LowTrimmed | LowStitched | LowAligned | LowSaturation | LowNegatives | HighNTC | LowArea | |
---|---|---|---|---|---|---|---|---|
DSP-1001250002642-A02.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A03.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A04.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A05.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A06.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
DSP-1001250002642-A07.dcc | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
data.frame(head(rowData(demoSPE))) # gene metadata
TargetName | Module | CodeClass | GeneID | SystematicName | Negative | |
---|---|---|---|---|---|---|
ACTA2 | ACTA2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 59 | ACTA2 | FALSE |
FOXA2 | FOXA2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 3170 | FOXA2 | FALSE |
NANOG | NANOG | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | 79923, 388112 | NANOG, NANOGP8 | FALSE |
TRAC | TRAC | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRAC | FALSE |
TRBC1/2 | TRBC1/2 | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRBC1 | FALSE |
TRDC | TRDC | VnV_GeoMx_Hs_CTA_v1.2 | Endogenous | NA | TRDC | FALSE |
When coercing, we can add the coordinate columns and they will be appended to the correct location in SpatialExperiment
nsclcSPE <- as.SpatialExperiment(nsclc, normData = "exprs_norm",
coordinates = c("x", "y"))
nsclcSPE
## class: SpatialExperiment
## dim: 1700 199
## metadata(1): sequencingMetrics
## assays(1): GeoMx
## rownames(1700): ABCF1 ABL1 ... TNFSF4 LAG3
## rowData names(9): TargetName HUGOSymbol ... GlobalOutliers Negative
## colnames(199): ROI01Tumor ROI01TME ... ROI100Tumor ROI100TME
## colData names(20): Sample_ID Tissue ... hkFactors sample_id
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(2) : x y
## imgData names(0):
data.frame(head(spatialCoords(nsclcSPE)))
x | y | |
---|---|---|
ROI01Tumor | 0 | 8000 |
ROI01TME | 0 | 8000 |
ROI02Tumor | 600 | 8000 |
ROI02TME | 600 | 8000 |
ROI03Tumor | 1200 | 8000 |
ROI03TME | 1200 | 8000 |
With the coordinates and the metadata, we can create spatial graphing figures similar to Seurat’s. To get the same orientation as Seurat we must swap the axes and flip the y.
figureData <- as.data.frame(cbind(colData(nsclcSPE), spatialCoords(nsclcSPE)))
figureData <- cbind(figureData, A2M=as.numeric(nsclcSPE@assays@data$GeoMx["A2M",]))
tumor <- ggplot(figureData[figureData$AOI.name == "Tumor",], aes(x=y, y=-x, color = A2M))+
geom_point(size = 6)+
scale_color_continuous(type = "viridis",
limits = c(min(figureData$A2M),
max(figureData$A2M)))+
theme(legend.position = "none", panel.grid = element_blank(),
panel.background = element_rect(fill = "white"),
axis.title = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank(), axis.line = element_blank())+
labs(title = "Tumor")
TME <- ggplot(figureData[figureData$AOI.name == "TME",], aes(x=y, y=-x, color = A2M))+
geom_point(size = 6)+
scale_color_continuous(type = "viridis",
limits = c(min(figureData$A2M),
max(figureData$A2M))) +
theme(panel.grid = element_blank(),
panel.background = element_rect(fill = "white"), axis.title = element_blank(),
axis.text = element_blank(), axis.ticks = element_blank(), axis.line = element_blank())+
labs(title = "TME")
wrap_plots(tumor, TME)
The free-handed nature of Region of Interest (ROI) selection in a GeoMx experiment makes visualization on top of the image difficult in packages designed for different data. We created SpatialOmicsOverlay specifically to visualize and analyze these types of ROIs in a GeoMx experiment and the immunofluorescent-guided segmentation process.
sessionInfo()
## R Under development (unstable) (2024-10-21 r87258)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.21-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB 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=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] SpatialExperiment_1.17.0 SingleCellExperiment_1.29.0
## [3] SummarizedExperiment_1.37.0 GenomicRanges_1.59.0
## [5] GenomeInfoDb_1.43.0 IRanges_2.41.0
## [7] MatrixGenerics_1.19.0 matrixStats_1.4.1
## [9] patchwork_1.3.0 SpatialDecon_1.17.0
## [11] Seurat_5.1.0 SeuratObject_5.0.2
## [13] sp_2.1-4 ggiraph_0.8.10
## [15] EnvStats_3.0.0 GeomxTools_3.11.0
## [17] NanoStringNCTools_1.15.0 ggplot2_3.5.1
## [19] S4Vectors_0.45.0 Biobase_2.67.0
## [21] BiocGenerics_0.53.0
##
## loaded via a namespace (and not attached):
## [1] RcppAnnoy_0.0.22 splines_4.5.0 later_1.3.2
## [4] R.oo_1.26.0 tibble_3.2.1 cellranger_1.1.0
## [7] polyclip_1.10-7 fastDummies_1.7.4 lifecycle_1.0.4
## [10] globals_0.16.3 lattice_0.22-6 MASS_7.3-61
## [13] magrittr_2.0.3 limma_3.63.0 plotly_4.10.4
## [16] sass_0.4.9 rmarkdown_2.28 jquerylib_0.1.4
## [19] yaml_2.3.10 httpuv_1.6.15 sctransform_0.4.1
## [22] spam_2.11-0 spatstat.sparse_3.1-0 reticulate_1.39.0
## [25] cowplot_1.1.3 pbapply_1.7-2 minqa_1.2.8
## [28] RColorBrewer_1.1-3 abind_1.4-8 zlibbioc_1.53.0
## [31] R.cache_0.16.0 Rtsne_0.17 R.utils_2.12.3
## [34] purrr_1.0.2 GenomeInfoDbData_1.2.13 ggrepel_0.9.6
## [37] irlba_2.3.5.1 listenv_0.9.1 spatstat.utils_3.1-0
## [40] pheatmap_1.0.12 goftest_1.2-3 RSpectra_0.16-2
## [43] spatstat.random_3.3-2 fitdistrplus_1.2-1 parallelly_1.38.0
## [46] DelayedArray_0.33.0 leiden_0.4.3.1 codetools_0.2-20
## [49] tidyselect_1.2.1 UCSC.utils_1.3.0 farver_2.1.2
## [52] lme4_1.1-35.5 spatstat.explore_3.3-3 jsonlite_1.8.9
## [55] progressr_0.15.0 ggridges_0.5.6 survival_3.7-0
## [58] systemfonts_1.1.0 tools_4.5.0 ica_1.0-3
## [61] Rcpp_1.0.13 glue_1.8.0 SparseArray_1.7.0
## [64] gridExtra_2.3 xfun_0.48 ggthemes_5.1.0
## [67] dplyr_1.1.4 withr_3.0.2 numDeriv_2016.8-1.1
## [70] fastmap_1.2.0 GGally_2.2.1 repmis_0.5
## [73] boot_1.3-31 fansi_1.0.6 digest_0.6.37
## [76] R6_2.5.1 mime_0.12 colorspace_2.1-1
## [79] scattermore_1.2 tensor_1.5 spatstat.data_3.1-2
## [82] R.methodsS3_1.8.2 utf8_1.2.4 tidyr_1.3.1
## [85] generics_0.1.3 data.table_1.16.2 S4Arrays_1.7.0
## [88] httr_1.4.7 htmlwidgets_1.6.4 ggstats_0.7.0
## [91] uwot_0.2.2 pkgconfig_2.0.3 gtable_0.3.6
## [94] lmtest_0.9-40 XVector_0.47.0 htmltools_0.5.8.1
## [97] dotCall64_1.2 scales_1.3.0 png_0.1-8
## [100] logNormReg_0.5-0 spatstat.univar_3.0-1 knitr_1.48
## [103] reshape2_1.4.4 rjson_0.2.23 uuid_1.2-1
## [106] nlme_3.1-166 nloptr_2.1.1 cachem_1.1.0
## [109] zoo_1.8-12 stringr_1.5.1 KernSmooth_2.23-24
## [112] parallel_4.5.0 miniUI_0.1.1.1 vipor_0.4.7
## [115] ggrastr_1.0.2 pillar_1.9.0 grid_4.5.0
## [118] vctrs_0.6.5 RANN_2.6.2 promises_1.3.0
## [121] xtable_1.8-4 cluster_2.1.6 beeswarm_0.4.0
## [124] evaluate_1.0.1 magick_2.8.5 cli_3.6.3
## [127] compiler_4.5.0 rlang_1.1.4 crayon_1.5.3
## [130] future.apply_1.11.3 labeling_0.4.3 plyr_1.8.9
## [133] ggbeeswarm_0.7.2 stringi_1.8.4 viridisLite_0.4.2
## [136] deldir_2.0-4 lmerTest_3.1-3 munsell_0.5.1
## [139] Biostrings_2.75.0 lazyeval_0.2.2 spatstat.geom_3.3-3
## [142] Matrix_1.7-1 RcppHNSW_0.6.0 future_1.34.0
## [145] statmod_1.5.0 shiny_1.9.1 highr_0.11
## [148] ROCR_1.0-11 igraph_2.1.1 bslib_0.8.0
## [151] readxl_1.4.3