Test for changes in the co-localisation of cell types between conditions
Source:R/spicy_main.R
spicy.Rdspicy() tests, for every ordered pair of cell types from → to, whether the co-localisation of
the two types differs between conditions, or is associated with survival. A pair asks whether to
cells are placed near from cells more than other cells are.
Usage
spicy(
cells,
condition,
subject = NULL,
covariates = NULL,
imageID = "imageID",
cellType = "cellType",
spatialCoords = c("x", "y"),
r = NULL,
from = NULL,
to = NULL,
method = c("cell", "image"),
effect = c("allocation", "count"),
k = NULL,
combine = c("maxT", "davies", "cauchy"),
adjustAbundance = FALSE,
variance = c("cr2", "hartung_knapp"),
ref = NULL,
cores = 1,
tableKey = NULL,
imageInfo = NULL,
...
)Arguments
- cells
A
data.frame,SingleCellExperimentorSpatialExperimentwith one row (column) per cell, or (cell method) the path of a SpatialData or AnnData Zarr store (read with the Rarr package). From a store, the columns are read a block of rows at a time and the coordinates a batch of whole images at a time, so the table is never held in memory; the results are those of the same cells given as adata.frame. Column names then refer to the table'sobs;imageIDdefaults to the table's region key andspatialCoordsto itsobsmarray"spatial". ASpatialDataobject (spatialdataR) read from a store is read from that store in the same way; one built in memory is analysed from its table.- condition
The column of the image-level condition: two groups, or a
survival::Survcolumn for a survival outcome (from a store, a column ofimageInfo).- subject
The column of the patient (unit) of each image. Images of one patient are combined; if omitted, every image is its own patient.
- covariates
Image- or patient-level columns to adjust for (cell method: added to the design of the excess, and the effect of each is reported as
<column>_effectand<column>_p_value; survival: added to the null Cox model).- imageID, cellType, spatialCoords
Column names of the image, cell type and coordinates. For a Zarr store,
spatialCoordsis either twoobscolumns or the name of oneobsmarray (its first two columns).- r
Radius (or radii) of the neighbourhood, in the units of the coordinates. Cell method: one radius (default 50), or several to be combined by
combine. Image method: the radii of the L function (default 20, 50 and 100).- from, to
Cell types to test (all ordered pairs by default).
- method
"cell"(spicyR Cell, the default) or"image"(the original spicyR test).- effect
Cell method:
"allocation"(the default), the extra fraction oftocells with at least onefromcell withinr; or"count", the number of extrafromcells withinrof eachtocell. Withk, "withinr" means among the cell'sknearest neighbours.- k
Cell method: use the
knearest neighbours instead of a radius.- combine
Cell method with several radii:
"maxT"(max-T with the sandwich correlation across radii; up to 6 radii),"davies"(Davies' bound for the same maximum, for many radii) or"cauchy"(Cauchy combination). The max-T p-value is the multivariate normal probability of the largest |z|, computed by the quasi-Monte Carlo method of Genz and Bretz with an absolute error of about 1e-4 (by quadrature for two radii); the same inputs always give the same value.- adjustAbundance
Cell method: adjust the test for the log share of the
fromtype in each image (defaultFALSE). Its effect is reported asabundance_effect. It does not separate morefromcells from more densely packed ones, and it removes real effects when the share tracks the condition.- variance
Cell method:
"cr2"(the default: CR2 on Satterthwaite df) or"hartung_knapp"(the model-based variance, scaled by the Pearson statistic when that exceeds its df and never below CR2, on m - 2 df).- ref
Cell method: the reference level of
condition.- cores
Number of threads (cell method) or cores (image method).
- tableKey
Cell method with a SpatialData store or object: the name of the cell table in
tables/(by default the only table, or the one called"table").- imageInfo
Cell method: a table with one row per image, for
condition,subject,covariatesor a survival outcome that are not columns of the cell table: adata.framewhoseimageIDcolumn, or else its row names, gives the image IDs, or the name of a table of the SpatialData store or object. Every image of the cells needs a row, and every row an image. Asurvival::Survcolumn given asconditionmakes a survival analysis, also from a store.- ...
Arguments of the image method:
sigma,alternateResult,minLambda,weights,weightsByPair,weightFactor,weightZThreshold,window,window.length,edgeCorrect,includeZeroCells,verbose,BPPARAM. SupplyingalternateResultselects the image method.
Value
A SpicyResults object. topPairs(), signifPlot(), spicyBoxPlot() and bind() work
for both methods. For the cell method, $cellResults holds the full table: for the allocation effect,
the pair's side ("attract" or "avoid", which sets the scale of the effect), the effect in each
condition (excess_ref, excess_comp, at the average covariates), the difference
(excess_difference), its standard error, df, p-value and BH-adjusted p-value, the frailty variance, the
between-image variance (tau2_image) and, when the test was adjusted, what for (adjusted_for), the effect
and p-value of each adjustment, and the unadjusted test (unadjusted_difference, unadjusted_p_value, unadjusted_p_adj). $effect
records which effect was estimated.
Details
method = "cell" (the default). In each image, the share of to cells with at least one from
cell within radius r is compared with its exact expectation q if the to cells were a random choice
among the cells that are not from cells. The effect (effect = "allocation", the default) is the
fraction of to cells placed next to (or kept away from) from cells. For a pair that attracts
(more to cells next to from cells than q over all images together) it is (observed share - q) / (1 - q):
if a fraction f of the to cells were moved next to from cells, the effect is f. For a pair that avoids
it is (observed share - q) / q: if a fraction f of the to cells that would have a from cell nearby were
moved away, the effect is -f. Either way it does not depend on how many from cells there are or how
densely they are packed. The side is chosen once per pair from all images, without the conditions, and is
reported in the side column. effect = "count" gives the number of extra from
cells within r of each to cell instead; it also reflects how many from cells surround a to cell
(depth of infiltration), but it grows with how densely the from cells are packed, so a change in
packing alone can appear as a change in co-localisation. Images are combined within patients and
patients within conditions by a frailty GEE with a second random effect for the images of a patient (each image
is weighted by 1 / (its sampling variance + the between-image variance), so one large image cannot outweigh the
patient's other images), and the difference between conditions is tested with a
CR2 cluster-robust variance on Satterthwaite degrees of freedom, with patients (subject) as the
units. The difference is adjusted for any covariates, and, with adjustAbundance = TRUE, for the
log share of the from type in each image; the unadjusted test is then reported alongside
(unadjusted_* columns).
When nearly every cell has a from cell within r (q close to 1), there is little room for attraction and
an attracting pair's images carry little information; a smaller r is more informative.
method = "image" (the original spicyR test). A per-image L-function summary of each pair is
compared between conditions with a weighted linear model, or a mixed model when subject is given
(Canete et al. 2022).
References
Canete NP et al. (2022). spicyR: spatial analysis of in situ cytometry data in R. Bioinformatics 38(11), 3099-3105. doi:10.1093/bioinformatics/btac268
Bell RM, McCaffrey DF (2002). Bias reduction in standard errors for linear regression with multi-stage samples. Survey Methodology 28(2), 169-181.
DerSimonian R, Laird N (1986). Meta-analysis in clinical trials. Controlled Clinical Trials 7(3), 177-188. doi:10.1016/0197-2456(86)90046-2
Pustejovsky JE, Tipton E (2018). Small-sample methods for cluster-robust variance estimation and hypothesis testing in fixed effects models. Journal of Business & Economic Statistics 36(4), 672-683. doi:10.1080/07350015.2016.1247004
Paule RC, Mandel J (1982). Consensus values and weighting factors. Journal of Research of the National Bureau of Standards 87(5), 377-385. doi:10.6028/jres.087.022
Hartung J, Knapp G (2001). A refined method for the meta-analysis of controlled clinical trials with binary outcome. Statistics in Medicine 20(24), 3875-3889. doi:10.1002/sim.1009
Liu Y, Xie J (2020). Cauchy combination test: a powerful test with analytic p-value calculation under arbitrary dependency structures. Journal of the American Statistical Association 115(529), 393-402. doi:10.1080/01621459.2018.1554485
Examples
data("diabetesData")
# spicyR Cell: patients ("case") are the units
# the extra fraction of Th cells, and of beta cells, with a Tc cell within 50 units
res <- spicy(diabetesData, condition = "stage", subject = "case", r = 50,
from = "Tc", to = c("Th", "beta"))
topPairs(res)
#> intercept coefficient p.value adj.pvalue from to
#> Tc__Th 0.272768 0.1023755 0.4489368 0.4489368 Tc Th
res$cellResults
#> from to level side excess_ref
#> Tc__Th__Onset Tc Th Onset attract 0.272768
#> Tc__Th__Long-duration Tc Th Long-duration attract 0.272768
#> excess_difference se df p_value p_adj
#> Tc__Th__Onset 0.1023755 0.1249849 5.153215 0.4489368 0.4489368
#> Tc__Th__Long-duration 0.0398330 0.0857751 5.231229 0.6610582 0.6610582
#> tau2 tau2_image
#> Tc__Th__Onset 0.001709649 0.05857091
#> Tc__Th__Long-duration 0.001709649 0.05857091
# the extra number of Tc cells within 50 units of each Th cell
resCount <- spicy(diabetesData, condition = "stage", subject = "case", r = 50,
from = "Tc", to = "Th", effect = "count")
# the original image-level test
resImage <- spicy(diabetesData, condition = "stage", subject = "case",
from = "Tc", to = "Th", method = "image")
#> Dropping unused levels. Using stage = Non-diabetic as base comparison group. If this is not the desired base group, please convert cells$stage into a factor and change the order of levels(cells$stage) so that the base group is at index 1.
topPairs(resImage)
#> intercept coefficient p.value adj.pvalue from to
#> Tc__Th 1.622671 5.961812 0.6122508 0.6122508 Tc Th