Channels#

A signature channel is a named family of columns carried through in its declared units, never passed through the corpus rotation. Those units may include a fixed transform such as log1p or clr. The full vocabulary – including the vsig channels – is documented in vdjtools’ channel reference; this page covers mirpy’s and the reason the split exists.

Why a channel is not rotated#

A provenance number that has been mixed with the measurements it was supposed to qualify is no longer provenance. If winsor_frac went through a rotation, the coordinate carrying it would also carry geometry, and a caller could no longer ask “is this row comparable to ours at all?” — which is the only question that column exists to answer.

The split is declared in the registry: raw features are inputs to corpus scaling and rotation; channels pass through separately. Channels include row provenance and masks, and also repertoire measurements retained for direct interpretation, such as embedding diversity.

The rsig channels#

Carried rather than rotated because the head-to-head against the statistics half’s coverage-standardised Hill numbers is the result, not a redundancy.

div – embedding diversity#

Every one of these is a metric-space analogue of a classical index, and each sees something a clonotype-counting index cannot: that two clonotypes are one substitution apart. To a Hill number they are two species, as distinct from each other as from anything else.

All of them come out of the same chunked pass that already computes Phi, so the family costs accumulators rather than a second embedding.

channel

what it is

rsig:div:<L>:rao

Rao quadratic entropy, log1p-stabilised and self-pair corrected. Simpson, with distance.

rsig:div:<L>:q_v / q_j / q_c

The same restricted to the V, J and junction strides of Phi. The strides are literal column offsets, so “how much of this is V-driven” needs no attribution model. The three sum to the total before the per-column log1p transform.

rsig:div:<L>:q_frac_v / q_frac_j / q_frac_c

Each stride’s share of the total dispersion, in clr coordinates – a composition of where the diversity sits.

rsig:div:<L>:evenness

Q(w) / Q(uniform): the clone-size weighting’s effect with the composition held fixed. A ratio of self-pair-corrected dispersions, not a proportion constrained to [0, 1].

rsig:div:<L>:eff_dim

log1p(exp(H(lambda))) over the normalized weighted covariance spectrum – effective dimensionality, interpreted as the number of independent directions of receptor space occupied. A thousand clones inside one convergent cluster occupy few; a thousand unrelated clones occupy many.

rsig:div:<L>:eff_dim_pr

log1p((sum lambda)^2 / sum lambda^2), the order-2 effective dimensionality, led by the dominant directions.

rsig:div:<L>:q_top / q_singleton

log1p of self-pair-corrected Rao inside a clone-size compartment, weights renormalised within it – the diversity of the top-clone or singleton compartment rather than its share, which band already carries.

rsig:div:<L>:q_ratio_top

Ratio of the untransformed compartment Rao values; not the ratio of their emitted log1p values.

disp – displacements between compartments#

A displacement is a quantity no index has: where a compartment sits rather than how large it is.

channel

what it is

rsig:disp:<L>:top_singleton / cos_top_singleton

log1p of the Euclidean distance and the untransformed cosine between the top-clone and singleton centroids.

rsig:disp:IGH:IgG_IgM / IgA_IgM and their cosines

log1p distances and untransformed cosines between isotype compartments – class-switch geometry.

rsig:disp:<L>:norm

log1p(||Phi||).

Warning

Only ever within one locus. Each locus has its own panel of K prototype receptors, so Phi(TRA) and Phi(TRB) are vectors in different spaces and a distance between them is arithmetic without a meaning. Cross-locus comparison belongs in vsig:pair, a ratio of scalars.

mask – which loci this donor resolved#

channel

loci

what it says

rsig:mask:<locus>:present

7

Whether the locus had any usable clonotype at all.

rsig:mask:<locus>:estimable

7

Whether it cleared min_clonotypes. present=1 with estimable=0 means the locus is there and too shallow for its div/disp family to be a measurement.

Important

mask is a pass-through channel block usable as model features, not merely diagnostics – which loci a donor resolved is biology. See the vdjtools page for the measurement: adding the presence flags moved an external ROC-AUC from 0.6243 to 0.6676.

It is also what makes holing the diversity family safe. Rao of a one-clonotype locus is arithmetically 0.0 and is not a diversity measurement – it is the presence mask in different units, and read as a measurement it sat about 29 robust deviations below the 1st percentile of the real values. A Cox screen over 261 channels returned a hazard ratio of 739 per standard deviation at p = 7e-155 for rsig:div:IGH:rao on 838 patients – off a single extreme point, against a Spearman correlation with survival of -0.023. The family is now a hole below the floor, and mask says why.

The geometry is still computed there: Phi is perfectly measurable from three clonotypes even when its dispersion is not.

qc#

channel

loci

what it says

rsig:qc:-:winsor_frac

–

What fraction of this row’s finite values the corpus’s bounds clamped. A value near 1.0 means this sample does not belong to this corpus – not that it is unusual.

depth is not a channel#

rsig:depth:<locus>:n_eff and :mass are raw features and go through the rotation, even though they look like provenance. They are measurements of the repertoire: n_eff is a Hill number of the clone weights the geometry actually uses, and mass is the share of the repertoire ever drawn. The compartment shares are depth-fragile on purpose and these two are the covariates that make that adjustable, so a rotation that could not see them would be worse, not cleaner.

Reading a row#

from mir.signature import Corpus, rsig

corpus = Corpus.load("naive_rsig.npz")
row = rsig(sample, corpus, named=("depth",))

row["rsig:qc:-:winsor_frac"]    # did the corpus's bounds edit this sample?
row["rsig:div:TRB:rao"]         # sequence-aware diversity, in its own units
row["rsig:depth:TRB:n_eff"]     # log10 effective clonotype count under the chosen weights

Declaring a channel#

rsig registers its groups and channels into vdjtools’ registry at import of mir.signature.signature, with register_raw() and register_channel(). The contract lives in vdjtools because mirpy depends on vdjtools and not the reverse; nothing in vdjtools imports mir.

from mir.signature import channel_columns, channels, raw_groups, support_of

[g.name for g in raw_groups("rsig")]   # phiv, phij, phic, depth, band, band_igh
[c.name for c in channels("rsig")]     # ['div', 'disp', 'disp', 'mask', 'qc']
support_of("rsig:phiv:TRB:P001")       # 'nonneg' -- a mean of distances
support_of("rsig:band:TRB:top")        # 'real'   -- a clr coordinate

Note

A channel is pass-through, so adding one does not invalidate a fitted corpus. The rotation is indexed by raw_columns() and nothing else, and apply() fills every registered channel from the sample. The div, disp and mask families are therefore emitted by every artifact already published, with no refit and no new download.