uchrom.spatial¶
Cells in tissue: neighbour graphs from cell positions (one frame per section / field of view), spatial autocorrelation of per-cell values (Moran’s I, Geary’s C) and tests of spatial variation (SPARK-X) — for 3-D genome features of spatial Hi-C spots or traced cells — with covariates such as the cells’ transcriptomes, to ask what varies in space beyond the cell types.
Neighbour graphs of cells (or spatial Hi-C spots) from their positions in the tissue.
Positions are read with ChromData.cell_positions() (key: the position set, e.g. "default").
Cells in different regions — sections of a spatial Hi-C study, fields of view of a tracing experiment (the
record’s region_col) — are never neighbours: each region is its own coordinate frame. The graph is
cheap to build (a k-d tree per region), so it is computed when needed and not stored on the object.
Methods: "knn" (each cell to its n_neighbors nearest, made symmetric), "radius" (every pair closer
than radius; on a barcode grid in spot units radius=1 gives the 4 and radius=1.5 the 8 adjacent
spots), "delaunay" (the edges of the Delaunay triangulation, 2-D positions).
- class uchrom.spatial.graph.SpatialGraph(cell_ids: ndarray, adjacency: scipy.sparse.csr_matrix, positions: DataFrame, params: dict = <factory>)[source]¶
Bases:
objectA neighbour graph over cells.
- Variables:
cell_ids (ndarray of str) – The cells, in the order of the rows and columns of
adjacency.adjacency (scipy.sparse.csr_matrix (n, n)) – 1 for neighbours (symmetric, zero diagonal).
positions (DataFrame) –
x, y[, z]of the cells (indexcell_id) andregionwhen the position set has regions.params (dict) – How the graph was built.
- adjacency: scipy.sparse.csr_matrix¶
- subset(mask) SpatialGraph[source]¶
The graph restricted to the cells of a boolean mask (edges to removed cells are dropped).
- uchrom.spatial.graph.cell_positions_table(cd, key: str = 'default', *, cells: Iterable | None = None, physical: bool = False) DataFrame[source]¶
The positions of
cells(all cells by default) with finite coordinates:x, y[, z][, region].
- uchrom.spatial.graph.spatial_neighbors(cd, *, key: str = 'default', method: str = 'knn', n_neighbors: int = 6, radius: float | None = None, cells: Iterable | None = None, physical: bool = False) SpatialGraph[source]¶
The neighbour graph of the cells of
cdin tissue space.- Parameters:
cd – A
ChromDatawith cell positions (set_cell_positions()).key – The position set.
method –
"knn","radius"or"delaunay"(module docstring). On a regular barcode grid prefer"radius": the k nearest of a grid are tied.n_neighbors – Of
"knn"and"radius"(in the units of the positions).radius – Of
"knn"and"radius"(in the units of the positions).cells – Only these cells (default: every cell with a position).
physical – Positions in physical units for positions stored in voxels.
- Returns:
Symmetric, no self-loops, no edges between regions.
- Return type:
Global spatial autocorrelation of per-cell values over a neighbour graph: Moran’s I and Geary’s C, with their moments under normality and under randomisation (Cliff & Ord 1981) and permutation p-values, many features at once.
For a feature x on n cells with weights w (transform="r": rows standardised to sum 1), z = x - mean(x),
S0 = sum w_ij, S1 = 1/2 sum (w_ij + w_ji)^2, S2 = sum_i (w_i. + w_.i)^2:
Moran’s I = n / S0 * z’Wz / z’z, E[I] = -1 / (n - 1);
Geary’s C = (n - 1) sum w_ij (x_i - x_j)^2 / (2 S0 z’z), E[C] = 1.
The variances are those of PySAL’s esda (VI_norm / VI_rand, VC_norm / VC_rand); positive
autocorrelation — a spatially variable feature — is I > E[I], C < 1. Cells where a feature is missing (NaN) are
left out of that feature: its weights are those of the graph restricted to the cells with a value, transformed
again.
References
Moran, P. A. P. (1950) Biometrika 37:17-23. Geary, R. C. (1954) The Incorporated Statistician 5:115-145. Cliff, A. D. & Ord, J. K. (1981) Spatial Processes: Models and Applications. Pion.
- uchrom.spatial.autocorr.bh_adjust(p: ndarray) ndarray[source]¶
Benjamini-Hochberg adjusted p-values (NaN kept).
- uchrom.spatial.autocorr.cell_values(cd, features: None | str | Sequence[str] = None, *, values: None | DataFrame | Series = None) DataFrame[source]¶
Per-cell values as a DataFrame indexed by cell id (str), one column per feature.
valuesis used as given (a Series becomes one column); elsefeaturesnames columns ofcd.cells, or one key ofcd.cellm(a 2-D array: columns"<key>[j]").
- uchrom.spatial.autocorr.spatial_autocorr(cd=None, features=None, *, graph: SpatialGraph, values=None, method: str = 'moran', transform: str = 'r', alternative: str = 'greater', n_perms: int = 0, seed: int = 0, min_cells: int = 10) DataFrame[source]¶
Moran’s I or Geary’s C of every feature over
graph.- Parameters:
cd – The per-cell values (
cell_values());cdmay be None withvalues=.features – The per-cell values (
cell_values());cdmay be None withvalues=.values – The per-cell values (
cell_values());cdmay be None withvalues=.graph –
spatial_neighbors()(its cells; values of other cells are ignored).method –
"moran"or"geary".transform –
"r"row-standardised (default, as esda) or"b"binary weights.alternative –
"greater"(positive autocorrelation; default),"less"or"two-sided".n_perms – Permutations for
p_perm(0: none); the cells’ values are shuffled over the graph.min_cells – Features with fewer cells with a value get NaN.
- Returns:
One row per feature:
n(cells with a value),IorC,expected,var_norm,z_norm,p_norm,var_rand,z_rand,p_rand[,p_perm],pval(p_permwith permutations, elsep_rand) andpadj(Benjamini-Hochberg over the features).- Return type:
DataFrame
SPARK-X, the non-parametric covariance test of spatial variation of Zhu, Sun & Zhou (2021), for many features
at once and with covariates (an implementation of the published method, checked against the authors’ R package
SPARK::sparkx; uchrom-reproducibility extended_data_fig2).
For a feature y on n cells, the covariates X (an intercept first) and a coordinate kernel S (n x d), with S_r = (I - H) S the coordinates residualised on X (H the projection on X):
T = n * y’ S_r (S_r’ S_r)^-1 S_r’ y / y’y, lambda = y’(I - H) y / y’y,
and under no spatial pattern T ~ lambda * chi2_d (the R package evaluates the same mixture, whose kernel
eigenvalues are all 1, with Davies’ method at accuracy 1e-4; here the chi-square tail is exact). Eleven
kernels are tested: the coordinates themselves (projection), and, per axis after centring, five Gaussian
(gaus1-gaus5: exp(-c^2 / 2 l^2)) and five cosine (cos1-cos5: cos(2 pi c / l)) transforms with
l the 20 / 40 / 60 / 80 / 100 % quantiles of |c|. The kernel p-values are combined by the Cauchy combination
(ACAT, Liu & Xie 2020), adjusted over the features by Benjamini-Yekutieli as the package does.
Values may be any per-cell number (counts, scores, ratios); a feature’s missing cells (NaN) are left out of its test (the kernels stay those of all cells, residualised on the cells with a value).
References
Zhu, J., Sun, S. & Zhou, X. (2021) SPARK-X: non-parametric modeling enables scalable and robust detection of spatial expression patterns for large spatial transcriptomic studies. Genome Biol. 22:184. Liu, Y. & Xie, J. (2020) Cauchy combination test. J. Am. Stat. Assoc. 115:393-402.
- uchrom.spatial.sparkx.acat(p: ndarray, weights: ndarray | None = None) ndarray[source]¶
Cauchy combination of the p-values in each row of
p(n_features x n_tests), asSPARK::ACAT: a row with a 0 gives 0, else a row with a 1 gives 1; p < 1e-16 use the approximation tan((0.5-p) pi) ~ 1 / (p pi); a statistic above 1e15 gives 1 / (stat pi). Rows with NaN give NaN.
- uchrom.spatial.sparkx.by_adjust(p: ndarray) ndarray[source]¶
Benjamini-Yekutieli adjusted p-values, as R’s
p.adjust(method="BY")(NaN kept, not counted).
- uchrom.spatial.sparkx.coordinate_kernels(coords: ndarray, kernels: str | Sequence[str] = 'mixture') List[Tuple[str, ndarray]][source]¶
The coordinate kernels of SPARK-X:
"mixture"(all eleven),"single"(projection only) or a list of names fromKERNELS.
- uchrom.spatial.sparkx.sparkx(values, coords: ndarray, *, covariates: ndarray | None = None, intercept: bool = True, kernels: str | Sequence[str] = 'mixture', min_cells: int = 10) DataFrame[source]¶
SPARK-X on arrays.
- Parameters:
values – n_cells x n_features (DataFrame: its columns name the features; NaN = missing).
coords – n_cells x d positions.
covariates – n_cells x c covariates the test is adjusted for (cell-type composition, depth, …).
intercept – Add an intercept to the covariates (the package’s test without covariates is the test with an intercept only; give
covariatesan intercept column andintercept=Falseto reproduce the package’s covariate path exactly).kernels –
"mixture","single"or kernel names (coordinate_kernels()).
- Returns:
One row per feature:
n,stat_<kernel>,pval_<kernel>,pval(combined) andpadj(Benjamini-Yekutieli);.attrs["df"]holds the degrees of freedom of each kernel.- Return type:
DataFrame
Which per-cell features vary in space: SPARK-X (default) or Moran’s I on the cells of a ChromData, per
region (section / field of view), optionally adjusted for covariates such as cell-type composition or depth.
A 3-D genome feature that follows the cell types will vary in space wherever the cell types do. Testing with the composition (or the cell type) as covariates asks the second question — does the feature vary beyond what the cells’ identities explain? Both answers are worth reporting; the second is the one that needs space.
- uchrom.spatial.variable.covariate_matrix(cd, covariates, cell_ids: Sequence[str]) DataFrame | None[source]¶
The covariates of
cell_idsas a numeric DataFrame:covariatesis a DataFrame (index = cell ids), or names ofcd.cellscolumns (andcd.cellmkeys: their columns); categorical columns become indicators (the first level dropped).
- uchrom.spatial.variable.spatially_variable(cd, features: None | str | Sequence[str] = None, *, values=None, key: str = 'default', method: str = 'sparkx', covariates=None, cells: Iterable | None = None, regions: Sequence[str] | None = None, graph: SpatialGraph | None = None, graph_kwargs: dict | None = None, kernels='mixture', n_perms: int = 0, physical: bool = False, key_added=UNSET, copy: bool = False)[source]¶
Test every feature for spatial variation, region by region.
- Parameters:
cd – A
ChromDatawith cell positions.features – The per-cell values (
cell_values():cd.cellscolumns, acd.cellmkey, or a DataFrame indexed by cell id).values – The per-cell values (
cell_values():cd.cellscolumns, acd.cellmkey, or a DataFrame indexed by cell id).key – The position set (its
region_colsplits the cells into regions).method –
"sparkx"(sparkx()) or"moran"(spatial_autocorr()ongraph/spatial_neighbors(**graph_kwargs); with covariates, Moran’s I of the residuals of a least-squares fit on them, permutation p-values recommended).covariates – Adjust for these (
covariate_matrix()).cells – Only these cells / regions.
regions – Only these cells / regions.
kernels – Of SPARK-X / Moran’s I.
n_perms – Of SPARK-X / Moran’s I.
- Returns:
region, featurethen the test’s columns (pval,padjper region); stored ascd.results[key_added](default"spatially_variable.<method>"; None: not stored) per the calling convention.- Return type:
DataFrame