96 lines
3.6 KiB
Python
96 lines
3.6 KiB
Python
import sys
|
|
from pathlib import Path
|
|
|
|
import numpy as np
|
|
|
|
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_reference as ref
|
|
|
|
|
|
def test_zero_mutation_preserves_zero_alleles_in_one_generation():
|
|
params = ref.Track1Parameters(K=5000, N0=2, n=2, u=0.0, R=10.0, T=20)
|
|
state = ref.PopulationState(
|
|
genomes=np.zeros((2, 2, 2), dtype=np.int16),
|
|
sexes=np.array([0, 1], dtype=np.int8),
|
|
)
|
|
next_state, summary = ref.simulate_one_generation(state, params, t=0, rng=np.random.default_rng(1))
|
|
assert summary.mean_allele_value == 0.0
|
|
assert int(next_state.genomes.sum()) == 0
|
|
|
|
|
|
def test_zero_offspring_fitness_prevents_survival(monkeypatch):
|
|
params = ref.Track1Parameters(K=5000, N0=2, n=1, u=0.0, R=10.0, T=20)
|
|
state = ref.PopulationState(
|
|
genomes=np.zeros((2, 2, 1), dtype=np.int16),
|
|
sexes=np.array([0, 1], dtype=np.int8),
|
|
)
|
|
|
|
def fake_fitness(genomes, r, T, t):
|
|
if genomes.shape[0] == 1:
|
|
return np.zeros(1, dtype=float)
|
|
return np.ones(genomes.shape[0], dtype=float)
|
|
|
|
monkeypatch.setattr(ref, "genotype_fitness", fake_fitness)
|
|
monkeypatch.setattr(ref, "female_fecundity", lambda r, N, K: 4.0)
|
|
monkeypatch.setattr(ref, "realize_birth_counts", lambda fecundity, sexes, rng: np.array([3, 0], dtype=np.int32))
|
|
|
|
next_state, _ = ref.simulate_one_generation(state, params, t=0, rng=np.random.default_rng(2))
|
|
assert next_state.size == 0
|
|
|
|
|
|
def test_unit_offspring_fitness_keeps_all_births(monkeypatch):
|
|
params = ref.Track1Parameters(K=5000, N0=2, n=1, u=0.0, R=10.0, T=20)
|
|
state = ref.PopulationState(
|
|
genomes=np.zeros((2, 2, 1), dtype=np.int16),
|
|
sexes=np.array([0, 1], dtype=np.int8),
|
|
)
|
|
|
|
monkeypatch.setattr(ref, "genotype_fitness", lambda genomes, r, T, t: np.ones(genomes.shape[0], dtype=float))
|
|
monkeypatch.setattr(ref, "female_fecundity", lambda r, N, K: 4.0)
|
|
monkeypatch.setattr(ref, "realize_birth_counts", lambda fecundity, sexes, rng: np.array([3, 0], dtype=np.int32))
|
|
|
|
next_state, summary = ref.simulate_one_generation(state, params, t=0, rng=np.random.default_rng(2))
|
|
assert summary.female_count == 1
|
|
assert next_state.size == 3
|
|
|
|
|
|
def test_one_father_is_used_per_female_reproductive_event(monkeypatch):
|
|
params = ref.Track1Parameters(K=5000, N0=3, n=2, u=0.0, R=10.0, T=20)
|
|
state = ref.PopulationState(
|
|
genomes=np.array(
|
|
[
|
|
[[0, 0], [0, 0]],
|
|
[[1, 1], [1, 1]],
|
|
[[2, 2], [2, 2]],
|
|
],
|
|
dtype=np.int16,
|
|
),
|
|
sexes=np.array([0, 1, 1], dtype=np.int8),
|
|
)
|
|
|
|
monkeypatch.setattr(ref, "genotype_fitness", lambda genomes, r, T, t: np.ones(genomes.shape[0], dtype=float))
|
|
monkeypatch.setattr(ref, "female_fecundity", lambda r, N, K: 4.0)
|
|
monkeypatch.setattr(ref, "realize_birth_counts", lambda fecundity, sexes, rng: np.array([3, 0, 0], dtype=np.int32))
|
|
|
|
next_state, _ = ref.simulate_one_generation(state, params, t=0, rng=np.random.default_rng(3))
|
|
paternal_alleles = next_state.genomes[:, 1, :]
|
|
assert next_state.size == 3
|
|
assert np.unique(paternal_alleles).size == 1
|
|
|
|
|
|
def test_absence_of_males_or_females_counts_as_extinction():
|
|
female_only = ref.PopulationState(
|
|
genomes=np.zeros((2, 2, 1), dtype=np.int16),
|
|
sexes=np.array([0, 0], dtype=np.int8),
|
|
)
|
|
male_only = ref.PopulationState(
|
|
genomes=np.zeros((2, 2, 1), dtype=np.int16),
|
|
sexes=np.array([1, 1], dtype=np.int8),
|
|
)
|
|
assert ref.is_extinct(female_only) is True
|
|
assert ref.is_extinct(male_only) is True
|