| Title: | Bootstrap Classification Confidence for Spatial Cell-Type Analysis |
|---|---|
| Description: | Cell type labels in spatial single-cell data are uncertain, particularly between closely related subtypes. fuzzyCell estimates a per-cell classification confidence by bootstrapping (multinomial resampling of each cell's counts followed by re-classification) and uses the resulting confidences as soft cell type weights. The weights are propagated through downstream analyses: cell type proportions, co-localisation (spicyR's L-function, and Statial's Kontextual test for relative co-localisation) and niche identification (lisaClust), each compared to the same analysis using hard labels. Cell types are organised with a user-supplied hierarchy of lineages, groups and subtypes. Helpers for testing against sample-level outcomes and for plotting are included. |
| Authors: | Shreya Rao [aut, cre] (ORCID: <https://orcid.org/0009-0007-8140-6844>), Ellis Patrick [aut, ths] |
| Maintainer: | Shreya Rao <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.99.1 |
| Built: | 2026-10-29 10:24:36 UTC |
| Source: | https://github.com/BiocStaging/fuzzyCell |
The single-group worker behind bootstrapLineageConfidence(). Trains a classifier on one group's cells, then repeatedly resamples each cell's counts (multinomial resampling) and re-predicts its class. The fraction of resamples assigning a cell to each class is its confidence for that class.
bootstrapClassify( countMat, labels, nBoot = 100, nPerClass = 50, cores = 1, seed = NULL, classifier = c("pcaLogistic", "logistic", "rf", "lda", "svm"), ntree = 500, priors = c("balanced", "observed"), correctedCounts = FALSE )bootstrapClassify( countMat, labels, nBoot = 100, nPerClass = 50, cores = 1, seed = NULL, classifier = c("pcaLogistic", "logistic", "rf", "lda", "svm"), ntree = 500, priors = c("balanced", "observed"), correctedCounts = FALSE )
countMat |
A cells x genes matrix of raw (non-negative integer) counts for the cells of one group. Normalised or log-transformed values are rejected, since the resampling needs each cell's total transcript count. |
labels |
Character vector of the original cell type label for each
row of |
nBoot |
Number of bootstrap resamples. |
nPerClass |
Minimum number of training cells per class; classes smaller than this are up-sampled with replacement. |
cores |
Number of cores to run the bootstrap resamples on (forked
with BiocParallel); the default runs serially. On Windows, where forking is
not available, it always runs serially. If |
seed |
Random seed for reproducibility, or |
classifier |
One of |
ntree |
Number of trees; only used when |
priors |
The classifier is trained with balanced classes, which gives
every class the same prior. |
correctedCounts |
|
A numeric matrix with one row per cell (in the order of
countMat) and one column per class in labels. Entry [i, k] is the
fraction of bootstrap resamples in which cell i was classified as class
k, so each row sums to 1.
data(lungSubset) endo = lungSubset$cellType %in% c("Arteriole", "Venous", "Capillary", "Lymphatic") countMat = t(as.matrix(SummarizedExperiment::assay(lungSubset, "counts")[, endo])) freq = bootstrapClassify(countMat, lungSubset$cellType[endo], nBoot = 5, seed = 1) head(freq)data(lungSubset) endo = lungSubset$cellType %in% c("Arteriole", "Venous", "Capillary", "Lymphatic") countMat = t(as.matrix(SummarizedExperiment::assay(lungSubset, "counts")[, endo])) freq = bootstrapClassify(countMat, lungSubset$cellType[endo], nBoot = 5, seed = 1) head(freq)
For each group in cellTypeTree that has children (see cellTypeTree),
runs bootstrapClassify() on that group's cells to get, for every cell, a
confidence score for each of the group's child cell types. The result is
the confList used by the downstream analyses, such as
runProportionsPipeline() and runColocalisationModels(). Cell types without a
group (ungrouped leaves) are not refined and keep hard labels.
bootstrapLineageConfidence( spe, cellTypeTree, nBoot = 100, nPerClass = 50, cores = 1, seed = 51773, skipGroups = character(0), subprocess = FALSE, classifier = c("pcaLogistic", "logistic", "rf", "lda", "svm"), ntree = 500, priors = c("balanced", "observed"), correctedCounts = FALSE, cellType = "cellType", cellID = "cellID", assayName = "counts" )bootstrapLineageConfidence( spe, cellTypeTree, nBoot = 100, nPerClass = 50, cores = 1, seed = 51773, skipGroups = character(0), subprocess = FALSE, classifier = c("pcaLogistic", "logistic", "rf", "lda", "svm"), ntree = 500, priors = c("balanced", "observed"), correctedCounts = FALSE, cellType = "cellType", cellID = "cellID", assayName = "counts" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
nBoot |
Number of bootstrap resamples. |
nPerClass |
Minimum number of training cells per class; classes smaller than this are up-sampled with replacement. |
cores |
Number of cores to run the bootstrap resamples on (forked
with BiocParallel); the default runs serially. On Windows, where forking is
not available, it always runs serially. If |
seed |
Random seed, or |
skipGroups |
Names of groups to leave out of the result. |
subprocess |
If |
classifier |
One of |
ntree |
Number of trees; only used when |
priors |
The classifier is trained with balanced classes, which gives
every class the same prior. |
correctedCounts |
|
cellType |
Name of the |
cellID |
Name of the |
assayName |
Name of the assay with the raw counts. |
A named list with one element per group (named by group). Groups
with no cells, or with only one cell type present, cannot be bootstrapped:
they are skipped with a message and left out of the list. Each
element is a data.frame with one row per cell in that group, a cellID
column, and one column per child cell type of the group holding the
cell's confidence score for that cell type (between 0 and 1, rows summing
to 1 across the child columns).
Each data frame also carries a "settings" attribute recording how it
was computed (nBoot, nPerClass, classifier, priors,
correctedCounts, ntree, the group's seed, its children and the
fuzzyCellVersion).
data(lungSubset) data(lungCellTypeTree) confList = bootstrapLineageConfidence(lungSubset, lungCellTypeTree, nBoot = 5, seed = 1) names(confList) head(confList[["Endothelial lineage"]]) # the same call with nBoot = 20 gives the confidences in `lungConfList`data(lungSubset) data(lungCellTypeTree) confList = bootstrapLineageConfidence(lungSubset, lungCellTypeTree, nBoot = 5, seed = 1) names(confList) head(confList[["Endothelial lineage"]]) # the same call with nBoot = 20 gives the confidences in `lungConfList`
Helpers for the cell type tree: a nested list describing how cell types are
organised into broad lineages and (optionally) groups of closely related
subtypes. bootstrapLineageConfidence() refines the cells within each group,
and the analysis functions compare cell types, groups and lineages.
buildCellTypeMap(cellTypeTree) annotateCellTypeTree(spe, cellTypeTree, cellType = "cellType") resolveTreeLeaves(cellTypeTree, nodeName) autoParentOverrides(cellTypeTree)buildCellTypeMap(cellTypeTree) annotateCellTypeTree(spe, cellTypeTree, cellType = "cellType") resolveTreeLeaves(cellTypeTree, nodeName) autoParentOverrides(cellTypeTree)
cellTypeTree |
A nested list describing the cell type hierarchy (see Details and heartCellTypeTree). |
spe |
A |
cellType |
Name of the column of |
nodeName |
A single string: the name of any node in |
A tree is a named list with one entry per broad lineage (these become the
lineage column). Each lineage is either a character vector of cell types,
or a list whose entries are:
a bare string: a cell type that is not in any group;
a named list(children = c(...)): a group of closely related cell
types, the unit that is bootstrap-refined. A group may contain only
children;
a named list of further entries: purely organisational nesting (a "wrapper") that is not a group itself, to any depth.
A lineage can also itself be list(children = c(...)), in which case the
lineage name doubles as the group name. A cell type's group is its nearest
list(children = ...) ancestor, however many wrappers sit above it. In the
example below CD8_Resting is in the group CD8+ T cells, not T cells.
Every cell type must appear exactly once, and lineage, wrapper and group names must be unique and different from every cell type name.
list(
"Immune" = list(
"T cells" = list(
"CD8+ T cells" = list(children = c("CD8_Resting", "CD8_Memory")),
"CD4+ T cells" = list(children = c("CD4_naive", "CD4_Memory"))),
"NK",
"Mast"),
"Endothelial lineage" = c("Endothelial", "Activated endothelial"))
resolveTreeLeaves() expands any node, however far up the tree, to the cell
types beneath it. It is used by relative co-localisation when it conditions
on a parent that is broader than a cell type's own group (see
parentOverrides in runColocalisationModels()), and autoParentOverrides() finds
those parents automatically.
buildCellTypeMap(): a list with cellMap (a data.frame with columns
cellType, group and broad, one row per cell type) and
groupsWithChildren (names of the groups to be bootstrap-refined). An
error is raised if the tree is not a valid tree as described in Details:
it must be a non-empty named list, every top-level entry must be named,
groups may only contain children, cell type names must be non-empty
strings, and names must not be repeated or shared between cell types and
lineages, wrappers or groups.
annotateCellTypeTree(): spe with group and lineage columns added
(a message reports any existing group or lineage column whose values
are replaced). An error is raised if any cell's cell type is not in the
tree (including NA).
resolveTreeLeaves(): character vector of every cell type beneath
nodeName.
autoParentOverrides(): named character vector mapping each group that
has a named ancestor to that ancestor, for use as parentOverrides in
runColocalisationModels().
data(lungCellTypeTree) buildCellTypeMap(lungCellTypeTree) resolveTreeLeaves(lungCellTypeTree, "Immune") autoParentOverrides(lungCellTypeTree) data(lungSubset) cells = annotateCellTypeTree(getCellData(lungSubset), lungCellTypeTree) table(cells$group, useNA = "ifany")data(lungCellTypeTree) buildCellTypeMap(lungCellTypeTree) resolveTreeLeaves(lungCellTypeTree, "Immune") autoParentOverrides(lungCellTypeTree) data(lungSubset) cells = annotateCellTypeTree(getCellData(lungSubset), lungCellTypeTree) table(cells$group, useNA = "ifany")
Builds the soft cell type membership of every cell, the weights that the weighted analyses pass to spicyR and lisaClust: one column per leaf cell type and per group of the tree. A cell of a bootstrapped group has, for each subtype of the group, its bootstrap confidence in that subtype; every other cell has weight 1 for its own cell type. A group's column is 1 for each of its cells, since the bootstrap reclassifies cells only within their group.
confidenceWeights( spe, cellTypeTree, confList, weighted = TRUE, cellType = "cellType", cellID = "cellID" )confidenceWeights( spe, cellTypeTree, confList, weighted = TRUE, cellType = "cellType", cellID = "cellID" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
confList |
Confidence list from |
weighted |
|
cellType, cellID
|
Names of the |
A numeric matrix with one row per cell of spe (in its order) and one
named column per leaf cell type and group.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) w = confidenceWeights(lungSubset, lungCellTypeTree, lungConfList) head(w[, c("Arteriole", "Venous", "Endothelial lineage")])data(lungSubset) data(lungCellTypeTree) data(lungConfList) w = confidenceWeights(lungSubset, lungCellTypeTree, lungConfList) head(w[, c("Arteriole", "Venous", "Endothelial lineage")])
An alternative to bootstrapLineageConfidence(): for each group with
children, a classifier is trained on the group's cells with balanced classes
and gives each cell the probability of each child cell type. The cells are
split into nFolds folds and each fold is scored by a classifier trained on
the other folds, so no cell is scored by a classifier that saw it. Because
the classes are balanced in training, the probabilities give every child cell
type the same prior weight.
crossfitLineageProbabilities( spe, cellTypeTree, nFolds = 5, nPerClass = 50, seed = 51773, classifier = c("pcaLogistic", "logistic", "rf", "lda"), ntree = 500, priors = c("balanced", "observed"), cores = 1, skipGroups = character(0), cellType = "cellType", cellID = "cellID", assayName = "counts" )crossfitLineageProbabilities( spe, cellTypeTree, nFolds = 5, nPerClass = 50, seed = 51773, classifier = c("pcaLogistic", "logistic", "rf", "lda"), ntree = 500, priors = c("balanced", "observed"), cores = 1, skipGroups = character(0), cellType = "cellType", cellID = "cellID", assayName = "counts" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
nFolds |
Number of folds. The folds are stratified by cell type, so every fold's classifier is trained on every child cell type; each child cell type therefore needs at least 2 cells. |
nPerClass |
Minimum number of training cells per class; classes smaller than this are up-sampled with replacement. |
seed |
Random seed, or |
classifier |
|
ntree |
Number of trees; only used when |
priors |
|
cores |
Number of cores to fit the folds on in parallel, as in
|
skipGroups |
Names of groups to leave out of the result. |
cellType |
Name of the |
cellID |
Name of the |
assayName |
Name of the assay with the raw counts. |
A confidence list in the format of bootstrapLineageConfidence(),
with probabilities in place of bootstrap confidences.
data(lungSubset) data(lungCellTypeTree) probList = crossfitLineageProbabilities(lungSubset, lungCellTypeTree, nFolds = 3, seed = 1) head(probList[["Endothelial lineage"]])data(lungSubset) data(lungCellTypeTree) probList = crossfitLineageProbabilities(lungSubset, lungCellTypeTree, nFolds = 3, seed = 1) head(probList[["Endothelial lineage"]])
Returns colData(spe) as a data.frame. For a SpatialExperiment whose
coordinates are stored in spatialCoords() rather than in colData(),
the coordinates are added as columns x and y. The spatial functions in
fuzzyCell expect cellID, imageID, cellType, x and y columns.
getCellData(spe)getCellData(spe)
spe |
A |
A data.frame with one row per cell.
data(lungSubset) head(getCellData(lungSubset))data(lungSubset) head(getCellData(lungSubset))
The cell type hierarchy used with loadAmancherla(): broad lineages, groups
of closely related subtypes (for example the T cell subtypes), and ungrouped
leaf cell types. See cellTypeTree for the format.
data(heartCellTypeTree)data(heartCellTypeTree)
A nested list; see cellTypeTree.
Defined in data-raw/heartCellTypeTree.R.
data(heartCellTypeTree) buildCellTypeMap(heartCellTypeTree)$groupsWithChildrendata(heartCellTypeTree) buildCellTypeMap(heartCellTypeTree)$groupsWithChildren
Downloads the Amancherla et al. (2025) heart transplant Xenium dataset from
the SpatialDatasets package (via ExperimentHub) and prepares it for fuzzyCell:
renames the columns fuzzyCell expects, keeps patients with cellular rejection,
and keeps one randomly chosen image per patient for each biopsy timing.
The first call downloads the data, which is large. With "both" every patient
has an image before and after transplant, so those images are not independent
and cannot be passed together to runColocalisationModels() with subject = "subject".
loadAmancherla(timing = c("pre", "post", "both"), seed = 51773)loadAmancherla(timing = c("pre", "post", "both"), seed = 51773)
timing |
Which biopsies to keep: |
seed |
Random seed used to choose one image per patient. |
The prepared object has the columns fuzzyCell functions use: cellID,
imageID, cellType, x, y and subject, and the per-patient outcome
resolution_broad ("persistence" or "resolved"). The cell type
hierarchy for these cell types is in heartCellTypeTree.
A SpatialExperiment.
spe = loadAmancherla("pre") spe table(spe$resolution_broad)spe = loadAmancherla("pre") spe table(spe$resolution_broad)
The cell type hierarchy for lungSubset (and the full
SpatialDatasets::spe_Vannan_2025() data): broad lineages, groups of closely
related subtypes (for example the fibroblast subtypes), and ungrouped leaf
cell types. See cellTypeTree for the format.
data(lungCellTypeTree)data(lungCellTypeTree)
A nested list; see cellTypeTree.
Defined in data-raw/lungCellTypeTree.R.
data(lungCellTypeTree) buildCellTypeMap(lungCellTypeTree)$groupsWithChildrendata(lungCellTypeTree) buildCellTypeMap(lungCellTypeTree)$groupsWithChildren
The bootstrap classification confidences of the cells in lungSubset, from
bootstrapLineageConfidence(lungSubset, lungCellTypeTree, nBoot = 20, classifier = "pcaLogistic", seed = 1), so that the examples can skip the
bootstrap.
data(lungConfList)data(lungConfList)
A named list with one data frame per group of lungCellTypeTree
(see bootstrapLineageConfidence() for the format).
Built by data-raw/lungConfList.R.
data(lungConfList) names(lungConfList) head(lungConfList[["Endothelial lineage"]])data(lungConfList) names(lungConfList) head(lungConfList[["Endothelial lineage"]])
Xenium data of lung biopsies from Vannan et al. (2025), available in full as
SpatialDatasets::spe_Vannan_2025(), cut down to ship with the package. It
has five control and five pulmonary fibrosis biopsies (the five with the
fewest cells of each), each cropped to the roughly 3,000 cells in a square
window at its centre, so each image is a window of a larger biopsy. Every
image comes from a different subject. Cell types with fewer than 20 cells in
the windows are removed. The hierarchy for these cell types is in
lungCellTypeTree.
data(lungSubset)data(lungSubset)
A SpatialExperiment with the raw counts of 343 genes in 29,971
cells (assay counts), the cell coordinates in spatialCoords(), and in
colData:
A unique cell ID.
The image (the window of a biopsy); also sample_id.
The patient.
The cell type label.
"Control" or "Disease".
Built from SpatialDatasets::spe_Vannan_2025() by
data-raw/lungSubset.R.
data(lungSubset) lungSubset table(lungSubset$imageID, lungSubset$disease_status)data(lungSubset) lungSubset table(lungSubset$imageID, lungSubset$disease_status)
Defines niches by k-means clustering of per-cell feature vectors, once with
hard cell type membership and once with bootstrap-confidence weights. The
features of each cell are its local indicators of spatial association from
lisaClust (lisaClust::lisa()) at several radii.
runNicheIdentification( spe, cellTypeTree, confList, toLabels = NULL, r = c(20, 50, 100), k, window = "convex", lisaFunc = "K", cores = 1, seed = 51773, cellType = "cellType", cellID = "cellID", imageID = "imageID", x = "x", y = "y" )runNicheIdentification( spe, cellTypeTree, confList, toLabels = NULL, r = c(20, 50, 100), k, window = "convex", lisaFunc = "K", cores = 1, seed = 51773, cellType = "cellType", cellID = "cellID", imageID = "imageID", x = "x", y = "y" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
confList |
Confidence list from |
toLabels |
Labels (leaves and/or groups) to build features from; defaults to every leaf and group in the tree. An error is raised for a label that is not in the tree. |
r |
Radii of the local curves: one or more positive numbers. |
k |
Number of niches, a whole number of at least 2 and below the number of cells. |
window, lisaFunc
|
The image window and the local function ( |
cores |
Number of threads. |
seed |
Random seed for the k-means clustering, as in
|
cellType, cellID, imageID
|
Names of the |
x, y
|
Names of the columns holding the cell coordinates. For a
|
For every cell, every label in toLabels and every radius in r, the
feature is the local co-localisation of the cell's neighbours with that label
(lisaClust's local K or L function, centred so that 0 means no attraction or
repulsion). The weighted features count each neighbour with its bootstrap
confidence of having the label, instead of 0 or 1 (see confidenceWeights()),
and a label's density is its summed weight per unit area.
Niche names (niche1, niche2, ...) are arbitrary. K-means starts from
random cluster centres, so the niches depend on the random seed. The
unweighted and weighted clusterings are both started from the same seed,
so that if the weights made no difference the two sets of niches would be
identical.
A list with the feature matrices (lisaMatUnweighted,
lisaMatWeighted) and named cell-to-niche vectors nicheUnweighted and
nicheWeighted.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) table(weighted = niches$nicheWeighted, unweighted = niches$nicheUnweighted)data(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) table(weighted = niches$nicheWeighted, unweighted = niches$nicheUnweighted)
plotNicheSpatial() shows the cells of one niche in one image.
nicheCompositionMap() shows the relative enrichment of each cell type in
each niche as a bubble plot or heatmap. nicheBarplot() shows it for a single
niche. nicheProportionBoxplot() compares a niche's per-image proportion
between outcome groups.
plotNicheSpatial(spe, imageID, niche, nicheCol = "nicheWeighted", cellSize = 1) nicheCompositionMap( spe, niche, cellType = "cellType", type = c("bubble", "heatmap"), limit = c(0.33, 3), ... ) nicheBarplot(spe, niche, target, cellType = "cellType", limit = c(0.33, 3)) nicheProportionBoxplot(proportions, niche, spe, outcomeCol)plotNicheSpatial(spe, imageID, niche, nicheCol = "nicheWeighted", cellSize = 1) nicheCompositionMap( spe, niche, cellType = "cellType", type = c("bubble", "heatmap"), limit = c(0.33, 3), ... ) nicheBarplot(spe, niche, target, cellType = "cellType", limit = c(0.33, 3)) nicheProportionBoxplot(proportions, niche, spe, outcomeCol)
spe |
A |
imageID |
The image to plot. |
niche |
For |
nicheCol |
The niche assignments for |
cellSize |
Size of the highlighted cells in |
cellType |
Column of |
type |
|
limit |
Lower and upper limit of the relative enrichment. |
... |
Further arguments passed to |
target |
The niche to plot in |
proportions |
The |
outcomeCol |
Name of the per-image outcome column in |
A ggplot object; for nicheProportionBoxplot() a girafe
(interactive) widget; for nicheCompositionMap(type = "heatmap") the
result of pheatmap::pheatmap().
data(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) plotNicheSpatial(lungSubset, "VUHD113", "niche1", nicheCol = niches$nicheWeighted) nicheCompositionMap(lungSubset, niches$nicheWeighted) nicheBarplot(lungSubset, niches$nicheWeighted, "niche1") res = testNicheOutcome(lungSubset, niches$nicheUnweighted, niches$nicheWeighted, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { nicheProportionBoxplot(res$propWeighted, "niche1", lungSubset, "disease_status") nicheProportionBoxplot(res$propUnweighted, "niche1", lungSubset, "disease_status") }data(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) plotNicheSpatial(lungSubset, "VUHD113", "niche1", nicheCol = niches$nicheWeighted) nicheCompositionMap(lungSubset, niches$nicheWeighted) nicheBarplot(lungSubset, niches$nicheWeighted, "niche1") res = testNicheOutcome(lungSubset, niches$nicheUnweighted, niches$nicheWeighted, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { nicheProportionBoxplot(res$propWeighted, "niche1", lungSubset, "disease_status") nicheProportionBoxplot(res$propUnweighted, "niche1", lungSubset, "disease_status") }
Plots one image, with the cells of a group shaded by the (library-size normalised, rescaled) expression of one or two markers.
plotOneMarkerSpatial( spe, imageID, group, marker, colour = "purple", cellTypeTree = NULL, cellSize = 1, assayName = "counts" ) plotTwoMarkerSpatial( spe, imageID, groupA, markerA, colourA = "purple", groupB, markerB, colourB = "green", cellTypeTree = NULL, cellSize = 1, assayName = "counts" )plotOneMarkerSpatial( spe, imageID, group, marker, colour = "purple", cellTypeTree = NULL, cellSize = 1, assayName = "counts" ) plotTwoMarkerSpatial( spe, imageID, groupA, markerA, colourA = "purple", groupB, markerB, colourB = "green", cellTypeTree = NULL, cellSize = 1, assayName = "counts" )
spe |
A |
imageID |
The image to plot. |
group, groupA, groupB
|
Group name(s) whose cells are shaded. |
marker, markerA, markerB
|
Gene name(s), which must be rows of the assay. |
colour, colourA, colourB
|
Colour(s) used for the shading. |
cellTypeTree |
A cell type tree, used to find the cells of each group.
It is needed unless |
cellSize |
Size of the highlighted cells, the ones drawn in colour. The grey background cells always have size 0.7. |
assayName |
Name of the assay with the counts. Expression is normalised by each cell's library size. |
A ggplot object.
data(lungSubset) data(lungCellTypeTree) plotOneMarkerSpatial(lungSubset, "VUHD113", "Endothelial lineage", "HEY1", cellTypeTree = lungCellTypeTree) plotTwoMarkerSpatial(lungSubset, "VUHD113", "Endothelial lineage", "PECAM1", "purple", "Fibroblast lineage", "COL1A1", "green", cellTypeTree = lungCellTypeTree)data(lungSubset) data(lungCellTypeTree) plotOneMarkerSpatial(lungSubset, "VUHD113", "Endothelial lineage", "HEY1", cellTypeTree = lungCellTypeTree) plotTwoMarkerSpatial(lungSubset, "VUHD113", "Endothelial lineage", "PECAM1", "purple", "Fibroblast lineage", "COL1A1", "green", cellTypeTree = lungCellTypeTree)
Shows, for one pair of cell types or groups, the per-image co-localisation measured with the original labels (unweighted) and with the bootstrap confidence weights (weighted), for each level of the outcome. Each point is one image.
plotMetricBoxplot( results, spe, fromType, toType, outcomeCol, metric = c("lfunction", "kontextual") )plotMetricBoxplot( results, spe, fromType, toType, outcomeCol, metric = c("lfunction", "kontextual") )
results |
Output of |
spe |
A |
fromType, toType
|
The pair to show. An error is raised if the pair is
not in the results; relative co-localisation ( |
outcomeCol |
Name of the outcome column in |
metric |
The measure to plot: |
An interactive plot, a girafe widget that needs the ggiraph
package.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runColocalisationModels(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { plotMetricBoxplot(res, lungSubset, "Mast", "Proliferating FBs", outcomeCol = "disease_status") plotMetricBoxplot(res, lungSubset, "Mast", "Proliferating FBs", outcomeCol = "disease_status", metric = "kontextual") }data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runColocalisationModels(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { plotMetricBoxplot(res, lungSubset, "Mast", "Proliferating FBs", outcomeCol = "disease_status") plotMetricBoxplot(res, lungSubset, "Mast", "Proliferating FBs", outcomeCol = "disease_status", metric = "kontextual") }
Shows, for one cell type (or group), each image's proportion measured with
the original labels (unweighted) and with the bootstrap confidence weights
(weighted), for each level of the outcome. For the results of
runProportionsPipeline() the proportion is of all cells in the image; for
the results of runProportionsRelativeToParentPipeline() it is of the cells
of the parent group. Each point is one image.
plotProportionBoxplot(results, cellType, spe, outcomeCol)plotProportionBoxplot(results, cellType, spe, outcomeCol)
results |
Output of |
cellType |
The cell type to show: one of the |
spe |
A |
outcomeCol |
Name of the outcome column in |
An interactive plot, a girafe widget that needs the ggiraph
package.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runProportionsPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") rel = runProportionsRelativeToParentPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { plotProportionBoxplot(res, "Arteriole", lungSubset, "disease_status") plotProportionBoxplot(rel, "Arteriole", lungSubset, "disease_status") }data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runProportionsPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") rel = runProportionsRelativeToParentPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") if (requireNamespace("ggiraph", quietly = TRUE)) { plotProportionBoxplot(res, "Arteriole", lungSubset, "disease_status") plotProportionBoxplot(rel, "Arteriole", lungSubset, "disease_status") }
Plots the cells of one image, highlighting a cell type or group, or showing bootstrap confidence scores.
plotWeightedSpatialPair( spe, cellTypeTree, confList, imageID, groupA, subtypeA, groupB, subtypeB, encoding = c("alpha", "colour"), cellSize = 1 ) plotHardSpatialPair( spe, imageID, subtypeA, subtypeB, cellTypeTree = NULL, cellSize = 1 ) plotWeightedSpatial( spe, cellTypeTree, confList, imageID, targetGroup, targetSubtype, cellSize = 1 ) plotOriginalLabelSpatial(spe, cellTypeTree, imageID, targetGroup, cellSize = 1)plotWeightedSpatialPair( spe, cellTypeTree, confList, imageID, groupA, subtypeA, groupB, subtypeB, encoding = c("alpha", "colour"), cellSize = 1 ) plotHardSpatialPair( spe, imageID, subtypeA, subtypeB, cellTypeTree = NULL, cellSize = 1 ) plotWeightedSpatial( spe, cellTypeTree, confList, imageID, targetGroup, targetSubtype, cellSize = 1 ) plotOriginalLabelSpatial(spe, cellTypeTree, imageID, targetGroup, cellSize = 1)
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. Optional for
|
confList |
Confidence list from |
imageID |
The image to plot. An error is raised if it is not an image in the data. |
groupA, groupB, targetGroup
|
Group names. An error is raised for a group that has no cells in the data. |
subtypeA, subtypeB, targetSubtype
|
Cell types within the groups, which
must have confidence scores in |
encoding |
How to show the confidence scores: |
cellSize |
Size of the highlighted cells, the ones drawn in colour. The grey background cells always have size 0.7. |
A ggplot object.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) plotHardSpatialPair(lungSubset, "VUHD113", "Mast", "Proliferating FBs", lungCellTypeTree) plotWeightedSpatial(lungSubset, lungCellTypeTree, lungConfList, "VUHD113", "Endothelial lineage", "Arteriole") plotOriginalLabelSpatial(lungSubset, lungCellTypeTree, "VUHD113", "Endothelial lineage") if (requireNamespace("ggnewscale", quietly = TRUE)) { plotWeightedSpatialPair(lungSubset, lungCellTypeTree, lungConfList, "VUHD113", "Granulocytes", "Mast", "Fibroblast lineage", "Proliferating FBs") }data(lungSubset) data(lungCellTypeTree) data(lungConfList) plotHardSpatialPair(lungSubset, "VUHD113", "Mast", "Proliferating FBs", lungCellTypeTree) plotWeightedSpatial(lungSubset, lungCellTypeTree, lungConfList, "VUHD113", "Endothelial lineage", "Arteriole") plotOriginalLabelSpatial(lungSubset, lungCellTypeTree, "VUHD113", "Endothelial lineage") if (requireNamespace("ggnewscale", quietly = TRUE)) { plotWeightedSpatialPair(lungSubset, lungCellTypeTree, lungConfList, "VUHD113", "Granulocytes", "Mast", "Fibroblast lineage", "Proliferating FBs") }
Tests, for every pair of leaf cell types and groups, whether the
co-localisation of the two differs between the two conditions of an outcome,
once with the original labels and once with the bootstrap confidences as soft
cell type weights. The co-localisation of each image is the cross-type
L-function, computed by spicyR (spicyR::spicy(method = "image")), and
relative co-localisation is Statial's Kontextual test
(spicyR::kontextualEngine()).
runColocalisationModels( spe, cellTypeTree, confList, outcomeCol, r = 50, subject = NULL, cores = 1, parentOverrides = character(0), autoOverrideParents = TRUE, cellType = "cellType", cellID = "cellID", imageID = "imageID", x = "x", y = "y" )runColocalisationModels( spe, cellTypeTree, confList, outcomeCol, r = 50, subject = NULL, cores = 1, parentOverrides = character(0), autoOverrideParents = TRUE, cellType = "cellType", cellID = "cellID", imageID = "imageID", x = "x", y = "y" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
confList |
Confidence list from |
outcomeCol |
Name of the |
r |
Radius within which cells count as neighbours, in the units of the coordinates; a single positive number. |
subject |
Name of the |
cores |
Number of threads. |
parentOverrides |
Named character vector mapping a |
autoOverrideParents |
Whether to add overrides found by
|
cellType, cellID, imageID
|
Names of the |
x, y
|
Names of the columns holding the cell coordinates. For a
|
Co-localisation of a pair from -> to in an image is the cross-type
L-function: how strongly the from cells are attracted to (positive values)
or avoid (negative values) the to cells within radius r, with 0 meaning no
attraction or repulsion. The area of an image is that of the square around its
cells, and cells near the border are edge corrected. Each pair is then tested
by a linear model of its per-image values on the outcome (the images are the
units); if some subjects have several images, spicyR fits a mixed model with
the subject as a random effect instead.
With weights (see confidenceWeights()), a cell of a bootstrapped group
belongs to each subtype of the group with its bootstrap confidence: each cell
contributes to a label in proportion to its weight, and the density of a label
is its summed weight per unit area. With the original labels (weights of 0
and 1) this is the unweighted L-function.
Relative co-localisation compares the co-localisation of from with to to
that of from with a parent population of to, so that attraction that only
arises because both cell types prefer the same region is not counted. By
default the parent of a to cell type is its own group; parentOverrides and
autoOverrideParents give broader parents. Pairs whose to has no parent
other than itself are not tested.
A label is not paired with itself, nor with a group that contains it.
A list with the tests modelWeighted, modelUnweighted,
modelRelativeWeighted and modelRelativeUnweighted (one row per pair:
estimate, the difference for the second level of the outcome compared with
the first, its se, statistic, p.value and BH-adjusted p.adj, and for
relative co-localisation the parent and side, "attract" or "avoid"),
the per-image values
weighted, unweighted, relativeWeighted and relativeUnweighted
(columns imageID, from, to, colocalisation, and parent for the
relative version), and the spicyR results themselves (spicy, a list of
weighted, unweighted, relativeWeighted and relativeUnweighted), for
spicyR's plotting functions.
data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runColocalisationModels(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(res$modelWeighted)data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runColocalisationModels(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(res$modelWeighted)
Computes per-image proportions of every cell type using original labels
(unweighted) and bootstrap confidences (weighted), and tests each against an
outcome with a linear model. runProportionsRelativeToParentPipeline()
instead expresses each subtype as a proportion of its parent group.
runProportionsPipeline( spe, cellTypeTree, confList, outcomeCol, skipGroups = character(0), subject = NULL, cellType = "cellType", cellID = "cellID", imageID = "imageID" ) runProportionsRelativeToParentPipeline( spe, cellTypeTree, confList, outcomeCol, skipGroups = character(0), subject = NULL, cellType = "cellType", cellID = "cellID", imageID = "imageID" )runProportionsPipeline( spe, cellTypeTree, confList, outcomeCol, skipGroups = character(0), subject = NULL, cellType = "cellType", cellID = "cellID", imageID = "imageID" ) runProportionsRelativeToParentPipeline( spe, cellTypeTree, confList, outcomeCol, skipGroups = character(0), subject = NULL, cellType = "cellType", cellID = "cellID", imageID = "imageID" )
spe |
A |
cellTypeTree |
A cell type tree, see cellTypeTree. |
confList |
Confidence list from |
outcomeCol |
Name of the per-image outcome column in |
skipGroups |
Names of groups of |
subject |
Name of the |
cellType, cellID, imageID
|
Names of the |
In runProportionsPipeline() the unweighted results cover every cell type
and also the whole groups that were bootstrapped. Only the subtypes of those
groups have confidences, so for every other cell type (cell types without a
group, and the group-level proportions) the weighted proportion is the
unweighted one: their labels are not uncertain. The weighted and unweighted
models therefore test the same set of cell types, and their adjusted
p-values are comparable.
The lineage column of the results is the group a subtype belongs to (not
the broad lineage). For cell types without a group and for the group-level
proportions it is the cell type or group itself.
A list with proportions, weighted, unweighted (long
data.frames; only proportions and not weighted/unweighted for
the relative-to-parent version), and modelWeighted and
modelUnweighted (per cell type model results, where estimate is the
difference for the second level of the outcome compared with the first).
data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runProportionsPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(res$modelWeighted) data(lungSubset) data(lungCellTypeTree) data(lungConfList) rel = runProportionsRelativeToParentPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(rel$modelWeighted)data(lungSubset) data(lungCellTypeTree) data(lungConfList) res = runProportionsPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(res$modelWeighted) data(lungSubset) data(lungCellTypeTree) data(lungConfList) rel = runProportionsRelativeToParentPipeline(lungSubset, lungCellTypeTree, lungConfList, outcomeCol = "disease_status", subject = "subject") head(rel$modelWeighted)
Computes the proportion of each image's cells in each niche and tests every niche against a two-level outcome with a Wilcoxon or t-test.
testNicheOutcome( spe, nicheUnweighted, nicheWeighted, outcomeCol, test = c("wilcox", "ttest"), subject = NULL, cellID = "cellID", imageID = "imageID" )testNicheOutcome( spe, nicheUnweighted, nicheWeighted, outcomeCol, test = c("wilcox", "ttest"), subject = NULL, cellID = "cellID", imageID = "imageID" )
spe |
A |
nicheUnweighted, nicheWeighted
|
Named cell-to-niche vectors, as
returned by |
outcomeCol |
Name of the per-image outcome column in |
test |
|
subject |
Name of the |
cellID, imageID
|
Names of the |
The estimate is the difference in the niche proportion for the second
level of the outcome compared with the first (alphabetical order for text,
factor order for factors), for both tests, as in runColocalisationModels(). For
test = "wilcox" this is the Hodges-Lehmann estimate of the shift in
location. Each image is one observation, so every image must come from a
different subject if subject is given.
A list with testUnweighted, testWeighted (one row per niche)
and propUnweighted, propWeighted (per image niche proportions, to
pass to nicheProportionBoxplot()).
data(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) res = testNicheOutcome(lungSubset, niches$nicheUnweighted, niches$nicheWeighted, outcomeCol = "disease_status", subject = "subject") res$testWeighteddata(lungSubset) data(lungCellTypeTree) data(lungConfList) niches = runNicheIdentification(lungSubset, lungCellTypeTree, lungConfList, r = 50, k = 6) res = testNicheOutcome(lungSubset, niches$nicheUnweighted, niches$nicheWeighted, outcomeCol = "disease_status", subject = "subject") res$testWeighted