Skip to content

Cohorts: run_cohort — N subjects per run - #8

Merged
MuteJester merged 9 commits into
masterfrom
genotype-cohorts
Jun 17, 2026
Merged

Cohorts: run_cohort — N subjects per run#8
MuteJester merged 9 commits into
masterfrom
genotype-cohorts

Conversation

@MuteJester

Copy link
Copy Markdown
Owner

Summary

Adds Experiment.run_cohort(genotypes, ...) — run N subjects, each with its own diploid Genotype, in one call. It is a Python loop around the existing single-subject genotype path (with_genotypecompilerun_records): each subject is compiled and run independently, records are tagged with subject_id and given a namespaced sequence_id, and the per-subject SimulationResult (with its own refdata) is collected into a new CohortResult. Follow-on #3 of the genotype roadmap.

Python-only — zero engine_rs/ changes. No new engine behavior; orchestration over already-correct per-subject behavior.

What's included

  • Experiment.run_cohort(genotypes, *, n_per_subject=1, seed=0, counts=None, strict=False, expose_provenance=False, validate_records=False, allow_curatable_refdata=None) — up-front validation, deterministic per-subject sub-seeds, clone-per-subject (copy.copy, never mutates the base experiment), per-subject with_metadata stamping.
  • src/GenAIRR/cohort.pyCohortSubjectResult (frozen: subject_id, genotype, result, refdata, seed, count) and CohortResult: derived .subject_ids/.genotypes/.results, .result_for/.refdata_for, independent .records, combined .to_dataframe/.to_csv/.to_fasta (union columns; unique >{sequence_id} FASTA headers), __len__. Per-subject refdata stored explicitly (which SimulationResult does not preserve).
  • Counts: n_per_subject for all, or a parallel counts list for varied repertoire sizes (incl. 0 — subject present with zero records). Mappings/str/bytes rejected.
  • Subject IDs: taken from each genotype, or auto-assigned subject_0..N-1; mixed/duplicate (incl. 1 vs "1") raise. Resolved on snapshots only — caller genotypes never mutated.
  • Docs: new "Cohorts" guide section; removed from Limitations.

Behavior

  • Mutually exclusive with with_genotype, restrict_alleles, recombine(*_allele_weights=...); not combined with receptor_revision/clonal forks (parity with the single-subject genotype path). Reserved metadata keys (subject_id/sequence_id/haplotype) raise.
  • Per-subject refdata preserved → validate_records and novel-allele truth calls correct even when subjects differ.
  • Deterministic: per-subject sub-seeds derived from seed.

Test plan

  • New tests/test_genotype_cohorts.py (21 tests): CohortResult accessors + independence, union/FASTA export, subject-id + counts resolution, happy path, determinism, no-base-mutation (incl. mid-loop failure), counts override/zero, mutual exclusions, cartridge-hash, mixed novel/plain subjects + per-subject refdata, per-subject validate, with_metadata parity + collision guard, empty-export schema, end-to-end.
  • Full Python suite green (2446 passed).
  • No engine_rs/ changes.
  • Two review rounds (spec-compliance + critic, both passes); findings fixed with regression tests.

@MuteJester
MuteJester merged commit dc7d8f0 into master Jun 17, 2026
13 checks passed
@MuteJester
MuteJester deleted the genotype-cohorts branch June 17, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant