SpaceTrooper is an R/Bioconductor package for Quality Control (QC)
of imaging-based spatial transcriptomics and proteomics data. It provides
multi-platform data harmonization, cell-level QC, and visualization utilities.
The package leverages SpatialExperiment objects to support data from
CosMx, Xenium, and MERFISH technologies.
This vignette describes additional SpaceTrooper utilities that extend the standard workflow and are intended to further improve the user experience. Please, be aware that this is an appendix vignette and does not present an exhaustive analytical workflow. Therefore, users should consult RNA and Protein tutorials before proceeding.
In addition, this vignette provides practical tips for making the most effective use of the package. It is organized into three main sections, corresponding to the typical analysis pipeline, with relevant insights for each step:
This section explains how to specify the inputs required by each data-reading
function. Both readCosmxSPE and readXeniumSPE are wrapper functions built on
the SpatialExperimentIO infrastructure.
Further details on their usage are available in the corresponding function
documentation, e.g. help(readCosmxSPE).
COSMX
library(SpaceTrooper)
library(ggplot2)
cosmxFolder <- system.file(file.path("extdata", "CosMx_DBKero_Tiny"),
package="SpaceTrooper")
spe <- readCosmxSPE(dirName=cosmxFolder,
sampleName="DBKero_CosMx",
coordNames=c("CenterX_global_px", "CenterY_global_px"),
countMatFPattern="exprMat_file.csv",
metadataFPattern="metadata_file.csv",
polygonsFPattern="polygons.csv",
fovPosFPattern="fov_positions_file.csv",
fovdims=c(xdim = 4256, ydim = 4256)
)
Here are summarized the default values of the input parameters. The dirName
parameter specifies the path to the directory containing the flat files produced
by the CosMx platform:
exprMat_file.csv)metadata_file.csv)fov_positions_file.csv)polygons.csv)These files represent the minimum set of inputs required to run the data-reading function.
The sampleName parameter defines the dataset label used as the title in
plotting functions.
The coordNames parameter specifies the column names in the cell metadata
corresponding to centroid coordinates. These are stored in the spatialCoords
slot of the SpatialExperiment and can be assessed via spatialCoords(spe).
They are also the columns used by plotCentroid function.
Additional details on working with SpatialExperiment objects are available in
the SpatialExperiment documentation.
The countMatFPattern, metadataFPattern, polygonsFPattern and
fovPosFPattern define file name patterns used to identify the expression
matrix, cell metadata, Fields of view (FoV) positions, and polygon files,
respectively. As file naming conventions may change over time with evolving
technologies, these parameters allow users to adapt to different file names or
extensions. Currently, CSV files are supported, including compressed .csv.gz.
formats.
IMPORTANT: the cell polygon file is the only input that is not imported
directly into the SpatialExperiment object by the reading function. However,
because polygons can be added later using the readAndAddPolygonsToSPE function
(see the Load polygons subsection), the path to the cell
polygon file is stored in the metadata slot and accessed via
metadata(spe)$polygons.
The fovdims parameter specifies the FoV dimensions as a vector containing the
x and y sizes. While FoV size and shape have changed over time, e.g. from
rectangular to square, in recent CosMx versions they have stabilized at 4,256
pixels per side.
COSMX PROTEIN
protfolder <- system.file( "extdata", "S01_prot", package="SpaceTrooper")
prot <- readCosmxProteinSPE(dirName=protfolder,
sampleName="CosMx_Protein_Tonsil",
coordNames=c("CenterX_global_px", "CenterY_global_px"),
countMatFPattern="exprMat_file.csv",
metadataFPattern="metadata_file.csv",
polygonsFPattern="polygons.csv",
fovPosFPattern="fov_positions_file.csv",
fovdims=c(xdim = 4256, ydim = 4256)
)
# code line for shift correction
metadata(prot)$fov_positions$y_global_px <- metadata(prot)$fov_positions$y_global_px - 4256
readCosmxProteinSPE is a wrapper around readCosmxSPE, thus the required
input files and parameters are identical. Input files may be provided in
compressed csv.gz file format, and the countMatFPattern, metadataFPattern,
polygonsFPattern and fovPosFPattern parameters are used to specify the
corresponding file name patterns.
XENIUM
xeniumFolder <- system.file( "extdata", "Xenium_small", package="SpaceTrooper")
xen <- readXeniumSPE(dirName=xeniumFolder,
sampleName="Xenium_small",
type=c("HDF5", "sparse"),
coordNames=c("x_centroid", "y_centroid"),
boundariesType=c("parquet", "csv"),
computeMissingMetrics=TRUE,
keepPolygons=FALSE,
countsFilePattern="cell_feature_matrix",
metadataFPattern="cells.csv.gz",
polygonsFPattern="cell_boundaries",
polygonsCol="polygons",
txPattern="transcripts",
addFOVs=FALSE
)
## Computing missing metrics, this could take some time...
readXeniumSPE function requires the path to the directory containing the
Xenium output files. This directory is typically generated automatically by the
Xenium pipeline and usually includes the pattern outs in its name. If the
directory exists but this pattern is missing from the provided path, a warning
is issued to allow the path to be corrected.
Xenium outputs are often provided redundantly in multiple formats. The
minimum set of files required to run the SpaceTrooper pipeline includes:
Optionally:
The dirName, sampleName and coordNames parameters behave in the same way
as in readCosmxSPE.
The remaining parameters are described below:
type specifies the format of the expression matrix to be loaded. Currently
only the following two formats are supported: MEX for sparse matrices (Cell
Ranger output) and HDF5. By default, the HDF5 file is used. If only the sparse
MEX format is available, you should provide a vector containing only that
format.
boundariesType specifies the format of the polygon file and must be either
Parquet or CSV. By default, the function uses Parquet format. If only the CSV
file is available, you should provide a vector containing only that format.
computeMissingMetrics is set to TRUE by default and enables the computation of
Area_um and AspectRatio cell metrics from boundary polygons.
IMPORTANT: it is strongly recommended to keep this parameter set to TRUE
as both metrics are required to run computeQCScore(), even if they are not used
in the final formula.
keepPolygons controls whether polygons are retained in the SpatialExperiment
object and is ONLY effective when computeMissingMetrics=TRUE. While
missing metrics can be computed without keeping polygons, polygons cannot be
retained without computing these metrics. However, polygons may also be loaded
at a later stage (see the Load polygons subsection).
countsFilePattern and polygonsFPattern define file name patterns (excluding
the file extension) for the expression matrix and polygon files, correspondingly,
since their formats are already specified via type and boundariesType.
metadataFPattern requires the full file name (including extension) of the cell
metadata file. Only .csv.gz and .parquet files are supported.
polygonsCol defines the name of the column in colData that stores polygon
geometries.
Optionally, FoV information can be retrieved for each cell from the transcript
file. The txPattern parameter specifies the file name pattern for the
transcript file (Parquet format only), while addFOVs controls whether FoV
information is extracted. This option is not mandatory and is therefore set to
FALSE by default.
OF NOTE, because readXeniumSPE is a wrapper function around
SpatialExperimentIO::readXeniumSXE, and multiple probe identifier sets could
be available, Gene Symbols are selected and used as row names.
MERFISH
merfishFolder <- system.file("extdata", "Merfish_Tiny", package="SpaceTrooper")
mer <- readMerfishSPE(dirName=merfishFolder,
sampleName="Merfish_Tiny",
computeMissingMetrics=TRUE,
keepPolygons=FALSE,
boundariesType=c("parquet"),
countmatFPattern="cell_by_gene.csv",
metadataFPattern="cell_metadata.csv",
polygonsFPattern="cell_boundaries.parquet",
coordNames=c("center_x", "center_y"),
polygonsCol="polygons")
## Computing missing metrics, this could take a while...
## Warning in computeMissingMetricsMerfish(pol_file, colData, boundariesType, : Volume is used to compute QC score for MERFISH technology.
## For simplicity, it is renamed as Area_um.
As with the other data-reading functions, readMerfishSPE requires the path to
the directory containing the MERFISH output files. The minimum set of inputs
required to run the SpaceTrooper pipeline includes:
The expression matrix and cell metadata are typically provided in CSV format.
Polygon data can be supplied either as a single Parquet file (recommended when available) or as multiple HDF5 files. In MERFISH/MERSCOPE experiments, HDF5 polygon files are generated per FoV and may easily scale to thousands of files, making this option computationally intensive and time-consuming. Fortunately, in more recent datasets, a Parquet file is usually available.
For this reason, it is recommended to override the default setting and provide a
vector containing only Parquet to the boundariesType parameter.
IMPORTANT: please, pay attention to warnings. computeMissingMetrics
parameter must be set to TRUE whenever it is desired to compute Quality Score
(QS). In MERFISH experiments, transcript hybridization signals are captured also
across the z dimension, and cell size is therefore represented by cell volume in
the provided metadata.
In contrast, cell area can also be computed by SpaceTrooper from polygon
boundaries obtained from the MERFISH experiment but from a single z plane only
(by running computeMissingMetricsMerfish() with useVolume=FALSE).
That said, cell volume appears to be a more appropriate measure of cell size for
QS computation with MERFISH data.
In the current version of SpaceTrooper, when computeMissingMetrics=TRUE, the
volume is renamed as Area_um for compatibility with the computeQCScore
function, whereas cell area is not computed.
For all supported technologies, polygons can be loaded after SpatialExperiment
object creation. The function readAndAddPolygonsToSPE performs the following
steps:
sf object;SpatialExperiment object if no valid polygon is
associated with them;sf object in a colData column whose name can be
specified via the polygonsCol argument;# polygon loading
spe <- readAndAddPolygonsToSPE(spe,
polygonsCol="polygons",
keepMultiPol=TRUE,
boundariesType=c("csv", "HDF5", "parquet")
)
spe$polygons
## Simple feature collection with 905 features and 5 fields
## Active geometry column: global
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: 151625.6 ymin: 18086.62 xmax: 155880.6 ymax: 22341.62
## CRS: NA
## First 10 features:
## cell_id is_multi multi_n fov cellID global
## f16_c1 f16_c1 FALSE 1 16 1 POLYGON ((155326.6 22322.62...
## f16_c10 f16_c10 FALSE 1 16 10 POLYGON ((155567.6 21777.62...
## f16_c100 f16_c100 FALSE 1 16 100 POLYGON ((153436.6 21099.62...
## f16_c101 f16_c101 FALSE 1 16 101 POLYGON ((154227.6 21091.62...
## f16_c102 f16_c102 FALSE 1 16 102 POLYGON ((153685.6 21087.62...
## f16_c103 f16_c103 FALSE 1 16 103 POLYGON ((154020.6 21059.62...
## f16_c104 f16_c104 FALSE 1 16 104 POLYGON ((155332.6 21066.62...
## f16_c105 f16_c105 FALSE 1 16 105 POLYGON ((153199.6 21077.62...
## f16_c106 f16_c106 FALSE 1 16 106 POLYGON ((154589.6 21068.62...
## f16_c107 f16_c107 FALSE 1 16 107 POLYGON ((154135.6 21075.62...
## local
## f16_c1 POLYGON ((3701 4237, 3711 4...
## f16_c10 POLYGON ((3942 3692, 3947 3...
## f16_c100 POLYGON ((1811 3014, 1829 3...
## f16_c101 POLYGON ((2602 3006, 2614 3...
## f16_c102 POLYGON ((2060 3002, 2065 3...
## f16_c103 POLYGON ((2395 2974, 2416 2...
## f16_c104 POLYGON ((3707 2981, 3715 2...
## f16_c105 POLYGON ((1574 2992, 1577 2...
## f16_c106 POLYGON ((2964 2983, 3001 2...
## f16_c107 POLYGON ((2510 2990, 2515 2...
In some technologies, segmentation may produce multi-polygons (indicated as
TRUE in the is_multi column of the sf object shown here), meaning that
more than one polygon is associated with a single cell. This can cause issues
when computing certain derived metrics, particularly theAspectRatio.
By default, the keepMultiPol parameter is set to TRUE. Under this setting,
cells associated with multi-polygons are retained in the dataset; however, their
AspectRatio is NA.
# xenium polygon loading
xen <- readAndAddPolygonsToSPE(xen, boundariesType=c("parquet"))
# merfish polygon loading
mer <- readAndAddPolygonsToSPE(mer, boundariesType=c("parquet"))
# protein polygon loading
prot <- readAndAddPolygonsToSPE(prot, boundariesType=c("csv"))
Multiple geometries files can be loaded into a SpatialExperiment object using
the readAndAddPolygonsToSPE function. The polygonsCol parameter allows users
to specify distinct column names under which these geometries are stored in
colData.
This section describes the cell metadata and quality metrics computed by the
spatialPerCellQC function. When inspecting colData, additional metadata and
metrics provided natively by each technology may also be present; these are
technology-specific and are generally not shared across all platforms. For
details on these additional fields, please refer to the corresponding technology
reference documentation.
spe <- spatialPerCellQC(spe, rmZeros=TRUE,
negProbList=c("NegPrb", "Negative", "SystemControl"))
xen <- spatialPerCellQC(xen, rmZeros=TRUE)
mer <- spatialPerCellQC(mer, rmZeros=TRUE)
prot <- spatialPerCellQC(prot, rmZeros=TRUE)
# check added columns to colData
colnames(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] "polygons" "sum"
## [23] "detected" "subsets_NegPrb_sum"
## [25] "subsets_NegPrb_detected" "subsets_NegPrb_percent"
## [27] "total" "control_sum"
## [29] "control_detected" "target_sum"
## [31] "target_detected" "CenterX_global_px"
## [33] "CenterY_global_px" "ctrl_total_ratio"
## [35] "log2Ctrl_total_ratio" "CenterX_global_um"
## [37] "CenterY_global_um" "Area_um"
## [39] "dist_border_x" "dist_border_y"
## [41] "dist_border" "log2AspectRatio"
## [43] "SignalDensity" "log2SignalDensity"
This function is a wrapper around scuttle::addPerCellQC(), hence a subset of
the reported metrics is derived from that function:
sample_id: character string specifying the dataset sample name. This matches
the value provided to the sampleName argument in the reading function;sum/total: numeric value representing total probe counts (RNA) or total
protein intensity per cell. In this context, sum and total are equivalent;subsets_controlProbeName_sum: numeric value giving sum of the counts
(intensities) obtained from each type of control probe (control protein). For
each one, a separate column is created by replacing “controlProbeName” with the
corresponding pattern from negProbList , e.g. negative control probes (RNA),
negative codewords (RNA), negative control antibodies (protein), etc.;subsets_controlProbeName_detected: numeric value indicating the number of
uniquely detected control probes (proteins) per each type;subsets_controlProbeName_percent: numeric value representing the percentage
of counts (intensities) from each type of control probe (protein) relative to
the total probe counts (protein intensities) per cell;control_sum: numeric value indicating total control probe counts (protein
intensities) per cell. It is the sum of counts (intensities) of all types of
controls;control_detected: numeric value representing the number of uniquely detected
control probes (proteins) per cell;target_sum: numeric value giving target probe counts (protein intensities)
per cell, obtained as sum - control_sum;target_detected: numeric value indicating number of uniquely detected target
probes (proteins) per cell;ctrl_total_ratio: numeric value representing the ratio between total control
probe counts (protein intensities) and total probe counts (protein intensities)
per cell;log2Ctrl_total_ratio: numeric value indicating log2-transformed
ctrl_total_ratioArea_um: numeric value giving cell area in μm² (for MERFISH technology it
corresponds to volume in μm³);dist_border_x: numeric value representing the distance in pixels from the
cell to the closest vertical border of its FoV (only available for CosMx);dist_border_y: numeric value representing the distance in pixels from the
cell to the closest horizontal border of its FoV (only available for CosMx);dist_border: numeric value representing the distance from the cell to the
nearest border of its FoV (only available for CosMx), computed as the minimum of
dist_border_x and dist_border_y;log2AspectRatio: numeric value indicating log2-transformed ratio between
cell maximum length along the x dimension and cell maximum length along the y
dimension in pixels;SignalDensity: numeric value indicating the ratio between total probe counts
(protein intensities) per cell and cell area in µm² (or volume in µm³ for
MERFISH technology);log2SignalDensity: log2-transformed SignalDensity.This section provides further details about the core component of the method: the Quality Score (QS). As already mentioned in RNA and Protein tutorial vignettes, a random seed should be set to ensure reproducible results, as the method involves underlying stochastic processes.
IMPORTANT: when working with recent MERSCOPE datasets, or with any dataset
that uses numeric cell identifiers, it is strongly recommended to convert cell
IDs to character strings before calling the computeQCScore function. This
prevents errors during the selection of training examples when estimating the
coefficients of the QS formula.
# MERSCOPE cell_id conversion
# spe$cell_id <- as.character(spe$cell_id)
set.seed(1713)
spe <- computeQCScore(spe, verbose=TRUE)
## Outliers found for log2SignalDensity:
## 19 38 847
## Outliers found for Area_um:
## 6 898
## Outliers found for log2AspectRatio:
## 11 5 888
## Outliers found for log2Ctrl_total_ratio:
## 9 895
## Chosen low qual examples: 51
## Chosen good quality examples (should match bad): 51
## Final formula used for QC score computation:
## ~(log2SignalDensity + Area_um + I(abs(log2AspectRatio) * as.numeric(dist_border<50)) + log2Ctrl_total_ratio)^2
## Model coefficients for every term used in the formula:
## -1.08 0 0.66 -0.01 -0.89 -0.1 0 -0.31 -0.05 -0.01 0 0.07
When verbose=TRUE, additional information regarding the underlying steps is
reported during the estimation of the QS formula coefficients. For this purpose,
bad and good example cells are selected to train a model that has to assign an
appropriate QS to each cell.
Bad example cells are identified separately for each metric according to several
criteria, based on outlier detection through a statistical test. The specific
test applied depends on the distribution of the metric: for asymmetric
distributions the Medcouple method is used, whereas for symmetric distributions
the Median Absolute Deviation (MAD) is applied, as implemented in
scuttle::isOutlier() with default parameters.
For a detailed description of the selection criteria used for each metric, please refer to the Methods section of the paper.
When inspecting the printed output, the following information is reported:
The first section summarizes the number of outliers identified for each
metric. The three reported values correspond to outliers detected in the right
tail, the left tail of the distribution, and the remaining non-outlier cells,
respectively.
Outlier detection is performed on the full dataset after excluding
cells with zero counts, if these were retained when running the
spatialPerCellQC function.
This step is carried out for all metrics, even those that are not ultimately
included in the final QS formula; however, outliers from excluded metrics are
not used for model training.
The next section reports the number of selected bad example cells, followed by the number of good example cells, which matches the former. Because the criteria for selecting good examples are intentionally permissive, these cells are sampled at random.
The final section displays the QS formula used for model training and score computation, along with the estimated coefficients for each retained term and all pairwise interactions.
IMPORTANT: at present, QS computation requires log2SignalDensity as a
mandatory metric in the QS formula. If an insufficient number of outliers is
detected for this metric (fewer than 0.1% of the dataset after excluding
zero-count cells), QS computation cannot proceed using the remaining metrics.
In such cases, the provided code will still add aQC_score column to colData.
This column is populated if the minimum requirement is met and contains NA
values otherwise.
# safe run function
safe_run <- function(expr) {
tryCatch(
list(result = expr, error = NULL),
error = function(e) list(result = NULL, error = e)
)
}
out <- safe_run(computeQCScore(spe))
if (!is.null(out$error)) {
message("Failed: ", out$error$message)
colData(spe)$QC_score <- NA
} else {
spe <- out$result
}
The SpaceTrooper package allows the identification of numerically aberrant
cells through outlier detection for each quantitative metric, using the same
procedures applied internally by the computeQCScore function. This enables
metric-specific cell flagging in a manner analogous to standard scRNA-seq
quality control workflows.
# detecting outliers for cell area in Xenium dataset with both Medcouple
# and MAD
xen <- computeSpatialOutlier(xen, computeBy="Area_um", method = "both")
## Warning in computeSpatialOutlier(xen, computeBy = "Area_um", method = "both"):
## Distribution is symmetric: mc is for asymmetric distributions. Use scuttle
## instead.
Pay attention to warnings: setting the method to both, applies both the
Medcouple and MAD approaches to identify outliers. Outlier results are stored in
two separate colData columns, with names formed by appending _outlier_mc
and _outlier_sc to the variable name. If a warning indicates that the variable
is symmetric, only the _outlier_sc column should be used for downstream
analyses.
spe <- computeSpatialOutlier(spe, computeBy="Mean.CD68", method = "both")
table(spe$Mean.CD68_outlier_mc)
##
## HIGH LOW NO
## 52 4 848
The three numbers correspond to outliers in the right tail (HIGH), in the
left tail (LOW) of the variable distribution, and remaining non-outlier cells
(NO).
Variable distributions can be visualized using the plotMetricsHist function,
as demonstrated in the RNA and Protein tutorial vignette.
If the computeSpatialOutlier function has already been executed, the resulting
columns can be provided as input to useFences parameter to display lines
corresponding to the upper and lower thresholds, used to define HIGH and LOW
outliers, respectively.
spe <- computeSpatialOutlier(spe, computeBy="log2SignalDensity", method = "both")
plotMetricHist(spe, metric="log2SignalDensity",
useFences="log2SignalDensity_outlier_mc")
The threshold values are indicated in the plot legend.
The plotZoomFovsMap function provides a zoomed-in view of selected FoVs, with
cell polygons colored according to the metric specified in the colourBy parameter.
In addition, it includes an overview map of all FoVs, analogous to that produced
by plotCellsFovs function.
# plotting FoVs map and zoom in of selected FoV colored by QS
plotZoomFovsMap(spe, fovs=16, colourBy="QC_score", csize=3, scaleBars=TRUE)
For this plot, scaleBars parameter controls whether scale bars are displayed
in both plots simultaneously. To show the scale bar in only one of the two
plots, set either scaleBarMap=FALSE or scaleBarPol=FALSE.
plotZoomFovsMap(prot, fovs = 344, colourBy="Area_um", csize=3, scaleBarMap=TRUE,
scaleBarPol=FALSE)
For the other plots, the scaleBar parameter can be set to FALSE to hide the
scale bar.
plotCentroids(spe, colourBy="QC_score", size=3, scaleBar=FALSE) +
scale_fill_viridis_c(option = "plasma") +
scale_color_viridis_c(option = "plasma")
plotPolygons(prot, colourBy="log2SignalDensity", scaleBar=FALSE) +
scale_fill_viridis_c(option="mako")
sessionInfo()
## R Under development (unstable) (2026-01-15 r89304)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.3 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.23-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] ggplot2_4.0.2 SpaceTrooper_1.1.6
## [3] SpatialExperiment_1.21.0 SingleCellExperiment_1.33.0
## [5] SummarizedExperiment_1.41.1 Biobase_2.71.0
## [7] GenomicRanges_1.63.1 Seqinfo_1.1.0
## [9] IRanges_2.45.0 S4Vectors_0.49.0
## [11] BiocGenerics_0.57.0 generics_0.1.4
## [13] MatrixGenerics_1.23.0 matrixStats_1.5.0
## [15] BiocStyle_2.39.0
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 jsonlite_2.0.0
## [3] shape_1.4.6.1 magrittr_2.0.4
## [5] ggbeeswarm_0.7.3 magick_2.9.0
## [7] farver_2.1.2 rmarkdown_2.30
## [9] vctrs_0.7.1 DelayedMatrixStats_1.33.0
## [11] tinytex_0.58 rstatix_0.7.3
## [13] htmltools_0.5.9 S4Arrays_1.11.1
## [15] BiocNeighbors_2.5.3 broom_1.0.12
## [17] Rhdf5lib_1.33.0 SparseArray_1.11.10
## [19] Formula_1.2-5 rhdf5_2.55.13
## [21] sass_0.4.10 KernSmooth_2.23-26
## [23] bslib_0.10.0 cachem_1.1.0
## [25] lifecycle_1.0.5 iterators_1.0.14
## [27] pkgconfig_2.0.3 rsvd_1.0.5
## [29] Matrix_1.7-4 R6_2.6.1
## [31] fastmap_1.2.0 digest_0.6.39
## [33] scater_1.39.2 dqrng_0.4.1
## [35] irlba_2.3.7 ggpubr_0.6.2
## [37] beachmat_2.27.2 labeling_0.4.3
## [39] SpatialExperimentIO_1.3.0 abind_1.4-8
## [41] compiler_4.6.0 proxy_0.4-29
## [43] bit64_4.6.0-1 withr_3.0.2
## [45] S7_0.2.1 backports_1.5.0
## [47] BiocParallel_1.45.0 carData_3.0-6
## [49] viridis_0.6.5 DBI_1.2.3
## [51] HDF5Array_1.39.0 R.utils_2.13.0
## [53] ggsignif_0.6.4 DelayedArray_0.37.0
## [55] rjson_0.2.23 classInt_0.4-11
## [57] tools_4.6.0 units_1.0-0
## [59] vipor_0.4.7 otel_0.2.0
## [61] beeswarm_0.4.0 R.oo_1.27.1
## [63] glue_1.8.0 h5mread_1.3.1
## [65] rhdf5filters_1.23.3 grid_4.6.0
## [67] sf_1.0-24 gtable_0.3.6
## [69] R.methodsS3_1.8.2 class_7.3-23
## [71] tidyr_1.3.2 data.table_1.18.2.1
## [73] BiocSingular_1.27.1 ScaledMatrix_1.19.0
## [75] car_3.1-5 XVector_0.51.0
## [77] ggrepel_0.9.6 foreach_1.5.2
## [79] pillar_1.11.1 limma_3.67.0
## [81] robustbase_0.99-7 splines_4.6.0
## [83] dplyr_1.2.0 lattice_0.22-9
## [85] survival_3.8-6 bit_4.6.0
## [87] tidyselect_1.2.1 locfit_1.5-9.12
## [89] scuttle_1.21.0 sfheaders_0.4.5
## [91] knitr_1.51 gridExtra_2.3
## [93] bookdown_0.46 edgeR_4.9.2
## [95] xfun_0.56 statmod_1.5.1
## [97] DropletUtils_1.31.0 DEoptimR_1.1-4
## [99] yaml_2.3.12 evaluate_1.0.5
## [101] codetools_0.2-20 tibble_3.3.1
## [103] BiocManager_1.30.27 cli_3.6.5
## [105] arrow_23.0.0.1 jquerylib_0.1.4
## [107] dichromat_2.0-0.1 Rcpp_1.1.1
## [109] parallel_4.6.0 assertthat_0.2.1
## [111] sparseMatrixStats_1.23.0 glmnet_4.1-10
## [113] viridisLite_0.4.3 scales_1.4.0
## [115] e1071_1.7-17 purrr_1.2.1
## [117] rlang_1.1.7 cowplot_1.2.0