import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SRC_DIR = ROOT / "src" if str(SRC_DIR) not in sys.path: sys.path.insert(0, str(SRC_DIR)) import renunney.track1_extinction as ext import renunney.track1_reference as ref def _sample_summaries(): return [ ref.GenerationSummary( t=0, N=10, female_fraction=0.5, male_count=5, female_count=5, fecundity=3.0, mean_fitness=0.8, mean_expected_female_productivity=2.4, target_value=0.0, mean_allele_value=0.2, mean_genotype_value=0.2, mean_tracking_gap=0.2, paper_M=0.05, expected_mutations_current_N=0.1, realized_mutation_count=0, realized_mutation_rate_per_allele=0.0, birth_count=6, surviving_offspring_count=4, ne_approx=5.0, extinct=False, ), ref.GenerationSummary( t=1, N=0, female_fraction=0.0, male_count=0, female_count=0, fecundity=0.0, mean_fitness=0.0, mean_expected_female_productivity=0.0, target_value=0.1, mean_allele_value=0.0, mean_genotype_value=0.0, mean_tracking_gap=-0.1, paper_M=0.05, expected_mutations_current_N=0.0, realized_mutation_count=0, realized_mutation_rate_per_allele=0.0, birth_count=0, surviving_offspring_count=0, ne_approx=0.0, extinct=True, ), ] def test_build_extinction_generation_rows_derives_expected_fields(): params = ref.Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20) rows = ext.build_extinction_generation_rows(params, _sample_summaries(), seed=7) assert len(rows) == 2 assert rows[0].M == 0.05 assert rows[0].survival_fraction == 4 / 6 assert rows[0].replacement_deficit == 0.0 assert rows[0].mutation_shortfall == 0.1 assert rows[0].extinction_next_step is True assert rows[1].extinction_occurred is True def test_build_extinction_run_row_summarizes_extinction_and_mutation_streaks(): params = ref.Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20) row = ext.build_extinction_run_row(params, _sample_summaries(), seed=7) assert row.extinction_occurred is True assert row.first_extinction_t == 1 assert row.first_productivity_below_replacement_t == 1 assert row.longest_zero_mutation_streak == 2 assert row.cumulative_expected_mutations == 0.1 assert row.cumulative_realized_mutations == 0 def test_save_jsonl_writes_row_data(tmp_path: Path): params = ref.Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20) row = ext.build_extinction_run_row(params, _sample_summaries(), seed=7) path = tmp_path / "runs.jsonl" ext.save_jsonl([row], path) lines = path.read_text(encoding="utf-8").splitlines() assert len(lines) == 1 parsed = json.loads(lines[0]) assert parsed["seed"] == 7 assert parsed["extinction_occurred"] is True