A comprehensive report should expose the consequences of analytical choices. Its purpose is not to produce an attractive embedding or maximize the number of significant features. The workflow follows the analysis chain of the historical mouse-brain vignette: inspect measurements and correspondence; compare individual, spatial and integrated representations; characterize regions; examine paired features; then connect measured identities to pathways and networks.
| Question | Native interface | Evidence to inspect |
|---|---|---|
| What was measured and retained? | normalizeSMData(), native containers and
image access |
Selected layer, QC exclusions, scale and acquisition provenance |
| What changes when spatial information is added? | runMetabolicPCA(),
scaleSMData(), runSpatialGraphPCA() |
Same selected features and all retained observations in both representations |
| Does integration improve the representation? | multiOmicIntegration(),
getKmeanClusters() |
Individual versus joint structure; external-reference ARI, approximate silhouettes and sensitivity across K |
| Which features characterize a region? | findAllDEMs(method="markers"),
demsHeatmap() |
Pairwise AUC, Cohen effects, detection, mean expression and spatial-block sensitivity |
| Which differences reproduce across biological samples? | findAllDEMs(method="replicate") |
Explicit design, replicate means, effect intervals and the complete BH family |
| Is an association explained by regional composition? | findCorrelatedFeatures(),
plot3DFeature() |
Raw versus covariate-residual correlations and matched spatial layers |
| Which members support a pathway? | buildPathwayIndex(),
createPathwayAssay(),
findRegionalPathways() |
Measured coverage, ambiguity exclusions, complete ranks and leading edges |
| Are pathway members coordinated and where are they? | runRAMPGeseca(),
plotRegionalPathways(),
pathwayNetworkPlots() |
The same identity assay and membership index in every downstream view |
The first examples use synthetic teaching data, not
biological findings. Later sections execute the complete registered
human-brain, FMP10/Visium and DHB/Visium inputs, without downsampling
observations for analysis. Building this article downloads versioned
resources when no verified cache is available and can take tens of
minutes. The installed workflows/prepare_mouse_brain.R and
workflows/run_mouse_brain.R scripts also support offline
command-line use.
x <- SpaMTPData::spaMTPExampleData(paired = TRUE)
protein <- rbind(marker1 = c(1:6, 8:13), marker2 = c(6:1, 2:7),
marker3 = rep(c(2, 7, 4), 4))
colnames(protein) <- colnames(x)
SingleCellExperiment::altExp(x, "protein") <-
SingleCellExperiment::SingleCellExperiment(assays = list(counts = protein))
spec <- list(
main = list(type = "metabolomics", layer = "counts"),
transcriptome = list(type = "transcriptomics", layer = "counts"),
protein = list(type = "proteomics", layer = "counts")
)The workflow preserves the supplied layers. Its declared baseline
uses native library-size normalization followed by conversion to log2
units for raw MS/RNA counts, and log2(1 + value) for protein counts. For
already transformed data, choose normalization="none". This
baseline does not replace vendor-specific spectral processing, RNA count
QC or a platform-appropriate normalization design. In particular, logged
values must not be logged again or labelled raw counts.
Biological replication is an explicit metadata field. A pixel, technical pool, spatial block, image channel or integration cluster does not create an independent specimen. Transcriptomics, metabolomics and proteomics can be declared as three modalities; H&E, DAPI and RGB channels remain contextual images unless their measurements support a separate stated assay model.
fit <- runSpaMTPWorkflow(x, spec, regions = "region", clusters = 2,
npcs = 2, association_features = 3,
coordinate_units = "synthetic grid units",
structure = list(primary = "spatial", k_grid = c(2, 3),
reference = "region", umap = FALSE,
stability_blocks = 3))
fit$structure$metrics
## representation k approx_silhouette reference_ARI
## 1 main / PCA 2 0.3927081 0.66481994
## 2 main / PCA 3 0.4015610 0.47323944
## 3 main / Graph PCA 2 0.5855174 1.00000000
## 4 main / Graph PCA 3 0.6789031 0.84507042
## 5 transcriptome / PCA 2 0.3706615 -0.04336043
## 6 transcriptome / PCA 3 0.3584979 -0.04011461
## 7 transcriptome / Graph PCA 2 0.4607921 -0.05319149
## 8 transcriptome / Graph PCA 3 0.5043638 -0.04904632
## 9 protein / PCA 2 0.3304443 0.17728532
## 10 protein / PCA 3 0.4181479 0.27507163
## 11 protein / Graph PCA 2 0.5465039 1.00000000
## 12 protein / Graph PCA 3 0.5779831 0.84507042
## 13 Joint / PCA 2 0.1883832 -0.10000000
## 14 Joint / PCA 3 0.2316406 0.24137931
## 15 Joint / Graph PCA 2 0.2916312 0.66481994
## 16 Joint / Graph PCA 3 0.3836235 0.53521127
## conditional_stability stability_omissions spatial_neighbor_agreement
## 1 1.0000000 3 0.7037037
## 2 0.6428571 3 0.5185185
## 3 1.0000000 3 0.8148148
## 4 0.6534653 3 0.7037037
## 5 0.1600000 3 0.6111111
## 6 0.5098039 3 0.2407407
## 7 1.0000000 3 0.7222222
## 8 1.0000000 3 0.6111111
## 9 0.2857143 3 0.5000000
## 10 0.6298472 3 0.4259259
## 11 1.0000000 3 0.8148148
## 12 1.0000000 3 0.7037037
## 13 0.2800000 3 0.3888889
## 14 0.5087719 3 0.3333333
## 15 0.1384615 3 0.7592593
## 16 0.5000000 3 0.6481481
## smallest_cluster
## 1 5
## 2 2
## 3 6
## 4 1
## 5 3
## 6 3
## 7 2
## 8 1
## 9 5
## 10 3
## 11 6
## 12 1
## 13 6
## 14 4
## 15 5
## 16 1runMetabolicPCA(features=...) now records all selected
features explicitly. Ordinary and graph PCA use the same variable
features, centred and scaled in the same way. Graph PCA uses a sparse
Laplacian for every retained observation and keeps different samples in
separate spatial graphs. It is not fitted on a small report preview and
then discarded: graph embeddings feed the spatial joint representation
and can be selected as the downstream primary representation.
The joint representation uses multiOmicIntegration() to
concatenate standardized modality embeddings. This native implementation
is not Seurat WNN. Recovering and benchmarking WNN
requires a separate, validated method implementation. UMAP is a
visualization of a representation; clusters and metrics use its complete
retained dimensions. A nicer-looking UMAP is not a performance test.
The number of clusters and primary method are chosen before examining reference ARI. Approximate silhouettes assess separation, while ARI compares to supplied external annotation. Spatial-neighbor agreement is a smoothness diagnostic; spatial regularization increases it by construction. Spatial-block omission refits clustering conditional on full-data embeddings. It does not validate feature selection, normalization or generalization to new specimens.
markers <- fit$region_analysis$modalities$main$markers
head(markers$DEMs[, c("gene", "cluster", "logFC", "mean_auc",
"min_auc", "mean_cohen", "direction_stability")])
## gene cluster logFC mean_auc min_auc mean_cohen direction_stability
## 1 peak1 core -0.4483818 0.27777778 0.27777778 -0.7415451 1
## 2 peak2 core -0.5567565 0.22222222 0.22222222 -1.0026087 1
## 3 peak3 core -1.0282257 0.08333333 0.08333333 -1.6161042 1
## 4 peak4 core 0.6046004 0.66666667 0.66666667 0.8884857 1
## 5 peak5 core 0.9645023 0.88888889 0.88888889 1.5201261 1
## 6 peak6 core 0.9982865 0.91666667 0.91666667 1.4499620 1
demsHeatmap(markers, n = 2, only.pos = TRUE, logfc.threshold = 0,
order.by = "mean_auc", fontsize_row = 9, fontsize_col = 10)The native marker mode delegates pairwise scoring to
scran::scoreMarkers(). AUC measures pairwise concordance,
including half credit for ties. Mean and minimum AUC distinguish broadly
specific markers from features that separate only some regions. Cohen
effects account for within-region variability. Summaries equally weight
other eligible regions so that the largest anatomical compartment does
not automatically dominate the reference. Detection fractions refer to
non-zero values on the explicitly selected layer; residualized layers
need different interpretation.
Coordinate-only blocks support a leave-one-block-out sensitivity analysis. The result records the range of Cohen effects, marker-rank changes, direction agreement and omitted fits that were ineligible because a region became too small. These ranges are not confidence intervals. Region labels are held fixed, including when learned from these data, and no pixel-based P values are manufactured.
demsHeatmap() uses the analysis expression matrix
directly. Its FDR ordering now sorts numerical FDR; it no longer sorts a
regulation label or applies CPM to an already transformed marker matrix.
The heatmap, detection plot, spatial feature maps and interactive
explorer use the same ranked feature identifiers.
The published brain sections do not provide independent biological replicates. This design example therefore explicitly simulates four paired patients, each with three observations per condition; it is not an analysis of the real sections.
design <- expand.grid(pixel = seq_len(3), condition = c("control", "treated"),
patient_id = paste0("simulated_patient", seq_len(4)))
set.seed(1234)
expression <- matrix(rnorm(6 * nrow(design), mean = 5, sd = 0.3), nrow = 6,
dimnames = list(paste0("feature", seq_len(6)),
paste0("observation", seq_len(nrow(design)))))
expression[1:2, design$condition == "treated"] <-
expression[1:2, design$condition == "treated"] + 1.2
replicate_example <- SingleCellExperiment::SingleCellExperiment(
assays = list(logcounts = expression), colData = S4Vectors::DataFrame(design))
replicate_de <- findAllDEMs(replicate_example, ident = "condition", assay = "main",
slot = "logcounts", method = "replicate", replicate = "patient_id",
contrasts = list(treatment_control = list(
numerator = "treated", denominator = "control", paired = TRUE)))
stopifnot(identical(replicate_de$tests$treatment_control$status, "completed"))
head(replicate_de$tests$treatment_control$table)
## logFC CI.L CI.R AveExpr t P.Value adj.P.Val
## 1 1.25278467 0.8678480 1.6377213 5.496658 6.8374968 2.124161e-06 6.372483e-06
## 2 1.33581582 0.9516022 1.7200295 5.635477 7.3043865 8.730057e-07 5.238034e-06
## 3 0.01823587 -0.3016203 0.3380921 5.045249 0.1197793 9.059848e-01 9.059848e-01
## 4 0.18103195 -0.1034775 0.4655415 4.945062 1.3368060 1.979376e-01 3.958752e-01
## 5 0.06925296 -0.2216750 0.3601809 4.962307 0.5001068 6.230587e-01 7.476705e-01
## 6 0.06732186 -0.1952123 0.3298560 4.885462 0.5387413 5.966660e-01 7.476705e-01
## B feature
## 1 16.211052 feature1
## 2 19.483081 feature2
## 3 -6.949913 feature3
## 4 -6.071433 feature4
## 5 -6.833080 feature5
## 6 -6.813190 feature6This mode fits limma to equally weighted biological-replicate means
of the selected values. Paired contrasts retain complete pairs; at least
three complete pairs (or three independent replicates per arm) are
required. The result retains the design, coefficient, residual degrees
of freedom, replicate expression matrix, pointwise moderated intervals,
and every tested feature. BH correction is within modality and contrast.
A logFC column is a difference on the selected workflow
scale; it is not automatically a fold change in raw abundance. RNA count
models may instead require independently designed count pseudobulking
and edgeR/DESeq2.
The historical random-pool mode remains available for compatibility and emits a warning about technical partitions. It is never used by the automatic workflow.
head(fit$associations[[1]])
## feature1 feature2 correlation correlation_raw modality1 modality2
## 1 peak6 gene2 0.7618268 0.6014781 main transcriptome
## 6 peak3 gene1 -0.6226655 -0.5516854 main transcriptome
## 7 peak3 gene3 0.4880833 0.3666491 main transcriptome
## 8 peak3 gene2 0.2416135 0.1756689 main transcriptome
## 11 peak5 gene2 0.2343414 0.1851459 main transcriptome
## 2 peak6 gene4 -0.2282004 -0.2013184 main transcriptome
## observations
## 1 12
## 6 12
## 7 12
## 8 12
## 11 12
## 2 12findCorrelatedFeatures(covariates=...) retains raw
Pearson correlation and the correlation between both features after
regression on the declared sample, replicate and region fields. The
workflow queries regional marker anchors against all PCA-selected target
features. It records those selection sets and the matched observations.
Strong raw association can disappear after removing a common regional
shift. A residual association can still reflect spatial autocorrelation
or other unmeasured structure, and selected pairs require independent
validation.
Exact feature identifiers work for RNA and protein as well as
metabolites; no artificial m/z metadata is needed. The report includes
paired scatter plots and native plot3DFeature() views of
the same selected pairs.
Here the complete human-brain resource supplies a real measured panel
and its archived cout_labels cell labels. These are
descriptive groups from a single section, not independent replicates or
newly validated anatomical boundaries.
database <- loadSpaMTPDatabase(
c("source_df", "analyte", "analytehaspathway", "pathway"), version = "3.0.7")
gene_reference <- SpaMTPdb::spaMTPdbGeneReference(version = "2026.7.7")
gene_index <- buildGeneMappingIndex(database$source_df,
gene_reference = gene_reference)
index <- buildPathwayIndex(database, gene_index = gene_index)
real_data <- SpaMTPData::spaMTPData("human_brain_integrated", version = "1.1.0")
real_data <- normalizeSMData(real_data, "LogNormalize", assay = "SPT", verbose = FALSE)
identity <- createPathwayAssay(real_data, analyte_type = "genes",
assay = "SPT", slot = "logcounts", new_assay = "gene_ids",
pathway_index = index, organism = "Homo sapiens")
## Warning: 10 gene input(s) unresolved; inspect mapping status and
## candidate_gene_ids.
identity_markers <- findAllDEMs(identity, ident = "cout_labels", assay = "gene_ids",
slot = "logcounts", method = "markers", spatial_blocks = 0)
# Build a feature-by-region matrix of the complete identity-level effects.
ranks <- identity_markers$expression
for (region in colnames(ranks)) {
tab <- identity_markers$DEMs[identity_markers$DEMs$cluster == region, ]
ranks[, region] <- tab$logFC[match(rownames(ranks), tab$gene)]
}
set.seed(1234)
regional <- findRegionalPathways(identity, ident = "cout_labels",
ranks = list(genes = ranks), pathway_index = index,
min_path_size = 5, max_path_size = 500)
## | | | 0% | |==== | 6% | |========= | 12% | |============= | 19% | |================== | 25% | |====================== | 31% | |========================== | 38% | |=============================== | 44% | |=================================== | 50% | |======================================= | 56% | |============================================ | 62% | |================================================ | 69% | |==================================================== | 75% | |========================================================= | 81% | |============================================================= | 88% | |================================================================== | 94% | |======================================================================| 100%
## Warning in fgsea::fgseaMultilevel(pathways = sets, stats =
## used_ranks[[region]], : There were 3 pathways for which P-values were not
## calculated properly due to unbalanced (positive and negative) gene-level
## statistic values. For such pathways pval, padj, NES, log2err are set to NA. You
## can try to increase the value of the argument nPermSimple (for example set it
## nPermSimple = 10000)
## | | | 0% | |==== | 6% | |========= | 12% | |============= | 19% | |================== | 25% | |====================== | 31% | |========================== | 38% | |=============================== | 44% | |=================================== | 50% | |======================================= | 56% | |============================================ | 62% | |================================================ | 69% | |==================================================== | 75% | |========================================================= | 81% | |============================================================= | 88% | |================================================================== | 94% | |======================================================================| 100%
##
## | | | 0% | |====== | 9% | |============= | 18% | |=================== | 27% | |========================= | 36% | |================================ | 45% | |====================================== | 55% | |============================================= | 64% | |=================================================== | 73% | |========================================================= | 82% | |================================================================ | 91% | |======================================================================| 100%
##
## | | | 0% | |======= | 10% | |============== | 20% | |===================== | 30% | |============================ | 40% | |=================================== | 50% | |========================================== | 60% | |================================================= | 70% | |======================================================== | 80% | |=============================================================== | 90% | |======================================================================| 100%
##
## | | | 0% | |==== | 6% | |======== | 11% | |============ | 17% | |================ | 22% | |=================== | 28% | |======================= | 33% | |=========================== | 39% | |=============================== | 44% | |=================================== | 50% | |======================================= | 56% | |=========================================== | 61% | |=============================================== | 67% | |=================================================== | 72% | |====================================================== | 78% | |========================================================== | 83% | |============================================================== | 89% | |================================================================== | 94% | |======================================================================| 100%
##
## | | | 0% | |==== | 6% | |======== | 12% | |============ | 18% | |================ | 24% | |===================== | 29% | |========================= | 35% | |============================= | 41% | |================================= | 47% | |===================================== | 53% | |========================================= | 59% | |============================================= | 65% | |================================================= | 71% | |====================================================== | 76% | |========================================================== | 82% | |============================================================== | 88% | |================================================================== | 94% | |======================================================================| 100%
stopifnot(nrow(regional) > 0, ncol(identity) == ncol(real_data))
plotRegionalPathways(regional, database = database)The ranks interface uses the complete measured feature ranking, with no FDR or foreground prefilter. It retains every used rank and the complete eligible pathway family. Competitive feature-set P values do not establish reproducibility across specimens. Joint gene/metabolite ranks can be RMS-scaled per modality, but pathways with many measured genes can still be dominated by transcriptomic coverage.
For metabolomics,
createPathwayAssay(metabolite_ambiguity="exclude") excludes
mass features with multiple candidate compound identities. Original
candidates, exclusions, aggregation weights and measured members remain
inspectable. The workflow uses this policy by default; the public native
interface retains the historical expand option. Sparse
matrices stay sparse during identity aggregation. The network viewer can
consume this identity assay directly, preventing re-expansion of
excluded mass candidates. GESECA, scores and networks therefore use the
same identity definition as regional enrichment.
The pathway dot plot uses adjusted P values for
significance outlines and 1 - Jaccard similarity for
pathway ordering. It handles a single pathway. Mouse genes are not
silently uppercased into a human HGNC index; the registered mouse
recipes currently show compound pathways until an explicit compatible
gene identity or orthology reference is supplied.
prepare <- system.file("workflows", "prepare_mouse_brain.R", package = "SpaMTP")
run <- system.file("workflows", "run_mouse_brain.R", package = "SpaMTP")
source(prepare)
source(run)
input_directory <- tempfile("mouse-brain-inputs-")Preparation reads only the pinned native SpaMTPData 1.1.0 resources.
With nativeDir = NULL, the public reader resolves verified
local files, its cache or the published download. Supplying a directory
selects offline mode by default; offline = TRUE can also
require a previously populated cache. It does not load Seurat or
deserialize historical Seurat objects. H&E is optional: the
published native resources contain expression and coordinates but omit
optical rasters. Independent image files can be attached with
addSpatialImage(); their checksums, explicit scale factors
and source provenance are retained.
For FMP10/Visium pixel-overlap mapping, supply a measured Visium spot
radius in the original image coordinate system. A nearest-neighbour
distance is not a spot diameter. Without a radius, preparation still
produces usable DHB inputs, but the FMP10 runner stops with an explicit
geometry requirement. The optional JSON configuration accepts
source, target_radius and images.
Image paths are resolved relative to the R process working directory,
not the JSON file.
For this exact registered pair, the small bundled scale-factor JSON
retains the values from the original Space Ranger
outs/spatial/scalefactors_json.json for V11L12-109_B1, from
Vicari et al.. Its
original file MD5 is 412630d2d6be8c828bcf13116c64c315. All
3,120 Visium barcodes and both coordinates match the original
tissue-position table exactly. The native convention is
x = pxl_row_in_fullres and
y = pxl_col_in_fullres; swapping these axes does not change
the isotropic radius. No H&E raster is attached here. Do not reuse
this radius for another sample or attach an image without checking axis
orientation and scale.
scales <- jsonlite::read_json(system.file("extdata",
"mouse_brain_scalefactors.json", package = "SpaMTP"))
config <- list(
source = paste("V11L12-109_B1 Space Ranger scalefactors_json.json;",
"https://doi.org/10.17632/w7nw4km7xd.1"),
target_radius = scales$spot_diameter_fullres / 2
)
config_file <- tempfile(fileext = ".json")
jsonlite::write_json(config, config_file, auto_unbox = TRUE,
pretty = TRUE, digits = NA)
pairing <- prepareMouseBrain(outputDir = input_directory,
spatialConfig = config_file)
stopifnot(pairing$target_radius == 188.471)
pairing[c("coordinate_units", "pixel_width", "target_radius")]
## $coordinate_units
## [1] "original image pixels"
##
## $pixel_width
## [1] 577.536
##
## $target_radius
## [1] 188.471The following calls execute both full analyses and render their reports. Output directories are new temporary paths, so rebuilding never overwrites a previous analysis. To retain reports across R sessions, choose new permanent paths.
mouse_outputs <- setNames(lapply(c("dhb", "fmp10"), function(case) {
output <- tempfile(paste0("mouse-brain-", case, "-"))
result <- runMouseBrain(input_directory, outputDir = output, case = case)
stopifnot(file.exists(result$report),
file.exists(file.path(output, "analysis.rds")))
list(directory = output, report = result$report,
metrics = result$structure$metrics)
}), c("dhb", "fmp10"))
## | | | 0% | |======================================================================| 100%
##
## | | | 0% | |======================================================================| 100%
##
## | | | 0% | |======================================================================| 100%
## Pathway network written to /tmp/RtmpMpoxsC/mouse-brain-dhb-26a743cce8ec/.spamtp-report-26a7322860a6/widgets/network_1/RegionLoupe_2026_09_25_08_17_45.html
## representation k approx_silhouette reference_ARI conditional_stability
## 1 main / PCA 4 0.12882606 -0.0019061865 0.4933855
## 2 main / PCA 6 0.11246543 0.0016213811 0.5552388
## 3 main / PCA 8 0.10666839 0.0007071816 0.4800462
## 4 main / PCA 10 0.10732307 0.0021782963 0.5491521
## 5 main / Graph PCA 4 0.14801815 0.0303762806 0.8123963
## 6 main / Graph PCA 6 0.16247278 0.0130904818 0.7442735
## 7 main / Graph PCA 8 0.15205488 0.0178266971 0.7655359
## 8 main / Graph PCA 10 0.14973794 0.0255500627 0.5781605
## 9 SPT / PCA 4 0.09408991 0.0932814885 0.7829793
## 10 SPT / PCA 6 0.07543536 0.0751102557 0.5239660
## 11 SPT / PCA 8 0.07588000 0.0398389534 0.4609613
## 12 SPT / PCA 10 0.06846807 0.0434329803 0.5365267
## 13 SPT / Graph PCA 4 0.14817514 0.1225235932 0.6248041
## 14 SPT / Graph PCA 6 0.14385890 0.0983346921 0.8760259
## 15 SPT / Graph PCA 8 0.17218604 0.0729354091 0.7063765
## 16 SPT / Graph PCA 10 0.17966847 0.0507772070 0.7685153
## 17 Joint / PCA 4 0.04417659 0.0718672069 0.6119008
## 18 Joint / PCA 6 0.04806496 0.0750478834 0.7445387
## 19 Joint / PCA 8 0.05012798 0.0435112477 0.5889424
## 20 Joint / PCA 10 0.04939911 0.0509717975 0.4905266
## 21 Joint / Graph PCA 4 0.07708606 0.0727363485 0.6058742
## 22 Joint / Graph PCA 6 0.09488760 0.0599800503 0.6494328
## 23 Joint / Graph PCA 8 0.11766077 0.0442641917 0.6856184
## 24 Joint / Graph PCA 10 0.13452642 0.0278014914 0.7211090
## stability_omissions spatial_neighbor_agreement smallest_cluster
## 1 6 0.3950564 169
## 2 6 0.2970512 82
## 3 6 0.2606245 80
## 4 6 0.2649610 42
## 5 6 0.8499566 87
## 6 6 0.8104944 9
## 7 6 0.7424111 8
## 8 6 0.6912402 8
## 9 6 0.4930616 70
## 10 6 0.4067650 26
## 11 6 0.3581960 25
## 12 6 0.3265395 20
## 13 6 0.8707719 30
## 14 6 0.8456201 21
## 15 6 0.8677363 21
## 16 6 0.8703382 19
## 17 6 0.7714657 164
## 18 6 0.7567216 1
## 19 6 0.6270598 1
## 20 6 0.5494363 1
## 21 6 0.9518647 151
## 22 6 0.9332177 25
## 23 6 0.9189072 13
## 24 6 0.9080659 13
## Report: /tmp/RtmpMpoxsC/mouse-brain-dhb-26a743cce8ec/report/report.html
## Warning: Quick-TRANSfer stage steps exceeded maximum (= 140950)
## representation k approx_silhouette reference_ARI conditional_stability
## 1 RNA / PCA 6 0.28578767 0.49733693 0.8663156
## 2 RNA / PCA 8 0.23459824 0.43099473 0.8512984
## 3 RNA / PCA 10 0.20799492 0.36000361 0.8392286
## 4 RNA / PCA 12 0.19864245 0.31379846 0.8927334
## 5 RNA / Graph PCA 6 0.32119478 0.52866773 0.8665574
## 6 RNA / Graph PCA 8 0.25842436 0.41961637 0.7952983
## 7 RNA / Graph PCA 10 0.25750551 0.37940085 0.8241918
## 8 RNA / Graph PCA 12 0.24895124 0.34236789 0.7054668
## 9 MS / PCA 6 0.15565324 0.07152823 0.6269252
## 10 MS / PCA 8 0.15628860 0.09798186 0.6465372
## 11 MS / PCA 10 0.13685486 0.07630411 0.5738940
## 12 MS / PCA 12 0.12277979 0.07147229 0.6566675
## 13 MS / Graph PCA 6 0.15088841 0.16740290 0.7156160
## 14 MS / Graph PCA 8 0.16556996 0.22082716 0.7851669
## 15 MS / Graph PCA 10 0.16791963 0.19647568 0.6697844
## 16 MS / Graph PCA 12 0.15061243 0.16514566 0.5513087
## 17 Joint / PCA 6 0.05494144 0.50487131 0.6885133
## 18 Joint / PCA 8 0.06434286 0.42968421 0.7725595
## 19 Joint / PCA 10 0.07456193 0.42941402 0.7390452
## 20 Joint / PCA 12 0.07811564 0.37972722 0.7175251
## 21 Joint / Graph PCA 6 0.09849265 0.47526192 0.7485592
## 22 Joint / Graph PCA 8 0.12329198 0.31959472 0.7278905
## 23 Joint / Graph PCA 10 0.13799716 0.33600840 0.7786624
## 24 Joint / Graph PCA 12 0.15883638 0.33327462 0.8200838
## stability_omissions spatial_neighbor_agreement smallest_cluster
## 1 6 0.7190505 84
## 2 6 0.6152161 76
## 3 6 0.5650639 75
## 4 6 0.5263542 75
## 5 6 0.8738892 123
## 6 6 0.8314060 95
## 7 6 0.8031649 81
## 8 6 0.7895313 77
## 9 6 0.3942788 37
## 10 6 0.3808886 8
## 11 6 0.3454656 3
## 12 6 0.3026172 1
## 13 6 0.7303713 210
## 14 6 0.7123554 93
## 15 6 0.6759586 12
## 16 6 0.6510043 12
## 17 6 0.8305539 71
## 18 6 0.7810103 71
## 19 6 0.7822276 3
## 20 6 0.7349970 3
## 21 6 0.9102861 260
## 22 6 0.9097991 199
## 23 6 0.8937310 147
## 24 6 0.8797322 90
## Report: /tmp/RtmpMpoxsC/mouse-brain-fmp10-26a73ae039ad/report/report.html
mouse_outputs$dhb$metrics
## representation k approx_silhouette reference_ARI conditional_stability
## 1 main / PCA 4 0.12882606 -0.0019061865 0.4933855
## 2 main / PCA 6 0.11246543 0.0016213811 0.5552388
## 3 main / PCA 8 0.10666839 0.0007071816 0.4800462
## 4 main / PCA 10 0.10732307 0.0021782963 0.5491521
## 5 main / Graph PCA 4 0.14801815 0.0303762806 0.8123963
## 6 main / Graph PCA 6 0.16247278 0.0130904818 0.7442735
## 7 main / Graph PCA 8 0.15205488 0.0178266971 0.7655359
## 8 main / Graph PCA 10 0.14973794 0.0255500627 0.5781605
## 9 SPT / PCA 4 0.09408991 0.0932814885 0.7829793
## 10 SPT / PCA 6 0.07543536 0.0751102557 0.5239660
## 11 SPT / PCA 8 0.07588000 0.0398389534 0.4609613
## 12 SPT / PCA 10 0.06846807 0.0434329803 0.5365267
## 13 SPT / Graph PCA 4 0.14817514 0.1225235932 0.6248041
## 14 SPT / Graph PCA 6 0.14385890 0.0983346921 0.8760259
## 15 SPT / Graph PCA 8 0.17218604 0.0729354091 0.7063765
## 16 SPT / Graph PCA 10 0.17966847 0.0507772070 0.7685153
## 17 Joint / PCA 4 0.04417659 0.0718672069 0.6119008
## 18 Joint / PCA 6 0.04806496 0.0750478834 0.7445387
## 19 Joint / PCA 8 0.05012798 0.0435112477 0.5889424
## 20 Joint / PCA 10 0.04939911 0.0509717975 0.4905266
## 21 Joint / Graph PCA 4 0.07708606 0.0727363485 0.6058742
## 22 Joint / Graph PCA 6 0.09488760 0.0599800503 0.6494328
## 23 Joint / Graph PCA 8 0.11766077 0.0442641917 0.6856184
## 24 Joint / Graph PCA 10 0.13452642 0.0278014914 0.7211090
## stability_omissions spatial_neighbor_agreement smallest_cluster
## 1 6 0.3950564 169
## 2 6 0.2970512 82
## 3 6 0.2606245 80
## 4 6 0.2649610 42
## 5 6 0.8499566 87
## 6 6 0.8104944 9
## 7 6 0.7424111 8
## 8 6 0.6912402 8
## 9 6 0.4930616 70
## 10 6 0.4067650 26
## 11 6 0.3581960 25
## 12 6 0.3265395 20
## 13 6 0.8707719 30
## 14 6 0.8456201 21
## 15 6 0.8677363 21
## 16 6 0.8703382 19
## 17 6 0.7714657 164
## 18 6 0.7567216 1
## 19 6 0.6270598 1
## 20 6 0.5494363 1
## 21 6 0.9518647 151
## 22 6 0.9332177 25
## 23 6 0.9189072 13
## 24 6 0.9080659 13
mouse_outputs$fmp10$metrics
## representation k approx_silhouette reference_ARI conditional_stability
## 1 RNA / PCA 6 0.28578767 0.49733693 0.8663156
## 2 RNA / PCA 8 0.23459824 0.43099473 0.8512984
## 3 RNA / PCA 10 0.20799492 0.36000361 0.8392286
## 4 RNA / PCA 12 0.19864245 0.31379846 0.8927334
## 5 RNA / Graph PCA 6 0.32119478 0.52866773 0.8665574
## 6 RNA / Graph PCA 8 0.25842436 0.41961637 0.7952983
## 7 RNA / Graph PCA 10 0.25750551 0.37940085 0.8241918
## 8 RNA / Graph PCA 12 0.24895124 0.34236789 0.7054668
## 9 MS / PCA 6 0.15565324 0.07152823 0.6269252
## 10 MS / PCA 8 0.15628860 0.09798186 0.6465372
## 11 MS / PCA 10 0.13685486 0.07630411 0.5738940
## 12 MS / PCA 12 0.12277979 0.07147229 0.6566675
## 13 MS / Graph PCA 6 0.15088841 0.16740290 0.7156160
## 14 MS / Graph PCA 8 0.16556996 0.22082716 0.7851669
## 15 MS / Graph PCA 10 0.16791963 0.19647568 0.6697844
## 16 MS / Graph PCA 12 0.15061243 0.16514566 0.5513087
## 17 Joint / PCA 6 0.05494144 0.50487131 0.6885133
## 18 Joint / PCA 8 0.06434286 0.42968421 0.7725595
## 19 Joint / PCA 10 0.07456193 0.42941402 0.7390452
## 20 Joint / PCA 12 0.07811564 0.37972722 0.7175251
## 21 Joint / Graph PCA 6 0.09849265 0.47526192 0.7485592
## 22 Joint / Graph PCA 8 0.12329198 0.31959472 0.7278905
## 23 Joint / Graph PCA 10 0.13799716 0.33600840 0.7786624
## 24 Joint / Graph PCA 12 0.15883638 0.33327462 0.8200838
## stability_omissions spatial_neighbor_agreement smallest_cluster
## 1 6 0.7190505 84
## 2 6 0.6152161 76
## 3 6 0.5650639 75
## 4 6 0.5263542 75
## 5 6 0.8738892 123
## 6 6 0.8314060 95
## 7 6 0.8031649 81
## 8 6 0.7895313 77
## 9 6 0.3942788 37
## 10 6 0.3808886 8
## 11 6 0.3454656 3
## 12 6 0.3026172 1
## 13 6 0.7303713 210
## 14 6 0.7123554 93
## 15 6 0.6759586 12
## 16 6 0.6510043 12
## 17 6 0.8305539 71
## 18 6 0.7810103 71
## 19 6 0.7822276 3
## 20 6 0.7349970 3
## 21 6 0.9102861 260
## 22 6 0.9097991 199
## 23 6 0.8937310 147
## 24 6 0.8797322 90These panels are taken from the reports just generated, not from saved reference figures. They compare spatial structure for both full real datasets. Spatial smoothing alone is not evidence of improved biological recovery.
spatial_figures <- vapply(mouse_outputs, function(output) {
directory <- dirname(output$report)
figures <- read.csv(file.path(directory, "figure_index.csv"))
selected <- figures$png[figures$name == "structure_spatial"]
stopifnot(length(selected) == 1L)
file.path(directory, selected)
}, character(1))
knitr::include_graphics(unname(spatial_figures))DHB / Visium: all retained observations.
FMP10 / Visium: all retained, overlap-mapped observations.
Pairing is documented for these registered source specimens; arbitrary datasets are not paired merely because both are mouse brains. DHB already contains paired modalities. Both runners re-annotate with the pinned chemical database and an explicit positive-mode DHB or FMP-10 index, rather than using the archived mass-only annotation cache. Ambiguous compound assignments remain excluded; mouse RNA is retained without human-HGNC or implicit orthology conversion.
The installed network-only demo is another native entry point:
demo <- system.file("examples", "pathway_network_mouse_brain_demo.R",
package = "SpaMTP")
source(demo)
network_directory <- tempfile("mouse-brain-networks-")
networks <- runMouseBrainNetworkDemo(outputDir = network_directory,
ident = "RegionLoupe")
## Building sorted adduct candidate index ...
## Searching candidate index at 5 ppm ...
## Adding annotations to rowData ....
## | | | 0% | |======================================================================| 100%
##
## | | | 0% | |================== | 25% | |=================================== | 50% | |==================================================== | 75% | |======================================================================| 100%
## Pathway network written to /tmp/RtmpMpoxsC/mouse-brain-networks-26a76036f777/leading_edge/RegionLoupe_2026_09_25_08_34_25.html
## Pathway network written to /tmp/RtmpMpoxsC/mouse-brain-networks-26a76036f777/annotated/RegionLoupe_2026_09_25_08_34_36.html
stopifnot(file.exists(file.path(network_directory, "network_analysis.rds")))
networks$status
## [1] "completed"
length(unlist(networks$networks))
## [1] 2It uses findAllDEMs(method="markers") for descriptive
regional effects, complete compound rankings for competitive pathway
enrichment, and pathwayNetworkPlots() for separate
leading-edge and annotation-coverage views. It does not assign
biological-replicate significance to individual pixels or map mouse gene
symbols to human genes. Outputs include the native analysis RDS,
annotation/mapping audits and, when pathways are eligible, offline HTML
networks. No eligible pathways is reported explicitly rather than
relaxing the filters.
Reports follow the analytical sequence above. They include a linked region/DE explorer with feature search, directional AUC/effect/stability/FDR filters, spatial zoom and pan, coordinated feature profiles and complete CSV exports. Native 3D and network views are available when their input requirements are satisfied. Figures are embedded as PNGs and also exported as PDFs. Open the HTML in a browser or an IDE HTML preview that permits JavaScript; Markdown previews may disable interaction. The output directory also contains the complete workflow RDS, settings, inputs used by each stage, source and database provenance, and file checksums.
For methods, see the Bioconductor marker-scoring documentation and the GraphPCA paper.
sessionInfo()
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 26.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.32.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=en_US.UTF-8
## [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: Etc/UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] SpaMTP_0.99.10 BiocStyle_2.41.0
##
## loaded via a namespace (and not attached):
## [1] splines_4.6.1 later_1.4.8
## [3] filelock_1.0.3 tibble_3.3.1
## [5] lifecycle_1.0.5 httr2_1.3.0
## [7] sf_1.1-3 edgeR_4.99.6
## [9] globals_0.19.1 lattice_0.23-1
## [11] crosstalk_1.2.2 magrittr_2.0.5
## [13] SpaMTPdb_0.99.4 limma_3.99.0
## [15] plotly_4.12.1 sass_0.4.10
## [17] rmarkdown_2.32 jquerylib_0.1.4
## [19] yaml_2.3.12 metapod_1.21.0
## [21] httpuv_1.6.17 otel_0.2.0
## [23] cowplot_1.2.0 DBI_1.3.0
## [25] buildtools_1.0.0 RColorBrewer_1.1-3
## [27] abind_1.4-8 GenomicRanges_1.65.4
## [29] purrr_1.2.2 BiocGenerics_0.59.12
## [31] rappdirs_0.3.4 SpaMTPData_0.99.5
## [33] IRanges_2.47.5 S4Vectors_0.51.10
## [35] ggrepel_0.9.8 irlba_2.3.7
## [37] listenv_1.0.0 maketools_1.3.2
## [39] pheatmap_1.0.13 units_1.0-1
## [41] RSpectra_0.16-2 matter_2.15.0
## [43] dqrng_0.4.1 parallelly_1.48.0
## [45] codetools_0.2-20 DelayedArray_0.39.7
## [47] scuttle_1.23.2 tidyselect_1.2.1
## [49] farver_2.1.2 ScaledMatrix_1.21.0
## [51] viridis_0.6.5 matrixStats_1.5.0
## [53] stats4_4.6.1 BiocFileCache_3.3.0
## [55] Seqinfo_1.3.2 jsonlite_2.0.0
## [57] CardinalIO_1.11.0 BiocNeighbors_2.7.3
## [59] e1071_1.7-17 scater_1.41.2
## [61] tools_4.6.1 Rcpp_1.1.2
## [63] glue_1.8.1 gridExtra_2.3.1
## [65] SparseArray_1.13.3 BiocBaseUtils_1.15.1
## [67] xfun_0.61 MatrixGenerics_1.25.0
## [69] dplyr_1.2.1 withr_3.0.3
## [71] BiocManager_1.30.27 fastmap_1.2.0
## [73] bluster_1.23.1 digest_0.6.39
## [75] rsvd_1.0.5 R6_2.6.1
## [77] mime_0.13 RSQLite_3.53.3
## [79] tidyr_1.3.2 generics_0.1.4
## [81] data.table_1.18.6.1 FNN_1.1.4.1
## [83] class_7.3-24 httr_1.4.9
## [85] htmlwidgets_1.6.4 S4Arrays_1.13.1
## [87] ontologyIndex_2.12 uwot_0.2.5
## [89] pkgconfig_2.0.3 gtable_0.3.6
## [91] blob_1.3.0 S7_0.2.2
## [93] SingleCellExperiment_1.35.2 XVector_0.53.0
## [95] sys_3.4.3 htmltools_0.5.9
## [97] fgsea_1.39.2 ProtGenerics_1.45.0
## [99] scales_1.4.0 Biobase_2.73.2
## [101] png_0.1-9 SpatialExperiment_1.23.0
## [103] scran_1.41.1 knitr_1.52
## [105] rjson_0.2.23 nlme_3.1-171
## [107] curl_8.0.0 proxy_0.4-29
## [109] cachem_1.1.0 stringr_1.6.0
## [111] Cardinal_3.15.0 BiocVersion_3.24.0
## [113] KernSmooth_2.23-27 parallel_4.6.1
## [115] vipor_0.4.7 AnnotationDbi_1.75.2
## [117] pillar_1.11.1 grid_4.6.1
## [119] vctrs_0.7.3 promises_1.5.0
## [121] BiocSingular_1.29.1 dbplyr_2.6.0
## [123] beachmat_2.29.3 xtable_1.8-8
## [125] cluster_2.1.8.3 beeswarm_0.4.0
## [127] evaluate_1.0.5 magick_2.9.1
## [129] cli_3.6.6 locfit_1.5-9.12
## [131] compiler_4.6.1 rlang_1.3.0
## [133] crayon_1.5.3 future.apply_1.20.2
## [135] labeling_0.4.3 mclust_6.1.3
## [137] classInt_0.4-11 naturalsort_0.1.3
## [139] ggbeeswarm_0.7.3 stringi_1.8.9
## [141] viridisLite_0.4.3 BiocParallel_1.47.0
## [143] Biostrings_2.81.9 Matrix_1.7-6
## [145] ExperimentHub_3.3.2 bit64_4.8.6
## [147] future_1.76.0 ggplot2_4.0.3
## [149] KEGGREST_1.53.6 statmod_1.5.2
## [151] shiny_1.14.0 SummarizedExperiment_1.43.0
## [153] AnnotationHub_4.3.2 igraph_2.3.3
## [155] memoise_2.0.1 bslib_0.12.0
## [157] fastmatch_1.1-8 bit_4.6.0