@@ -5491,3 +5491,91 @@ def test_error_if_no_schema(self, table_name):
54915491 ts = msprime .simulate (10 )
54925492 with pytest .raises (NotImplementedError ):
54935493 getattr (ts , f"{ table_name } _metadata" )
5494+
5495+
5496+ class TestIndividualNodes :
5497+ def test_basic_individual_nodes (self , tmp_path ):
5498+ # Create a basic tree sequence with two individuals
5499+ tables = tskit .TableCollection (sequence_length = 100 )
5500+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5501+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5502+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5503+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5504+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 1 )
5505+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 1 )
5506+ ts = tables .tree_sequence ()
5507+
5508+ result = ts .individual_nodes ()
5509+ assert result .shape == (2 , 2 )
5510+ assert np .array_equal (result , [[0 , 1 ], [2 , 3 ]])
5511+
5512+ def test_variable_ploidy (self , tmp_path ):
5513+ tables = tskit .TableCollection (sequence_length = 100 )
5514+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" ) # Diploid
5515+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" ) # Haploid
5516+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" ) # Triploid
5517+
5518+ # Diploid individual
5519+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5520+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5521+
5522+ # Haploid individual
5523+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 1 )
5524+
5525+ # Triploid individual
5526+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 2 )
5527+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 2 )
5528+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 2 )
5529+
5530+ ts = tables .tree_sequence ()
5531+
5532+ result = ts .individual_nodes ()
5533+
5534+ assert result .shape == (3 , 3 )
5535+
5536+ expected = np .array (
5537+ [[0 , 1 , - 1 ], [2 , - 1 , - 1 ], [3 , 4 , 5 ]] # Diploid # Haploid # Triploid
5538+ )
5539+ assert np .array_equal (result , expected )
5540+
5541+ def test_no_individuals (self ):
5542+ tables = tskit .TableCollection (sequence_length = 100 )
5543+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 )
5544+ ts = tables .tree_sequence ()
5545+
5546+ with pytest .raises (ValueError , match = "Tree sequence has no individuals" ):
5547+ _ = ts .individual_nodes ()
5548+
5549+ def test_no_samples_with_individuals (self ):
5550+ tables = tskit .TableCollection (sequence_length = 100 )
5551+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5552+ # Node without individual reference
5553+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 )
5554+ ts = tables .tree_sequence ()
5555+
5556+ with pytest .raises (ValueError , match = "No nodes refer to individuals" ):
5557+ _ = ts .individual_nodes ()
5558+
5559+ def test_individual_with_no_nodes (self ):
5560+ tables = tskit .TableCollection (sequence_length = 100 )
5561+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5562+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5563+ # Only add nodes for first individual
5564+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5565+ ts = tables .tree_sequence ()
5566+
5567+ with pytest .raises (
5568+ ValueError , match = "Individual 1 not associated with any nodes"
5569+ ):
5570+ _ = ts .individual_nodes ()
5571+
5572+ def test_mixed_sample_status (self ):
5573+ tables = tskit .TableCollection (sequence_length = 100 )
5574+ tables .individuals .add_row (flags = 0 , location = (0 , 0 ), metadata = b"" )
5575+ tables .nodes .add_row (flags = tskit .NODE_IS_SAMPLE , time = 0 , individual = 0 )
5576+ tables .nodes .add_row (flags = 0 , time = 0 , individual = 0 )
5577+ ts = tables .tree_sequence ()
5578+ with pytest .raises (
5579+ ValueError , match = "has nodes that are sample and non-samples"
5580+ ):
5581+ _ = ts .individual_nodes ()
0 commit comments