mantispy.tl.subpopulation_hits#
- mantispy.tl.subpopulation_hits(adata, cluster_key='leiden', groupby='Metadata_Perturbation', reference='negcon', use_rep=None, min_cells=3, seed=0, key_added='subpopulation_hits', copy=False, *, block=None, n_permutations=1000)[source]#
Test each perturbation against the controls within each cluster.
An effect confined to one cell state is diluted by the other states in a well median. Comparing cells within a cluster avoids that.
- Parameters:
- adata
AnnData Clustered single-cell object.
- cluster_key
str(default:'leiden') obscolumn holding the cluster label.- groupby
str(default:'Metadata_Perturbation') obscolumn holding the perturbation.- reference
str|None(default:'negcon') Which rows are the controls,
"negcon"or the name of a booleanobscolumn.- use_rep
str|None(default:None) Measure in
obsm[use_rep]instead ofX.- min_cells
int(default:3) Skip a (cluster, group) pair with fewer cells than this on either side. A cluster needs twice as many controls, and at least four, since half of them place the centroid and half supply the distances tested against. The reference group’s own row needs four times as many, since it comes from a second split of the held-out half.
- seed
int(default:0) Seed for the split of a cluster’s controls and the permutation null.
- key_added
str(default:'subpopulation_hits') Name for the output table.
- copy
bool(default:False) Return a modified copy instead of mutating in place.
- block
str|Sequence[str] |None(default:None) obscolumn, or sequence of columns, whose groups are the design’s exchangeable unit, normally the well. The permutation null then draws whole wells rather than cells, since cells within a well are not independent replicates (see Notes). LeftNone, it defaults to the physical well on an object stamped cell resolution with replicated wells; it warns and falls back to the analytic KS approximation when no complete well column is present.- n_permutations
int(default:1000) Size of the well-block permutation null. Ignored on the analytic fallback, which has no permutation draw.
- adata
- Return type:
- Returns:
None, or the modified copy. Writesuns["mantispy"][key_added]withcluster,group,n_cells,statistic(KS),pvalueandqvalue.- Raises:
KeyError –
obshas no columncluster_key.
Notes
Each cell is reduced to its Euclidean distance from the control centroid of its own cluster, and a KS test compares the treated cells’ distances with the controls’. This is close to
hit_calling(method="ks"), restricted to comparable cells. A distance is used rather than a single feature so that the test means the same on every dataset.Cells within a well are not independent replicates, so the p-value comes from a well-block permutation: whole wells are drawn for the pseudo-treated side and the KS statistic recomputed, the same unit
hit_calling()resamples. Without a usable well column at cell resolution it warns and falls back to the analytic KS approximation on cell counts, which is anti-conservative for the same reason.A cluster’s controls are split in half, as in
hit_calling(). One half places the centroid and the other supplies the distances tested against, so the null is out of sample. Controls measured against a centroid they defined themselves sit closer to it than any other group can. That bias grows with features per control, which is the shape of real Cell Painting data. On pure noise with few controls and many features, a null drawn from the rows that placed the centroid calls far more pseudo-treatments than the nominal rate at rawp < 0.05, and the split stays near it.The controls carry a perturbation label of their own, so one row of the table is the reference group against itself. That row is computed from the held-out half alone, split once more, at random, so that the cells tested and the cells they are tested against are different cells. It is therefore a draw from the null, rather than a sample compared with part of itself measured against a centre half of it placed. A cluster with too few controls to split twice has no such row.