This vignette introduces the SpaceTrooper
package for spatial data analysis
from platforms like Xenium, Merfish, and CosMx. We cover data
loading, quality control, and result visualization.
To install SpaceTrooper
, use the following commands:
# Install BiocManager if not already installed, then install SpaceTrooper
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("drighelli/SpaceTrooper")
In this section, we load data from various platforms using the package’s
functions. The goal is to provide a uniform SpatialExperiment
object across
all technologies, allowing for consistent QC analysis.
The functions in SpaceTrooper
compute missing metrics as needed and allow
for the inclusion of polygons with the keep_polygons
argument. This stores
polygons in the colData
of the SpatialExperiment
.
We suggest to use the keep_polygons
argument for technologies like
Xenium and Merfish/Merscope because we already load the polygons to
compute missing metrics in these cases.
Note that when loading data with readXeniumSPE
in HDF5 format, this creates a
DelayedArray
count assay in the SpatialExperiment
, which could lead to some
issues in downstream analysis, in case this data structure is not supported
by the used package.
# Load the SpaceTrooper library
library(SpaceTrooper)
# Load Xenium data into a Spatial Experiment object (SPE)
xeniumFolder <- system.file( "extdata", "Xenium_small", package="SpaceTrooper")
(xen <- readXeniumSPE(xeniumFolder, computeMissingMetrics=TRUE,
keepPolygons=TRUE))
## class: SpatialExperiment
## dim: 4 6
## metadata(2): polygons technology
## assays(1): counts
## rownames(4): ABCC11 ACTA2 ACTG2 ADAM9
## rowData names(3): ID Symbol Type
## colnames(6): 1 2 ... 5 6
## colData names(11): X cell_id ... AspectRatio polygons
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(2) : x_centroid y_centroid
## imgData names(1): sample_id
colData(xen)
## DataFrame with 6 rows and 11 columns
## X cell_id transcript_counts control_probe_counts
## <integer> <integer> <integer> <integer>
## 1 1 1 384 0
## 2 2 2 146 0
## 3 3 3 81 0
## 4 4 4 314 0
## 5 5 5 639 0
## 6 6 6 270 0
## control_codeword_counts total_counts cell_area nucleus_area sample_id
## <integer> <integer> <numeric> <numeric> <character>
## 1 0 385 305.211 70.71469 sample01
## 2 0 146 176.606 6.41219 sample01
## 3 0 81 263.938 32.78344 sample01
## 4 0 315 427.810 68.18594 sample01
## 5 0 640 424.604 102.95625 sample01
## 6 0 270 416.882 33.41562 sample01
## AspectRatio polygons
## <numeric> <sf>
## 1 0.800000 1:list(c(849.787475585..:FALSE:...
## 2 0.687499 2:list(c(817.0625, 816..:FALSE:...
## 3 0.699999 3:list(c(849.787475585..:FALSE:...
## 4 0.897439 4:list(c(823.224975585..:FALSE:...
## 5 1.448982 5:list(c(840.650024414..:FALSE:...
## 6 1.333327 6:list(c(847.237487792..:FALSE:...
# Load Merfish data into an SPE with parquet boundaries
merscopeFolder <- system.file("extdata", "Merfish_Tiny", package="SpaceTrooper")
(mer <- readMerfishSPE(merscopeFolder, boundariesType="parquet",
computeMissingMetrics=TRUE, keepPolygons=TRUE))
## class: SpatialExperiment
## dim: 10 50
## metadata(2): polygons technology
## assays(1): counts
## rownames(10): PDK4 CCL26 ... TBX21 FAP
## rowData names(0):
## colnames(50): 26985800002100002 26985800002100003 ... 26985800003100008
## 26985800003100010
## colData names(27): cell_id fov ... polygons sample_id
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(2) : center_x center_y
## imgData names(0):
colData(mer)
## DataFrame with 50 rows and 27 columns
## cell_id fov volume min_x min_y
## <integer64> <integer> <numeric> <numeric> <numeric>
## 26985800002100002 26985800002100002 188 67.4877 1456.56 149.926
## 26985800002100003 26985800002100003 188 572.6167 1285.17 150.447
## 26985800002100009 26985800002100009 188 180.6029 1439.18 150.461
## 26985800002100016 26985800002100016 188 236.3058 1369.52 162.237
## 26985800002100017 26985800002100017 188 211.9732 1447.71 161.462
## ... ... ... ... ... ...
## 26985800003100005 26985800003100005 264 816.136 1544.29 58.1212
## 26985800003100006 26985800003100006 264 1557.570 1559.25 60.7662
## 26985800003100007 26985800003100007 264 891.561 1545.13 64.4227
## 26985800003100008 26985800003100008 264 1094.290 1527.17 68.4953
## 26985800003100010 26985800003100010 264 1092.694 1518.86 77.0072
## max_x max_y anisotropy transcript_count
## <numeric> <numeric> <numeric> <integer>
## 26985800002100002 1459.78 152.855 1.30646 0
## 26985800002100003 1288.84 167.175 4.56560 0
## 26985800002100009 1444.56 154.525 1.32596 0
## 26985800002100016 1374.25 168.944 1.45674 0
## 26985800002100017 1453.91 165.686 1.60233 1
## ... ... ... ... ...
## 26985800003100005 1556.39 67.0141 1.56662 220
## 26985800003100006 1571.92 75.6834 1.19477 504
## 26985800003100007 1557.11 75.1396 1.61050 237
## 26985800003100008 1540.24 82.4848 1.33467 611
## 26985800003100010 1532.71 88.7656 1.28149 597
## perimeter_area_ratio solidity DAPI_raw DAPI_high_pass
## <numeric> <numeric> <integer> <numeric>
## 26985800002100002 1.460466 7.00000 10031450 1275615
## 26985800002100003 0.699506 6.74990 10566420 1569192
## 26985800002100009 0.897958 7.00000 17483674 1128739
## 26985800002100016 0.839058 6.54357 9699598 165876
## 26985800002100017 0.852500 6.84923 31223309 328891
## ... ... ... ... ...
## 26985800003100005 0.435879 6.81694 619728199 3074276
## 26985800003100006 0.303557 6.89371 995974204 5756449
## 26985800003100007 0.421047 6.87562 624145706 3240592
## 26985800003100008 0.398144 6.37886 781206643 4199120
## 26985800003100010 0.365497 6.90240 843343768 4555631
## Cellbound2_raw Cellbound2_high_pass PolyT_raw PolyT_high_pass
## <integer> <numeric> <integer> <numeric>
## 26985800002100002 7545395 683236 8272827 1053956
## 26985800002100003 17739873 1396788 19038054 2727259
## 26985800002100009 12073443 318845 17359008 1107675
## 26985800002100016 8454232 118069 18952192 272687
## 26985800002100017 18054960 204996 27813347 281936
## ... ... ... ... ...
## 26985800003100005 217119396 1612132 401433689 2243790
## 26985800003100006 476710032 5098785 711413405 4688473
## 26985800003100007 293781198 2945993 408437826 2077031
## 26985800003100008 298710416 2714216 520983160 2927650
## 26985800003100010 287395414 2720645 543653205 3137387
## Cellbound3_raw Cellbound3_high_pass Anti.Ms.CD45RA_raw
## <integer> <numeric> <integer64>
## 26985800002100002 1978031 190336.1 3646677
## 26985800002100003 7399745 618972.0 23340256
## 26985800002100009 3404019 121075.1 9552347
## 26985800002100016 2824879 64292.2 11682873
## 26985800002100017 4834605 98919.5 12042800
## ... ... ... ...
## 26985800003100005 61317799 893250 57497557
## 26985800003100006 104833992 1750080 104260941
## 26985800003100007 56278321 714652 60108349
## 26985800003100008 62275042 1006426 74054883
## 26985800003100010 59351838 1007649 71828467
## Anti.Ms.CD45RA_high_pass Cellbound1_raw Cellbound1_high_pass
## <numeric> <integer64> <numeric>
## 26985800002100002 306526.2 11993880 1068209
## 26985800002100003 1932074.2 31455099 2395973
## 26985800002100009 250153.3 18873810 466134
## 26985800002100016 105143.5 13044814 147990
## 26985800002100017 97753.7 28441170 245080
## ... ... ... ...
## 26985800003100005 435947 373898626 2618444
## 26985800003100006 921107 690727218 6323352
## 26985800003100007 512397 478131337 3649511
## 26985800003100008 681909 438161375 4097784
## 26985800003100010 578224 339102882 3006323
## um_area AspectRatio
## <numeric> <numeric>
## 26985800002100002 6.4274 0.908763
## 26985800002100003 54.5349 4.563174
## 26985800002100009 17.2003 0.755732
## 26985800002100016 22.5053 1.418292
## 26985800002100017 20.1879 0.681541
## ... ... ...
## 26985800003100005 77.7273 0.735266
## 26985800003100006 148.3400 1.177586
## 26985800003100007 84.9105 0.893979
## 26985800003100008 104.2181 1.070487
## 26985800003100010 104.0661 0.848952
## polygons
## <sf>
## 26985800002100002 26985800002100002:list(c(1457.03135009..:FALSE:...
## 26985800002100003 26985800002100003:list(c(1285.17346897..:FALSE:...
## 26985800002100009 26985800002100009:list(c(1439.17997851..:FALSE:...
## 26985800002100016 26985800002100016:list(c(1369.58905121..:FALSE:...
## 26985800002100017 26985800002100017:list(c(1448.74199550..:FALSE:...
## ... ...
## 26985800003100005 26985800003100005:list(c(1548.14720174..:FALSE:...
## 26985800003100006 26985800003100006:list(c(1559.24912423..:FALSE:...
## 26985800003100007 26985800003100007:list(c(1547.70509276..:FALSE:...
## 26985800003100008 26985800003100008:list(c(1532.80367814..:FALSE:...
## 26985800003100010 26985800003100010:list(c(1519.93351811..:FALSE:...
## sample_id
## <character>
## 26985800002100002 sample01
## 26985800002100003 sample01
## 26985800002100009 sample01
## 26985800002100016 sample01
## 26985800002100017 sample01
## ... ...
## 26985800003100005 sample01
## 26985800003100006 sample01
## 26985800003100007 sample01
## 26985800003100008 sample01
## 26985800003100010 sample01
Despite main differences across the technologies provided data, we can see that
all the technologies have the same mandatory cell_id
and AspectRatio
columns.
The package offers several functions for spatial data analysis, including quality control and visualization.
This tutorial focuses on CosMx data, which provides Fields of View (FoVs) with cell identifiers. Note that FoVs are unique to CosMx and are not available for other technologies like Xenium and Merfish/Merscope.
For CosMx data, you don’t need to keep_polygons
initially because the
metrics can be computed without them. Polygons can be loaded later if needed.
# Reload CosMx data with sample name and without polygons
cosmxFolder <- system.file(file.path("extdata", "CosMx_DBKero_Tiny"),
package="SpaceTrooper")
spe <- readCosmxSPE(cosmxFolder, sampleName="DBKero_CosMx")
## a custom function for the labels of this dataset
source(system.file(file.path("scripts", "labelsfunct.R"),
package="SpaceTrooper"))
spe <- addLabelsDBKero(spe)
spe
## class: SpatialExperiment
## dim: 1010 905
## metadata(4): fov_positions fov_dim polygons technology
## assays(1): counts
## rownames(1010): RAMP2 CD83 ... NegPrb09 NegPrb10
## rowData names(0):
## colnames(905): f16_c1 f16_c10 ... f16_c98 f16_c99
## colData names(22): fov cellID ... labels labels_colors
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(2) : CenterX_global_px CenterY_global_px
## imgData names(1): sample_id
The plotCellsFovs
function shows a map of the FoVs within an experiment.
This plot is specific to CosMx data and uses cell centroids.
# Plot the cells within their respective Field of Views (FOVs)
plotCellsFovs(spe)
Because the dataset is a subset of just one Field of View of the original experiment, we are able to see the identifier of the FoV in black and the centroids of the cells in purple.
When an experiment has multiple FoVs, you can see the map and the topological organization of the FoVs, together with their identifiers.
To focus on cell centroids, use the plotCentroidsSPE
function. It provides
a colour_by
argument, similar to scater
, to colour the centroids by the
values present in the indicated column.
Additionally, if you have a column with a color palette it automatically maps it
to the values passed in the colour_by
argument.
# Plot the centroids of the cells in the SPE
plotCentroids(spe, colourBy="labels")
# Plot the centroids of the cells in the SPE with personalized labels
plotCentroids(spe, colourBy="labels", palette="labels_colors")
This allow us to see the cell centroids coloured by their cell types giving us an idea of the cell population in the entire experiment.
Additionally, the palette
argument allows to use a user-defined palette
for the associated centroids. The palette
value must by a column in the
object colData
.
Notice that with this plot the FoV identifier is not shown.
The spatialPerCellQC
function, inspired by scater::addPerCellQC
, computes
additional metrics for each cell in the SpatialExperiment
. It also allows for
the detection of negative control probes, which is crucial for QC.
By default, it automatically removes 0 counts cells, but this can be handled
with the rmZeros
argument.
# Perform per-cell quality control checks
spe <- spatialPerCellQC(spe, rmZeros=TRUE,
negProbList=c("NegPrb", "Negative", "SystemControl"))
names(colData(spe))
## [1] "fov" "cellID"
## [3] "Area" "AspectRatio"
## [5] "CenterX_local_px" "CenterY_local_px"
## [7] "Width" "Height"
## [9] "Mean.PanCK" "Max.PanCK"
## [11] "Mean.CD68" "Max.CD68"
## [13] "Mean.MembraneStain_B2M" "Max.MembraneStain_B2M"
## [15] "Mean.CD45" "Max.CD45"
## [17] "Mean.DAPI" "Max.DAPI"
## [19] "sample_id" "cell_id"
## [21] "labels" "labels_colors"
## [23] "sum" "detected"
## [25] "subsets_NegPrb_sum" "subsets_NegPrb_detected"
## [27] "subsets_NegPrb_percent" "total"
## [29] "control_sum" "control_detected"
## [31] "target_sum" "target_detected"
## [33] "CenterX_global_px" "CenterY_global_px"
## [35] "ctrl_total_ratio" "CenterX_global_um"
## [37] "CenterY_global_um" "Area_um"
## [39] "dist_border_x" "dist_border_y"
## [41] "dist_border" "log2AspectRatio"
## [43] "CountArea" "log2CountArea"
You can investigate individual metrics by viewing their histograms. For
outliers, use the use_fences
argument to display the fences computed by
computeSpatialOutlier
(see next chunk).
# Plot a histogram of counts (sum)
plotMetricHist(spe, metric="sum")
# Plot a histogram of cell areas (Area_um)
plotMetricHist(spe, metric="Area_um")
# Plot a histogram of proportion of counts respect to the cell area in micron
plotMetricHist(spe, metric="log2CountArea")
These plots show, respectively, the distributions of the total counts (sum
),
of the Area in micron (Area_um
) and the relationship between the counts and
the Area of each cell (log2CountArea
).
Spatial outlier detection is another critical step in QC. While the flag score addresses some metrics, other outlier detection methods may be needed.
The computeSpatialOutlier
function allows the computation of the medcouple
statistics on a specified metric (compute_by
argument).
The medcouple is specifically designed for symmetric distributions, indeed the
function stamps a warning message when this requisite is not satisfied.
It can also use scuttle::isOutlier
for asymmetric distributions.
The method
argument supports mc
, scuttle
, or both
.
This outlier detection approach can be used to decide if and which cells can be discarded on a singular metric.
# Identify spatial outliers based on cell area (Area_um)
spe <- computeSpatialOutlier(spe, computeBy="Area_um", method="both")
# Identify spatial outliers based on mean DAPI intensity
spe <- computeSpatialOutlier(spe, computeBy="Mean.DAPI", method="both")
names(colData(spe))
## [1] "fov" "cellID"
## [3] "Area" "AspectRatio"
## [5] "CenterX_local_px" "CenterY_local_px"
## [7] "Width" "Height"
## [9] "Mean.PanCK" "Max.PanCK"
## [11] "Mean.CD68" "Max.CD68"
## [13] "Mean.MembraneStain_B2M" "Max.MembraneStain_B2M"
## [15] "Mean.CD45" "Max.CD45"
## [17] "Mean.DAPI" "Max.DAPI"
## [19] "sample_id" "cell_id"
## [21] "labels" "labels_colors"
## [23] "sum" "detected"
## [25] "subsets_NegPrb_sum" "subsets_NegPrb_detected"
## [27] "subsets_NegPrb_percent" "total"
## [29] "control_sum" "control_detected"
## [31] "target_sum" "target_detected"
## [33] "CenterX_global_px" "CenterY_global_px"
## [35] "ctrl_total_ratio" "CenterX_global_um"
## [37] "CenterY_global_um" "Area_um"
## [39] "dist_border_x" "dist_border_y"
## [41] "dist_border" "log2AspectRatio"
## [43] "CountArea" "log2CountArea"
## [45] "Area_um_outlier_mc" "Area_um_outlier_sc"
## [47] "Mean.DAPI_outlier_mc" "Mean.DAPI_outlier_sc"
If we computed outliers with the computeSpatialOutlier
function, we can also
visualize which fences have been used to create the filter on the cells.
# Plot a histogram with fences to identify outliers using the medcouple
plotMetricHist(spe, metric="Area_um", useFences="Area_um_outlier_mc")
# Plot a histogram with fences to identify outliers using scuttle
plotMetricHist(spe, metric="Area_um", useFences="Area_um_outlier_sc")
# Plot a histogram with fences to identify outliers using the medcouple
plotMetricHist(spe, metric="Mean.DAPI", useFences="Mean.DAPI_outlier_mc")
# Plot a histogram with fences to identify outliers using scuttle
plotMetricHist(spe, metric="Mean.DAPI", useFences="Mean.DAPI_outlier_sc")
We visualize the fences computed with medcouple and scuttle outlier detection approaches, to directly inspect differences and the amount of detected outlier each method detected.
If we want, we can already use these fences to remove the computed outliers.
Next, we use computeQScore
to calculate a flag score based on previously
computed metrics.
The flag score combines transcript counts related to
cell area, the aspect ratio of each cell, and its
distance from the FoV border (only for CosMx, this last one is not used
otherwise).
See the help(computeQScore)
details section for additional details.
# Calculate quality scores for each cell
spe <- computeQScore(spe)
names(colData(spe))
## [1] "fov" "cellID"
## [3] "Area" "AspectRatio"
## [5] "CenterX_local_px" "CenterY_local_px"
## [7] "Width" "Height"
## [9] "Mean.PanCK" "Max.PanCK"
## [11] "Mean.CD68" "Max.CD68"
## [13] "Mean.MembraneStain_B2M" "Max.MembraneStain_B2M"
## [15] "Mean.CD45" "Max.CD45"
## [17] "Mean.DAPI" "Max.DAPI"
## [19] "sample_id" "cell_id"
## [21] "labels" "labels_colors"
## [23] "sum" "detected"
## [25] "subsets_NegPrb_sum" "subsets_NegPrb_detected"
## [27] "subsets_NegPrb_percent" "total"
## [29] "control_sum" "control_detected"
## [31] "target_sum" "target_detected"
## [33] "CenterX_global_px" "CenterY_global_px"
## [35] "ctrl_total_ratio" "CenterX_global_um"
## [37] "CenterY_global_um" "Area_um"
## [39] "dist_border_x" "dist_border_y"
## [41] "dist_border" "log2AspectRatio"
## [43] "CountArea" "log2CountArea"
## [45] "Area_um_outlier_mc" "Area_um_outlier_sc"
## [47] "Mean.DAPI_outlier_mc" "Mean.DAPI_outlier_sc"
## [49] "quality_score" "training_status"
Logical filters can then be computed using computeQScoreFlags
, which requires
thresholds for various metrics. Currently, the function considers:
Flag Score (qs_threshold
): Cells with scores below this threshold
(default 0.5) are flagged for exclusion. This value can be used to indicate
the quantile for the filtering when setting the use_fs_quantiles
argument
to TRUE
.
Flag Score Quantiles (use_qs_quantiles
): Option to filter based on
quantiles (default FALSE
).
# Compute flags to identify cells for filtering
spe <- computeQScoreFlags(spe, qsThreshold=0.5)
names(colData(spe))
## [1] "fov" "cellID"
## [3] "Area" "AspectRatio"
## [5] "CenterX_local_px" "CenterY_local_px"
## [7] "Width" "Height"
## [9] "Mean.PanCK" "Max.PanCK"
## [11] "Mean.CD68" "Max.CD68"
## [13] "Mean.MembraneStain_B2M" "Max.MembraneStain_B2M"
## [15] "Mean.CD45" "Max.CD45"
## [17] "Mean.DAPI" "Max.DAPI"
## [19] "sample_id" "cell_id"
## [21] "labels" "labels_colors"
## [23] "sum" "detected"
## [25] "subsets_NegPrb_sum" "subsets_NegPrb_detected"
## [27] "subsets_NegPrb_percent" "total"
## [29] "control_sum" "control_detected"
## [31] "target_sum" "target_detected"
## [33] "CenterX_global_px" "CenterY_global_px"
## [35] "ctrl_total_ratio" "CenterX_global_um"
## [37] "CenterY_global_um" "Area_um"
## [39] "dist_border_x" "dist_border_y"
## [41] "dist_border" "log2AspectRatio"
## [43] "CountArea" "log2CountArea"
## [45] "Area_um_outlier_mc" "Area_um_outlier_sc"
## [47] "Mean.DAPI_outlier_mc" "Mean.DAPI_outlier_sc"
## [49] "quality_score" "training_status"
## [51] "low_qscore"
table(spe$low_qscore)
##
## FALSE TRUE
## 816 88
We detected 88 cells to be removed.
While for other metrics such as the total counts and the negative prob ratio,
the function computeThresholdFlags
considers:
Total Counts (total_threshold
): Minimum count threshold (default 0).
Negative Probe Ratio (ctrl_tot_ratio_threshold
): Minimum ratio of
negative probes to total counts (default 0.1).
spe <- computeThresholdFlags(spe, totalThreshold=0,
ctrlTotRatioThreshold=0.1)
table(spe$threshold_flags)
##
## FALSE
## 904
In this example, we don’t find any cell to be removed.
To better understand the quality score values we start to load the polygons, giving us a better overview of the cells characteristics.
We can load and add polygons to the SPE object using the following functions.
Each technology has its own readPolygons
function to standardize the
loaded sf
object and handle different file types.
# Read polygon data associated with cells in the SPE
# the polygon file path is stored in the spe metadata
pols <- readPolygonsCosmx(metadata(spe)$polygons)
# Add the polygon data to the SPE object
spe <- addPolygonsToSPE(spe, pols)
Once the polygons are stored in an sf
object within colData
, they can be
visualized using functions based on the ggplot2
library.
# Plot the polygons of the selected cells
plotPolygons(spe, bgColor="white")
Showing the cells on a white background for better visualization.
# Plot polygons colored by cell area
plotPolygons(spe, colourBy="log2AspectRatio")
plotPolygons(spe, colourBy="Area_um")
We can see in yellow
and darkviolet
that there are few cells with extreme
values of log2AspectRatio
and Area_um
in micron.
plotPolygons(spe, colourBy="quality_score")
plotPolygons(spe, colourBy="low_qscore")
We can see that the quality score is able to detect both these aspects and highlight the cells that are mostly isolated on the FoV border or showing a weird confomation.
We always recommend to be aware of the cell populations in the under-study context, before proceeding to remove the detected cells.
The plotZoomFovsMap
function allows you to visualize a map of the FoVs with
a zoom-in of selected FoVs, colored by the colour_by
argument.
plotZoomFovsMap(spe, fovs=16, colourBy="quality_score")
plotZoomFovsMap(spe, fovs=16, colourBy="low_qscore")
We see on the left side the map of all the FoVs (only the FoV 16 in this case), together with the poligons on the right, coloured by the quality score. Allowing us to have a better view of a specific tissue area in the whole experiment.
In this vignette, we explored the main functionalities of the SpaceTrooper
package for spatial data analysis.
Main steps shown are:
* data loading: Xenium, Merfish/Merscope, CosMx
* polygons loading: Xenium, Merfish/Merscope, CosMx
* quality control:
+ outlier detection: medcouple and scuttle MAD
+ flag score: a score combining transcript counts, cell area,
aspect ratio and distance from the FoV border
* visualization:
+ centroids: with ggplot2
+ polygons: sf + ggplot2
sessionInfo()
## R version 4.5.1 (2025-06-13)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.2 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.22-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0 LAPACK version 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] SpaceTrooper_0.99.3 SpatialExperiment_1.19.1
## [3] SingleCellExperiment_1.31.1 SummarizedExperiment_1.39.1
## [5] Biobase_2.69.0 GenomicRanges_1.61.1
## [7] Seqinfo_0.99.2 IRanges_2.43.0
## [9] S4Vectors_0.47.0 BiocGenerics_0.55.1
## [11] generics_0.1.4 MatrixGenerics_1.21.0
## [13] matrixStats_1.5.0 BiocStyle_2.37.1
##
## loaded via a namespace (and not attached):
## [1] splines_4.5.1 tibble_3.3.0
## [3] R.oo_1.27.1 leaflegend_1.2.1
## [5] XML_3.99-0.18 lifecycle_1.0.4
## [7] sf_1.0-21 rstatix_0.7.2
## [9] edgeR_4.7.3 lattice_0.22-7
## [11] crosstalk_1.2.1 backports_1.5.0
## [13] magrittr_2.0.3 limma_3.65.3
## [15] sass_0.4.10 rmarkdown_2.29
## [17] jquerylib_0.1.4 yaml_2.3.10
## [19] sp_2.2-0 cowplot_1.2.0
## [21] DBI_1.2.3 RColorBrewer_1.1-3
## [23] abind_1.4-8 purrr_1.1.0
## [25] R.utils_2.13.0 ggrepel_0.9.6
## [27] irlba_2.3.5.1 terra_1.8-60
## [29] units_0.8-7 dqrng_0.4.1
## [31] DelayedMatrixStats_1.31.0 codetools_0.2-20
## [33] DropletUtils_1.29.4 DelayedArray_0.35.2
## [35] scuttle_1.19.0 tidyselect_1.2.1
## [37] shape_1.4.6.1 raster_3.6-32
## [39] farver_2.1.2 ScaledMatrix_1.17.0
## [41] viridis_0.6.5 base64enc_0.1-3
## [43] jsonlite_2.0.0 cols4all_0.8
## [45] BiocNeighbors_2.3.1 e1071_1.7-16
## [47] Formula_1.2-5 survival_3.8-3
## [49] scater_1.37.0 iterators_1.0.14
## [51] foreach_1.5.2 tools_4.5.1
## [53] Rcpp_1.1.0 glue_1.8.0
## [55] gridExtra_2.3 SparseArray_1.9.1
## [57] xfun_0.52 leaflet.providers_2.0.0
## [59] dplyr_1.1.4 HDF5Array_1.37.0
## [61] withr_3.0.2 BiocManager_1.30.26
## [63] fastmap_1.2.0 rhdf5filters_1.21.0
## [65] digest_0.6.37 rsvd_1.0.5
## [67] R6_2.6.1 microbenchmark_1.5.0
## [69] colorspace_2.1-1 wk_0.9.4
## [71] spacesXYZ_1.6-0 dichromat_2.0-0.1
## [73] R.methodsS3_1.8.2 h5mread_1.1.1
## [75] tidyr_1.3.1 data.table_1.17.8
## [77] robustbase_0.99-4-1 class_7.3-23
## [79] htmlwidgets_1.6.4 S4Arrays_1.9.1
## [81] tmaptools_3.3 pkgconfig_2.0.3
## [83] gtable_0.3.6 XVector_0.49.0
## [85] htmltools_0.5.8.1 carData_3.0-5
## [87] bookdown_0.43 scales_1.4.0
## [89] png_0.1-8 knitr_1.50
## [91] rjson_0.2.23 proxy_0.4-27
## [93] cachem_1.1.0 rhdf5_2.53.3
## [95] KernSmooth_2.23-26 parallel_4.5.1
## [97] vipor_0.4.7 arrow_21.0.0
## [99] s2_1.1.9 leafsync_0.1.0
## [101] pillar_1.11.0 grid_4.5.1
## [103] logger_0.4.0 vctrs_0.6.5
## [105] ggpubr_0.6.1 car_3.1-3
## [107] BiocSingular_1.25.0 beachmat_2.25.4
## [109] sfheaders_0.4.4 beeswarm_0.4.0
## [111] evaluate_1.0.4 SpatialExperimentIO_1.1.0
## [113] tinytex_0.57 magick_2.8.7
## [115] cli_3.6.5 locfit_1.5-9.12
## [117] compiler_4.5.1 rlang_1.1.6
## [119] crayon_1.5.3 tmap_4.1
## [121] maptiles_0.10.0 ggsignif_0.6.4
## [123] labeling_0.4.3 classInt_0.4-11
## [125] ggbeeswarm_0.7.2 viridisLite_0.4.2
## [127] BiocParallel_1.43.4 stars_0.6-8
## [129] assertthat_0.2.1 leaflet_2.2.2
## [131] glmnet_4.1-10 Matrix_1.7-3
## [133] sparseMatrixStats_1.21.0 bit64_4.6.0-1
## [135] leafem_0.2.4 ggplot2_3.5.2
## [137] Rhdf5lib_1.31.0 statmod_1.5.0
## [139] broom_1.0.9 bslib_0.9.0
## [141] lwgeom_0.2-14 DEoptimR_1.1-4
## [143] bit_4.6.0