You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
and, when the split runs, invents the label "CAS2" for the second subcluster.
Why this is a problem. The ancestry label vocabulary is user-supplied — it
comes from the --ref-labels TSV through an unconstrained LabelEncoder, or
from a pickled model's encoder. Hardcoding a label is the one thing this code is
otherwise careful not to do; CLAUDE.md calls it out by name, and it was the
second defect behind the old --amr-het flag (label == "AMR", round 11).
What it costs today. The special-casing exists because CAS is bimodal in
the GP2 reference panel. On any other panel:
a panel with no CAS gets no subclustering, which is correct by accident —
the len(cas_train) > 0 guard makes it a no-op rather than a crash (that
guard is what fixed Ancestry prediction with clinical exome #202);
a panel whose bimodal group is called something else gets no subclustering at
all, silently, with no warning that the treatment its data needs was skipped;
a panel that happens to use CAS for an unrelated group gets it split in two
for no reason.
So it is not currently a live bug — it is a correctness hazard that produces
quiet, panel-dependent behaviour.
Possible shapes for a fix, roughly in increasing order of ambition:
Move the label out of the code and into AdmixedConfig (it already owns n_clusters_cas), so a panel can name its own bimodal group — or name none.
Warn when the configured label is absent from the training panel, so the
silent no-op becomes visible.
Detect bimodality rather than declaring it, which removes the need for any
label at all.
Found while triaging #202. The missing test for the guard is #294.
AncestryModel._predict_admixedspecial-cases the literal label"CAS"(
genotools/ancestry/model.py:684):and, when the split runs, invents the label
"CAS2"for the second subcluster.Why this is a problem. The ancestry label vocabulary is user-supplied — it
comes from the
--ref-labelsTSV through an unconstrainedLabelEncoder, orfrom a pickled model's encoder. Hardcoding a label is the one thing this code is
otherwise careful not to do;
CLAUDE.mdcalls it out by name, and it was thesecond defect behind the old
--amr-hetflag (label == "AMR", round 11).What it costs today. The special-casing exists because
CASis bimodal inthe GP2 reference panel. On any other panel:
CASgets no subclustering, which is correct by accident —the
len(cas_train) > 0guard makes it a no-op rather than a crash (thatguard is what fixed Ancestry prediction with clinical exome #202);
all, silently, with no warning that the treatment its data needs was skipped;
CASfor an unrelated group gets it split in twofor no reason.
So it is not currently a live bug — it is a correctness hazard that produces
quiet, panel-dependent behaviour.
Possible shapes for a fix, roughly in increasing order of ambition:
AdmixedConfig(it already ownsn_clusters_cas), so a panel can name its own bimodal group — or name none.silent no-op becomes visible.
label at all.
Found while triaging #202. The missing test for the guard is #294.