grassp.tl.competitive_propagation

grassp.tl.competitive_propagation#

competitive_propagation(data, gt_col=None, fix_markers=False, class_balance=True, min_probability=None, plot_optimization=True, inplace=True, obsp_key='connectivities', key_added='competitive_propagation', iterative=False, max_iter=1000, tol=0.001, verbose=True, method='propagation', alpha=0.8, seed_obsm_key=None, seed_categories_uns_key=None, unknown_label='unknown')[source]#

Propagate categorical annotations along the k-NN graph.

For each observation the function inspects its neighbourhood in adata.obsp[obsp_key] (generated by scanpy.pp.neighbors()) and calculates the a weighted probability for each label category.

Parameters:
data AnnData

anndata.AnnData with a populated neighbour graph (distances or connectivities).

gt_col str | None (default: None)

Observation column containing the source annotations to be propagated.

fix_markers bool (default: False)

If True marker probabilities do not get overwritten by the propagated labels.

class_balance bool (default: True)

If True ground truth compartments with a lot of proteins are downweighted proportional to their size to prevent them from dominating the propagated labels.

min_probability float | None (default: None)

If the probability of the most probable label is below this threshold, the label is set to np.nan. If None (default), the threshold is automatically determine by the data. Specifically the threshold is chosen to maximize the F1 score for the given ground truth labels.

plot_optimization bool (default: True)

If True a plot is shown showing the F1 score for different minimum probability thresholds.

obsp_key default: 'connectivities'

Name of the neighbour connectivity graph to use (default "connectivities"). If obsp_key="distances" is passed, a Gaussian RBF affinity W = exp(-d² / (2σ²)) is built on the kNN distance graph (with σ the median nonzero distance) and used as the spreading/propagation operator. The resulting matrix is cached at adata.obsp["W_spreading"] for inspection. This typically gives a narrower effective kernel than UMAP’s fuzzy-union connectivities, which is useful when you want boundary-localized uncertainty in label spreading.

key_added str (default: 'competitive_propagation')

Name of the new column that will hold the propagated annotation (default "competitive_propagation").

iterative bool (default: False)

If True perform multi-step label propagation with hard clamping (in the style of sklearn.semi_supervised.LabelPropagation). At every step the label distribution is propagated along T, row-normalized, then labeled rows are reset to their initial one-hot encoding. Iteration stops when |Y - Y_prev|.sum() < tol or when max_iter is reached. If False (default) only a single propagation step is performed. Ignored when method="spreading" (spreading is always iterative).

max_iter int (default: 1000)

Maximum number of propagation iterations when iterative=True or method="spreading" (default 30).

tol float (default: 0.001)

Convergence tolerance on the L1 change of the label distribution between consecutive iterations (default 1e-3).

verbose bool (default: True)

If True print progress to the console.

method Literal['propagation', 'spreading'] (default: 'propagation')

Either "propagation" (default, Zhu & Ghahramani, 2002) or "spreading" (Zhou et al., 2003). Spreading uses the symmetric normalized operator S = D^{-1/2} W D^{-1/2} and a soft clamp controlled by alpha, which makes it more robust to noisy seeds.

alpha float (default: 0.8)

Soft-clamping parameter for label spreading, in [0, 1). The update rule is F(t+1) = alpha * S @ F(t) + (1 - alpha) * Y_0: small alpha keeps predictions close to the initial seeds, alpha close to 1 lets labeled rows drift. Ignored when method="propagation". Default 0.8 (matches sklearn.semi_supervised.LabelSpreading).

seed_obsm_key str | None (default: None)

If given, seed the propagation with a soft per-observation label distribution stored in data.obsm[seed_obsm_key] (shape (n_obs, n_categories)) instead of a one-hot encoding of gt_col. Use this to propagate enrichment uncertainty produced by enrichment_to_cluster_distribution() / soft_cluster_annotation(). gt_col becomes optional when this is set, and fix_markers is disabled (its one-hot marker test does not apply to soft seeds).

seed_categories_uns_key str | None (default: None)

Name of the data.uns entry holding the ordered list of category names matching the columns of the soft seed matrix. Optional when the seed is a DataFrame, whose own column names are used instead; required when it is a bare ndarray, as written by grassp before labelled obsm matrices were introduced.

unknown_label str | None (default: 'unknown')

Name of the background/unknown category in the soft seed. Observations whose most probable label is this category are reported as unassigned (NaN) in data.obs[key_added] while the full probability matrix (including the unknown column) is kept in obsm. Set to None to keep the unknown label as a regular category. Only used with soft seeds.

inplace bool

Returns:

Modified anndata object with the following new entries: - .obsm[f”{key_added}_probabilities”] containing the propagated probabilities - .obs[f”{key_added}”] containing the propagated labels (most probable label) - .uns[f”{key_added}_colors”] to make sure plotting uses the same colors as the ground truth labels - .obs[f”{key_added}_probability”] containing the probability of the most probable label