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 inobsm[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.
- 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 36 controls and 120 features, a null drawn from the rows that placed the centroid called 0.40 of pseudo-treatments at rawp < 0.05, and the split called 0.03.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.