Skip to content

Link three more SGDP genomes on a recorded genotype check, and report whose files reach no donor (#718) - #739

Merged
NoopDog merged 6 commits into
mainfrom
noopdog/718-sgdp-genotype-checks
Oct 23, 2026
Merged

NoopDog merged 6 commits into
mainfrom
noopdog/718-sgdp-genotype-checks

Conversation

@NoopDog

@NoopDog NoopDog commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Closes #718

What changed

  • Three more SGDP genomes reach a donor, on a recorded genotype check.
    • src/meta_disco/sources/sgdp_genotype_checks.yaml records a bcftools gtcheck run. Each sample's chr22 gVCF was compared with every genome of SGDP's public release (278) and HGDP's (929). For each sample the record holds the genome it matched (or none) and the two best scores per release.
    • make import-sgdp-entities links a sample when either check passes:
      • sex check: SGDP's sex agrees with T2T_CHRY's karyotype (275 samples, as before);
      • genotype check: the record matches the sample to the genome its tables pair it with (3 more).
    • A recorded non-match leaves a sample out whatever its sex says.
    • The three:
      • S_Palestinian-2 becomes donor hgdp:HGDP00725, sex M;
      • S_Norwegian-1 and B_Australian-3 get donors with no sex.
    • S_Naxi-2 stays out: it isn't in SGDP's file, and it matches no public genome.
  • Both checks are declared rules: code_rules.IDENTITY_CHECKS (sgdp_sex_agrees, sgdp_genotype_matches). They are listed in the rules report.
  • Every import says why it linked or left out each sample, in outcomes.json beside its evidence: the pairing, each check's finding, and which checks confirmed it. No evidence reader takes the file as evidence (it isn't .ndjson).
  • Reconcile reports donor reach:
    • entities.donor_reach, per dataset: files with samples, files whose every sample has a donor, files with one sample and no donor, and files with several samples where some have no donor;
    • entities.samples.no_donor: each sample a file names that has no donor, with what its importer recorded.
  • Table cells are read more carefully:
    • A blank cell disagrees with nothing.
    • Two tables naming different genomes are tables_disagree.
    • Two stated karyotypes make the sex check karyotypes_disagree, which the genotype record can still confirm.
  • SGDP's U sex gets an authored value-map row, phenotypic_sex.sgdp_u (declares: {}: reviewed, and no claim).
  • Docs:
    • docs/studies/sgdp-genome-identity.md, a new note: the chain from file to person, what T2T_CHRY holds, both checks, the method, the controls, and each genome's verdict.
    • Contract 2.10 amended, plus CLAUDE.md and the Makefile.

Why

#559 linked a sample only where SGDP's sex and T2T_CHRY's karyotype agree, because the sample-to-genome pairing rests on one table. Four genomes failed that check. A genotype comparison answers the real question — is this the same person? — directly. Three of the four are, and one isn't anyone in the public releases.

For S_Palestinian-2, the content sides with SGDP's M: the sample's own chrX shows one X. That makes T2T_CHRY's XX the odd one out. I think it may be a male cell line that lost its Y; that isn't checked.

Assumptions I made

  • The genotype record is a measurement, not a source. It adds no value to a record: it confirms or vetoes the pairing T2T_CHRY's tables state. The importer reads only sgdp_id and matched. The scores are there for a person, and only the record's keys are checked, not their values.
  • The record is tied to the catalog it measured (anvil15). The import refuses another catalog until a person confirms the record still holds there. SGDP genotype record: pin the measured gVCFs by md5 instead of the catalog #737 would replace this with pinning each measured gVCF by md5.
  • The measurement isn't re-runnable from the repo yet. The note's §4 and §6 give the exact steps. Re-runnable genotype check for the SGDP record (gtcheck, optionally a genome-wide panel) #738 adds a target that re-measures the record and fails on any difference.
  • gtcheck can't read a gVCF directly (its ALTs carry <NON_REF>). So each sample is written as plain genotypes at the reference's sites, with reference blocks read as 0/0, before scoring.
  • Several importers may write outcomes for one dataset. Reconcile keeps one per source per sample, so a second importer is never refused.
  • The two U donors get no sex.

How to verify

Definition of done from #718:

  1. Read the note: docs/studies/sgdp-genome-identity.md §4–§5. You should see gtcheck mismatches:
    • the same person differs at 0–1 of about 25,000 HGDP sites and 33–60 of about 30,800 SGDP sites;
    • every other genome differs at 1.98% of sites or more;
    • S_Naxi-2's best match is 2.6% (S_Naxi-3), so it has none.
  2. Import: make import-sgdp-entities ARGS="--entity-root /tmp/718_e" (network; or omit ARGS to write the shared root). It should print:
    linked: 278
      confirmed by sgdp_sex_agrees: 275
      confirmed by sgdp_genotype_matches: 3
    left out: 1
      simons_data_sample_273 (S_Naxi-2): not_in_sgdp_file, sex not_checked, genotype no_match
    
    The generation folder holds outcomes.json with one entry per sample.
  3. Reconcile with that evidence (make reconcile, or scripts/reconcile.py --run <copy of a run> --entity-root <root holding anvil, anvil_published and the new sgdp>). In reconciled/reconcile_report.json:
    • entities.donor_reach.ANVIL_T2T_CHRY.one_sample_without_donor is 118 (was 448), S_Naxi-2's single-sample files;
    • several_samples_some_without_donor is 62,310: the joint-called files and the SGDP workspace tars, all of which name S_Naxi-2;
    • entities.samples.no_donor.ANVIL_T2T_CHRY lists simons_data_sample_273 with its outcome;
    • donors.ndjson.gz gains hgdp:HGDP00725, sgdp:S_Norwegian-1 and sgdp:B_Australian-3;
    • every file artifact is identical to the same run reconciled on main.
  4. make rules-report lists sgdp_sex_agrees and sgdp_genotype_matches under the sample and donor rules.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
🐦 Built with cc-claude-tools

NoopDog and others added 2 commits October 22, 2026 21:07
… whose files reach no donor (#718)

The SGDP importer linked a sample to its donor only where SGDP's sex and
T2T_CHRY's karyotype agree, leaving four genomes out. A genotype search
(each sample's chr22 gVCF against every genome of SGDP's and HGDP's public
releases) confirms three pairings and finds none for S_Naxi-2.

- sources/sgdp_genotype_checks.yaml records the measurement; the importer
  links a sample its sex check cannot confirm where the record matches it
  to the genome its tables pair it with, and a recorded non-match leaves a
  sample out. Both checks are declared in code_rules.IDENTITY_CHECKS.
- Each import writes every sample's checks to outcomes.json beside its
  evidence, which no evidence reader takes as evidence.
- Reconcile reports, per dataset, whether each file's samples all reach a
  donor (entities.donor_reach) and lists each sample without one with the
  checks its import recorded (entities.samples.no_donor).
- docs/studies/sgdp-genome-identity.md records the chain, the checks, the
  method and each genome's verdict; contract 2.10 amended.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
…the checks, U reviewed (#718)

- The genotype record's scores are bcftools gtcheck mismatch counts per
  reference (#738 makes them re-runnable); the note gives the method.
- A blank table cell disagrees with no other: tables naming two genomes
  are tables_disagree, none no_sgdp_id; two stated karyotypes make the
  sex check karyotypes_disagree, which a genotype record still confirms.
- The pairing is its own field, apart from what each check found.
- The record stays tied to its catalog (#737 would pin files by md5).
- SGDP's U is authored as "reviewed, no claim" (declares nothing).
- outcomes.json names its source, one outcome per source per sample;
  a row naming no sample or its own source is refused when written.
- Files per sample list are counted by the samples report; each list's
  members are parsed once; the record loads through map_document.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
Co-authored-by: cc-claude-tools <cc-claude-tools@clevercanary.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 05:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Missing-donor diagnostics omit sample identifiers when no importer outcome exists, leaving affected samples counted but unidentified.

1 open issue
What changed in this PR

Extends SGDP donor linking to accept recorded genotype matches and adds donor-reach reporting to reconciliation, addressing #718.

Changes:

  • Adds genotype-based identity checks and per-sample import outcomes.
  • Reports file-level donor reach and missing-donor diagnostics.
  • Updates rule reporting, tests, and identity-check documentation.
File Description
tests/​test_sgdp_entities.py Tests genotype checks, outcomes, and donor reach.
tests/​test_entities.py Tests donor-reach counts and diagnostics.
tests/​test_code_rules.py Validates identity-check declarations.
src/​meta_disco/​sources/​sgdp_genotype_checks.yaml Records four samples’ genotype verdicts.
src/​meta_disco/​sgdp_entities.py Applies identity checks and writes outcomes.
src/​meta_disco/​rules/​value_map.yaml Treats SGDP’s unknown sex as reviewed without a claim.
src/​meta_disco/​reconcile.py Passes file counts into entity reconciliation.
src/​meta_disco/​reconcile_samples.py Counts files by dataset and sample list.
src/​meta_disco/​reconcile_entities.py Builds donor-reach and missing-donor reports.
src/​meta_disco/​entity_evidence.py Reads and writes outcome sidecars.
src/​meta_disco/​code_rules.py Declares sex and genotype identity checks.
scripts/​generate_rules_report.py Includes identity checks in rule reports.
Makefile Updates SGDP import help and comments.
docs/​studies/​sgdp-genome-identity.md Documents identity evidence, methods, and verdicts.
docs/​claims-contract.md Updates linking and reporting requirements.
CLAUDE.md Updates SGDP architecture guidance.

Review effort: Balanced

Comment thread src/meta_disco/reconcile_entities.py Outdated
…mporter gave some (#718)

Copilot: no_donor counted a sample no importer spoke of but did not name
it, short of what contract 2.10 and the plan say. Each dataset's entry is
now the list of those samples.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
Co-authored-by: cc-claude-tools <cc-claude-tools@clevercanary.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 05:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The new donor links depend on manually recorded genotype measurements that require domain-expert validation and are not yet reproducible through repository tooling.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

NoopDog and others added 2 commits October 22, 2026 22:34
…es; kill surviving mutations (#718)

- outcome() raises where the tables name two genomes and the record's is
  neither, as its docstring said.
- A record's sample key must be a non-empty string.
- Docstrings and notes say what confirmed_by, no_donor and the record's
  header actually cover.
- Tests: files counted per file not per list; a recorded match for a genome
  SGDP's file lacks links nothing; a record entry for a sample naming no
  genome, or two genomes neither its own, is refused; an empty sgdp_id is
  refused; a sample whose sources name two donors reaches none.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
Co-authored-by: cc-claude-tools <cc-claude-tools@clevercanary.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
Co-authored-by: cc-claude-tools <cc-claude-tools@clevercanary.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 05:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The additional donor links rely on manually recorded genotype measurements that need domain-expert validation, with reproducible measurement tooling deferred to #738.

No open issues 🎉

Review effort: Balanced

…with SGDP generation 20261023T054318Z (#718)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VF7tbFa5ZTmYWZ6JWKiBBS
Co-authored-by: cc-claude-tools <cc-claude-tools@clevercanary.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The donor identity changes rely on manually recorded genotype measurements that need human validation, with repository-based remeasurement deferred to #738.

No open issues 🎉

Review effort: Balanced

@NoopDog
NoopDog merged commit b01ec3f into main Oct 23, 2026
2 checks passed
@NoopDog
NoopDog deleted the noopdog/718-sgdp-genotype-checks branch October 23, 2026 05:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Four SGDP genomes left without a donor by #559's sex check: S_Palestinian-2, S_Naxi-2, S_Norwegian-1, B_Australian-3

2 participants