Skip to content

Commit d91bfc5

Browse files
GertjanBisschopmergify[bot]
authored andcommitted
extending tests record unary nodes
1 parent 6819af7 commit d91bfc5

3 files changed

Lines changed: 227 additions & 8 deletions

File tree

tests/test_ancestry.py

Lines changed: 159 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,16 @@ def test_gene_conversion_n100(self):
229229

230230

231231
class TestStoreUnary:
232-
def test_recombination_n25(self):
233-
ts = msprime.sim_ancestry(
234-
samples=25,
235-
sequence_length=100,
236-
recombination_rate=1,
237-
record_unary=True,
238-
)
239-
self.verify_store_unary(ts)
232+
"""
233+
Tests for recording unary nodes.
234+
"""
240235

241236
def verify_store_unary(self, ts):
237+
self.verify_min_max_children(ts)
238+
tss = ts.simplify()
239+
self.verify_simple_stats(ts, tss)
240+
241+
def verify_min_max_children(self, ts):
242242
min_children = np.zeros(ts.num_nodes, dtype=int)
243243
max_children = np.zeros_like(min_children)
244244

@@ -257,6 +257,157 @@ def verify_store_unary(self, ts):
257257
if minc == 1:
258258
assert maxc >= 2
259259

260+
def verify_simple_stats(self, ts, ts_simplified):
261+
assert ts.num_samples == ts_simplified.num_samples
262+
assert ts.num_nodes == ts_simplified.num_nodes
263+
264+
def test_unary(self):
265+
for n in [25, 50, 100]:
266+
ts = msprime.sim_ancestry(
267+
samples=n,
268+
sequence_length=100,
269+
recombination_rate=0.1,
270+
record_unary=True,
271+
)
272+
self.verify_store_unary(ts)
273+
274+
def test_unary_smc(self):
275+
for n in [25, 50, 100]:
276+
ts = msprime.sim_ancestry(
277+
samples=n,
278+
sequence_length=100,
279+
recombination_rate=0.1,
280+
record_unary=True,
281+
model="smc",
282+
)
283+
self.verify_store_unary(ts)
284+
285+
def test_unary_smc_prime(self):
286+
for n in [25, 50, 100]:
287+
ts = msprime.sim_ancestry(
288+
samples=n,
289+
sequence_length=100,
290+
recombination_rate=0.1,
291+
record_unary=True,
292+
model="smc_prime",
293+
)
294+
self.verify_store_unary(ts)
295+
296+
def test_unary_sweep_coalescence(self):
297+
N = 1e6
298+
model = msprime.SweepGenicSelection(
299+
position=0.5,
300+
start_frequency=1.0 / (2 * N),
301+
end_frequency=1.0 - (1.0 / (2 * N)),
302+
s=100,
303+
dt=1e-6,
304+
)
305+
ts = msprime.sim_ancestry(
306+
10,
307+
recombination_rate=1e-4,
308+
model=[model, "hudson"],
309+
population_size=N,
310+
sequence_length=100,
311+
record_unary=True,
312+
random_seed=6974,
313+
)
314+
assert ts.num_trees > 1
315+
assert all(tree.num_roots == 1 for tree in ts.trees())
316+
self.verify_store_unary(ts)
317+
318+
def test_multimerger(self):
319+
demography = msprime.Demography()
320+
demography.add_population(initial_size=10_000)
321+
demography.add_instantaneous_bottleneck(time=0.1, population=0, strength=5)
322+
ts = msprime.sim_ancestry(
323+
samples=20,
324+
sequence_length=100,
325+
recombination_rate=0.1,
326+
record_unary=True,
327+
demography=demography,
328+
)
329+
self.verify_store_unary(ts)
330+
331+
def test_unary_gene_conversion(self):
332+
rate = 100
333+
sim = ancestry._parse_sim_ancestry(
334+
10,
335+
sequence_length=100,
336+
gene_conversion_rate=rate,
337+
gene_conversion_tract_length=5,
338+
record_unary=True,
339+
)
340+
sim.run()
341+
assert sim.num_gene_conversion_events > 1
342+
ts = tskit.TableCollection.fromdict(sim.tables.asdict()).tree_sequence()
343+
self.verify_store_unary(ts)
344+
345+
def test_no_recombination(self):
346+
# no recombination -> no unary nodes
347+
ts = msprime.sim_ancestry(
348+
samples=25,
349+
sequence_length=100,
350+
record_unary=True,
351+
)
352+
tss = ts.simplify()
353+
assert ts.equals(tss, ignore_provenance=True)
354+
355+
def test_predefined_scenario(self):
356+
# initial state
357+
# 1.50┊ 5 6 ┊ 5 7 ┊
358+
# ┊ ┃ ┃ ┊ ┃ ┃ ┊
359+
# 0.70┊ ┃ ┃ ┊ ┃ 4 ┊
360+
# ┊ ┃ ┃ ┊ ┃ ┏┻┓ ┊
361+
# 0.50┊ ┃ 3 ┊ ┃ ┃ ┃ ┊
362+
# ┊ ┃ ┏┻┓ ┊ ┃ ┃ ┃ ┊
363+
# 0.00┊ 0 1 2 ┊ 0 1 2 ┊
364+
# 0 5 10
365+
# completed simulation
366+
# ┊ ┊ 9 ┊
367+
# ┊ ┊ ┏━┻┓ ┊
368+
# ┊ 8 ┊ 8 ┃ ┊
369+
# ┊ ┏━┻┓ ┊ ┃ ┃ ┊
370+
# ┊ 5 6 ┊ 5 7 ┊
371+
# ┊ ┃ ┃ ┊ ┃ ┃ ┊
372+
# ┊ ┃ ┃ ┊ ┃ 4 ┊
373+
# ┊ ┃ ┃ ┊ ┃ ┏┻┓ ┊
374+
# ┊ ┃ 3 ┊ ┃ ┃ ┃ ┊
375+
# ┊ ┃ ┏┻┓ ┊ ┃ ┃ ┃ ┊
376+
# ┊ 0 1 2 ┊ 0 1 2 ┊
377+
# 0 5 10
378+
379+
tables = tskit.TableCollection(sequence_length=10)
380+
tables.time_units = "generations"
381+
tables.nodes.set_columns(
382+
time=np.array([0, 0, 0, 0.5, 0.7, 1.5, 1.5, 1.5]),
383+
flags=np.array([1, 1, 1, 0, 0, 0, 0, 0], dtype="uint32"),
384+
population=np.array([0, 0, 0, 0, 0, 1, 1, 0], dtype="int32"),
385+
)
386+
tables.edges.set_columns(
387+
left=np.array([0, 0, 5, 5, 0, 0, 5]),
388+
right=np.array([5, 5, 10, 10, 10, 5, 10]),
389+
parent=np.array([3, 3, 4, 4, 5, 6, 7], dtype="int32"),
390+
child=np.array([1, 2, 1, 2, 0, 3, 4], dtype="int32"),
391+
)
392+
tables.populations.add_row()
393+
tables.populations.add_row()
394+
demography = msprime.Demography()
395+
demography.add_population(initial_size=100)
396+
demography.add_population(initial_size=100)
397+
demography.add_mass_migration(1e6, source=1, dest=0, proportion=1.0)
398+
with warnings.catch_warnings():
399+
warnings.simplefilter("ignore")
400+
simulator = msprime.ancestry._parse_sim_ancestry(
401+
initial_state=tables, demography=demography, record_unary=True
402+
)
403+
simulator._run_until(event_chunk=1, end_time=math.inf)
404+
new_tables = tskit.TableCollection.fromdict(simulator.tables.asdict())
405+
ts = new_tables.tree_sequence()
406+
tree = ts.first()
407+
left_root = tree.root
408+
tree.next()
409+
assert tree.parent_array[left_root] == tree.root
410+
260411

261412
class TestSimulator:
262413
"""

tests/test_mutations.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,3 +2387,29 @@ def test_time_units(self, time_units):
23872387
tables.time_units = time_units
23882388
ts2 = msprime.sim_mutations(tables.tree_sequence(), rate=1, random_seed=2)
23892389
assert ts2.time_units == time_units
2390+
2391+
2392+
class TestNonStandardTopologies:
2393+
def test_record_unary(self):
2394+
ts = msprime.sim_ancestry(
2395+
20,
2396+
sequence_length=10,
2397+
random_seed=2,
2398+
record_unary=True,
2399+
recombination_rate=1,
2400+
)
2401+
assert ts.num_trees > 1
2402+
mutated = msprime.sim_mutations(ts, 2, random_seed=1234)
2403+
assert mutated.num_mutations > 0
2404+
2405+
def test_full_arg(self):
2406+
ts = msprime.sim_ancestry(
2407+
20,
2408+
sequence_length=10,
2409+
random_seed=2,
2410+
record_full_arg=True,
2411+
recombination_rate=1,
2412+
)
2413+
assert ts.num_trees > 1
2414+
mutated = msprime.sim_mutations(ts, 2, random_seed=1234)
2415+
assert mutated.num_mutations > 0

tests/test_simulate_from.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,3 +1277,45 @@ def test_segments_in_inactive_population(self):
12771277
d.add_population_split(T - 1, derived=[0], ancestral=1)
12781278
with pytest.raises(_msprime.InputError, match="from an inactive"):
12791279
msprime.sim_ancestry(initial_state=ts, demography=d)
1280+
1281+
1282+
class TestNonStandardTopologies:
1283+
def test_record_unary(self):
1284+
ts = msprime.sim_ancestry(
1285+
20, sequence_length=100, random_seed=4, recombination_rate=0.1, end_time=0.5
1286+
)
1287+
assert ts.num_trees > 1
1288+
roots = set()
1289+
for tree in ts.trees():
1290+
for root in tree.roots:
1291+
if tree.num_children(root) == 1:
1292+
roots.add(root)
1293+
rts = msprime.sim_ancestry(
1294+
initial_state=ts,
1295+
random_seed=4,
1296+
recombination_rate=0.1,
1297+
population_size=1,
1298+
record_unary=True,
1299+
)
1300+
assert rts.num_trees - ts.num_trees > 0
1301+
rts_simplified = rts.simplify()
1302+
assert rts.num_nodes == rts_simplified.num_nodes + len(roots)
1303+
1304+
def test_full_arg(self):
1305+
ts = msprime.sim_ancestry(
1306+
20, sequence_length=100, random_seed=2, recombination_rate=0.1, end_time=0.5
1307+
)
1308+
assert ts.num_trees > 1
1309+
rts = msprime.sim_ancestry(
1310+
initial_state=ts,
1311+
random_seed=2,
1312+
recombination_rate=1,
1313+
population_size=1,
1314+
record_full_arg=True,
1315+
)
1316+
assert rts.num_trees - ts.num_trees > 0
1317+
flags = rts.tables.nodes.flags
1318+
re_nodes = np.where(flags == msprime.NODE_IS_RE_EVENT)[0]
1319+
ca_nodes = np.where(flags == msprime.NODE_IS_CA_EVENT)[0]
1320+
assert np.sum(re_nodes) > 0
1321+
assert np.sum(ca_nodes) > 0

0 commit comments

Comments
 (0)