@@ -229,16 +229,16 @@ def test_gene_conversion_n100(self):
229229
230230
231231class 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
261412class TestSimulator :
262413 """
0 commit comments