@@ -975,3 +975,78 @@ def test_reversed_names(self):
975975 )
976976 == expected
977977 )
978+
979+
980+ class TestVcfMapping :
981+ def test_mix_sample_non_sample (self ):
982+ ts = tskit .Tree .generate_balanced (5 , span = 10 ).tree_sequence
983+ ts = tsutil .insert_branch_sites (ts )
984+ assert ts .num_nodes >= 8
985+ tables = ts .dump_tables ()
986+ tables .individuals .add_row ()
987+ tables .individuals .add_row ()
988+ tables .individuals .add_row ()
989+ tables .individuals .add_row ()
990+ individual = tables .nodes .individual
991+ assert np .all (individual == - 1 )
992+ # First has only non-sample nodes
993+ individual [7 ] = 0
994+ # Second has 2 sample nodes
995+ individual [0 ] = 1
996+ individual [1 ] = 1
997+ # Third has 1 non-sample and 1 sample
998+ individual [5 ] = 2
999+ individual [2 ] = 2
1000+ # Fourth has sandwiched non-sample
1001+ individual [3 ] = 3
1002+ individual [6 ] = 3
1003+ individual [4 ] = 3
1004+ tables .nodes .individual = individual
1005+ ts = tables .tree_sequence ()
1006+
1007+ # Individual "A" is redacted as has no nodes
1008+ s = """\
1009+ #CHROM\t POS\t ID\t REF\t ALT\t QUAL\t FILTER\t INFO\t FORMAT\t B\t C\t D
1010+ 1\t 0\t 0\t 0\t 1\t .\t PASS\t .\t GT\t 1|1\t 0\t 0|0
1011+ 1\t 1\t 1\t 0\t 1\t .\t PASS\t .\t GT\t 1|0\t 0\t 0|0
1012+ 1\t 2\t 2\t 0\t 1\t .\t PASS\t .\t GT\t 0|1\t 0\t 0|0
1013+ 1\t 3\t 3\t 0\t 1\t .\t PASS\t .\t GT\t 0|0\t 1\t 1|1
1014+ 1\t 4\t 4\t 0\t 1\t .\t PASS\t .\t GT\t 0|0\t 1\t 0|0
1015+ 1\t 6\t 5\t 0\t 1\t .\t PASS\t .\t GT\t 0|0\t 0\t 1|1
1016+ 1\t 7\t 6\t 0\t 1\t .\t PASS\t .\t GT\t 0|0\t 0\t 1|0
1017+ 1\t 8\t 7\t 0\t 1\t .\t PASS\t .\t GT\t 0|0\t 0\t 0|1"""
1018+ expected = textwrap .dedent (s )
1019+ assert (
1020+ drop_header (
1021+ ts .as_vcf (
1022+ individual_names = ["A" , "B" , "C" , "D" ],
1023+ allow_position_zero = True ,
1024+ ),
1025+ )
1026+ == expected
1027+ )
1028+
1029+ # Now with non-sample nodes, so A is included, C becomes diploid
1030+ # and D is triploid
1031+ s = """\
1032+ #CHROM\t POS\t ID\t REF\t ALT\t QUAL\t FILTER\t INFO\t FORMAT\t A\t B\t C\t D
1033+ 1\t 0\t 0\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 1|1\t 0|1\t 0|0|0
1034+ 1\t 1\t 1\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 1|0\t 0|0\t 0|0|0
1035+ 1\t 2\t 2\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 0|1\t 0|0\t 0|0|0
1036+ 1\t 3\t 3\t 0\t 1\t .\t PASS\t .\t GT\t 1\t 0|0\t 1|0\t 1|1|1
1037+ 1\t 4\t 4\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 0|0\t 1|0\t 0|0|0
1038+ 1\t 6\t 5\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 0|0\t 0|0\t 1|1|1
1039+ 1\t 7\t 6\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 0|0\t 0|0\t 1|0|0
1040+ 1\t 8\t 7\t 0\t 1\t .\t PASS\t .\t GT\t 0\t 0|0\t 0|0\t 0|1|0"""
1041+ expected = textwrap .dedent (s )
1042+ assert (
1043+ drop_header (
1044+ ts .as_vcf (
1045+ individual_names = ["A" , "B" , "C" , "D" ],
1046+ allow_position_zero = True ,
1047+ include_non_sample_nodes = True ,
1048+ isolated_as_missing = False ,
1049+ ),
1050+ )
1051+ == expected
1052+ )
0 commit comments