@@ -195,6 +195,106 @@ def test_mean_traceback_size(self):
195195 assert isinstance (tb , float )
196196 assert tb >= 0
197197
198+ def test_init_bad_recombination (self ):
199+ ts , mi , _ = make_matcher_indexes_and_matcher ()
200+ mismatch = np .array ([0.0 ])
201+ with pytest .raises (ValueError ):
202+ _tsinfer .AncestorMatcher (mi , recombination = "bad" , mismatch = mismatch )
203+ with pytest .raises (ValueError , match = "Size of recombination" ):
204+ _tsinfer .AncestorMatcher (
205+ mi , recombination = np .array ([1e-9 , 1e-9 ]), mismatch = mismatch
206+ )
207+
208+ def test_init_bad_mismatch (self ):
209+ ts , mi , _ = make_matcher_indexes_and_matcher ()
210+ recombination = np .array ([1e-9 ])
211+ with pytest .raises (ValueError ):
212+ _tsinfer .AncestorMatcher (mi , recombination = recombination , mismatch = "bad" )
213+ with pytest .raises (ValueError , match = "Size of mismatch" ):
214+ _tsinfer .AncestorMatcher (
215+ mi , recombination = recombination , mismatch = np .array ([0.0 , 0.0 ])
216+ )
217+
218+ def test_init_extended_checks (self ):
219+ ts , mi , _ = make_matcher_indexes_and_matcher ()
220+ am = _tsinfer .AncestorMatcher (
221+ mi ,
222+ recombination = np .array ([1e-9 ]),
223+ mismatch = np .array ([0.0 ]),
224+ extended_checks = True ,
225+ )
226+ assert am is not None
227+
228+ def test_init_weight_by_n_false (self ):
229+ ts , mi , _ = make_matcher_indexes_and_matcher ()
230+ am = _tsinfer .AncestorMatcher (
231+ mi ,
232+ recombination = np .array ([1e-9 ]),
233+ mismatch = np .array ([0.0 ]),
234+ weight_by_n = False ,
235+ )
236+ assert am is not None
237+
238+ def test_find_path_bad_haplotype (self ):
239+ ts , _ , am = make_matcher_indexes_and_matcher ()
240+ with pytest .raises (ValueError ):
241+ am .find_path ("not an array" , 0 , ts .num_sites )
242+ with pytest .raises (ValueError , match = "Dim != 1" ):
243+ am .find_path (np .zeros ((1 , 1 ), dtype = np .int8 ), 0 , ts .num_sites )
244+ with pytest .raises (ValueError , match = "Incorrect size" ):
245+ am .find_path (np .zeros (100 , dtype = np .int8 ), 0 , ts .num_sites )
246+
247+ def test_find_path_returns_values (self ):
248+ ts , _ , am = make_matcher_indexes_and_matcher ()
249+ h = np .zeros (ts .num_sites , dtype = np .int8 )
250+ result = am .find_path (h , 0 , ts .num_sites )
251+ assert len (result ) == 5
252+ num_edges , left , right , parent , match = result
253+ assert isinstance (num_edges , int )
254+ assert left .dtype == np .uint32
255+ assert right .dtype == np .uint32
256+ assert parent .dtype == np .int32
257+ assert match .dtype == np .int8
258+
259+ def test_find_path_match_impossible (self ):
260+ # mu=0 with a mismatching haplotype makes p_e=0 for all nodes,
261+ # triggering TSI_ERR_MATCH_IMPOSSIBLE_EXTREME_MUTATION_PROBA.
262+ # Build a tree sequence where all nodes carry allele 0 at a site
263+ # (no mutations), then query h=[1] so nothing matches.
264+ tables = tskit .Tree .generate_balanced (4 ).tree_sequence .dump_tables ()
265+ tables .sequence_length = 2
266+ tables .edges .right = np .full (len (tables .edges ), 2 , dtype = np .float64 )
267+ tables .sites .add_row (position = 1 , ancestral_state = "A" )
268+ # No mutations: all nodes carry allele 0
269+ ts = tables .tree_sequence ()
270+ ts = matching .add_vestigial_root (ts )
271+ ll_tables = _tsinfer .LightweightTableCollection (ts .sequence_length )
272+ ll_tables .fromdict (ts .dump_tables ().asdict ())
273+ mi = _tsinfer .MatcherIndexes (ll_tables )
274+ am = _tsinfer .AncestorMatcher (
275+ mi ,
276+ recombination = np .array ([1e-9 ]),
277+ mismatch = np .array ([0.0 ]),
278+ )
279+ h = np .array ([1 ], dtype = np .int8 )
280+ with pytest .raises (_tsinfer .MatchImpossible ):
281+ am .find_path (h , 0 , ts .num_sites )
282+
283+ def test_get_traceback (self ):
284+ ts , _ , am = make_matcher_indexes_and_matcher ()
285+ h = np .zeros (ts .num_sites , dtype = np .int8 )
286+ am .find_path (h , 0 , ts .num_sites )
287+ for site in range (ts .num_sites ):
288+ tb = am .get_traceback (site )
289+ assert isinstance (tb , dict )
290+
291+ def test_get_traceback_bad_site (self ):
292+ ts , _ , am = make_matcher_indexes_and_matcher ()
293+ h = np .zeros (ts .num_sites , dtype = np .int8 )
294+ am .find_path (h , 0 , ts .num_sites )
295+ with pytest .raises (ValueError , match = "site out of range" ):
296+ am .get_traceback (ts .num_sites )
297+
198298
199299class TestMatcherIndexes :
200300 def test_single_tree (self ):
@@ -204,6 +304,14 @@ def test_single_tree(self):
204304 ll_tables .fromdict (tables .asdict ())
205305 _ = _tsinfer .MatcherIndexes (ll_tables )
206306
307+ def test_num_alleles (self ):
308+ ts , mi , _ = make_matcher_indexes_and_matcher ()
309+ num_alleles = np .array ([2 ] * ts .num_sites , dtype = np .uint64 )
310+ ll_tables = _tsinfer .LightweightTableCollection (ts .sequence_length )
311+ ll_tables .fromdict (ts .dump_tables ().asdict ())
312+ mi = _tsinfer .MatcherIndexes (ll_tables , num_alleles = num_alleles )
313+ assert mi is not None
314+
207315 def test_print_state (self , tmpdir ):
208316 ts = tskit .Tree .generate_balanced (4 ).tree_sequence
209317 tables = ts .dump_tables ()
@@ -220,3 +328,12 @@ def test_print_state(self, tmpdir):
220328 output = f .read ()
221329 assert len (output ) > 0
222330 assert "indexes" in output
331+
332+ def test_print_state_bad_file (self ):
333+ ts = tskit .Tree .generate_balanced (4 ).tree_sequence
334+ tables = ts .dump_tables ()
335+ ll_tables = _tsinfer .LightweightTableCollection (tables .sequence_length )
336+ ll_tables .fromdict (tables .asdict ())
337+ mi = _tsinfer .MatcherIndexes (ll_tables )
338+ with pytest .raises (TypeError ):
339+ mi .print_state ("not a file" )
0 commit comments