mantispy.metrics.known_relationships

mantispy.metrics.known_relationships#

mantispy.metrics.known_relationships(adata, net, label_key='Metadata_Perturbation', metric='cosine', use_rep=None, percentile=5.0, name=None)#

Share of annotated pairs that land in either tail of the similarity distribution [Celik et al., 2024].

Parameters:
  • adata (AnnData) – One profile per perturbation, normally the output of consensus().

  • net (DataFrame) – The annotation, with a source column naming a set and a target column naming one of its members, as gene_sets() returns it: two perturbations are related when they share a set, which also expresses a mechanism of action shared by several compounds. A pair is counted once whichever way round it appears, and nothing is paired with itself. The reference gene sets — CORUM, hu.MAP, Reactome, SIGNOR, StringDB — are distributed as one pair per row, which becomes this shape with pairs.assign(source=pairs.index.astype(str)).melt(id_vars="source", value_name="target")[["source", "target"]].

  • label_key (str (default: 'Metadata_Perturbation')) – obs column holding the perturbation label, normally a gene symbol. Labels are matched to the annotation exactly, as the reference implementation matches them, so a screen that writes its symbols in another case recalls nothing.

  • metric (str (default: 'cosine')) – Similarity between profiles, "cosine" or "pearson".

  • use_rep (str | None (default: None)) – Measure in obsm[use_rep] instead of X.

  • percentile (float (default: 5.0)) – Size of each tail, in percent, between 0 and 50. The comparison distribution is every pair of profiles, so the tails adapt to how similar the map is overall.

  • name (str | None (default: None)) – What to call this annotation in the metric column, as known_relationships:name. Each source is scored separately, and two rows both called known_relationships would collide when metrics() pivots the table.

Return type:

DataFrame

Returns:

A one-row tidy frame with metric, representation, key and value, so it stacks with the other metrics. value is the recall, between 0 and 1.

Raises:
  • KeyErrorobs has no column label_key.

  • ValueErrorlabel_key repeats a label, so a pair of labels would not be a pair of profiles. Aggregate first with adata = mt.tl.consensus(adata).

  • ValueErrornet lacks source or target, or relates no two perturbations that were both profiled.

  • ValueErrorpercentile is not between 0 and 50, or the sets expand into more pairs than the module’s MAX_PAIRS cap allows.

Notes

Read this against the 2 × percentile baseline, not against 100%. Annotated pairs are noisy — two genes share a complex and still do different things — so published maps recover a minority of them, and the number ranks pipelines against each other rather than standing on its own [Celik et al., 2024].

Which annotation is supplied matters more than any argument here. Broad sets, such as the hallmark programs, call hundreds of genes related and pull the recall toward the baseline; curated complexes are the stricter test. Score each source on its own, under its own name, rather than concatenating them: a pair two sources agree on would otherwise be counted once and a source with more pairs would decide the number.

The comparison distribution contains the annotated pairs themselves, as in the reference implementation. They are a small minority of all pairs in a real screen, and holding them out would score each source against a different distribution.