Back to index

python-biopython  1.60
test_Nexus.py
Go to the documentation of this file.
00001 import os.path
00002 import unittest
00003 import tempfile
00004 import cStringIO
00005 import sys
00006 
00007 from Bio.Nexus import Nexus, Trees
00008 
00009 
00010 class NexusTest1(unittest.TestCase):
00011     def setUp(self):
00012         self.testfile_dir = "Nexus"
00013         self.handle = open(os.path.join(self.testfile_dir, 
00014             "test_Nexus_input.nex"))
00015 
00016     def tearDown(self):
00017         self.handle.close()
00018 
00019     def test_WriteToFileName(self):
00020         """Test writing to a given filename."""
00021         filename = "Nexus/test_temp.nex"
00022         if os.path.isfile(filename):
00023             os.remove(filename)
00024         n = Nexus.Nexus(self.handle)
00025         n.write_nexus_data(filename)
00026         self.assertTrue(os.path.isfile(filename))
00027         os.remove(filename)
00028 
00029     def test_NexusTest1(self):
00030         """Test Nexus module"""
00031         # check data of main nexus file
00032         n=Nexus.Nexus(self.handle)
00033         self.assertEqual(os.path.normpath(n.filename),
00034                          os.path.normpath("Nexus/test_Nexus_input.nex"))
00035         self.assertEqual(n.ntax, 9)
00036         self.assertEqual(n.nchar, 48)
00037         self.assertEqual(n.datatype, "dna")
00038         self.assertEqual(n.interleave, True)
00039         self.assertEqual(n.missing, "?")
00040         self.assertEqual(n.gap, "-")
00041         self.assertEqual(n.taxlabels, ["t1",
00042                                        "t2 the name",
00043                                        "isn'that [a] strange name?",
00044                                        "one should be punished, for (that)!",
00045                                        "t5",
00046                                        "t6",
00047                                        "t7",
00048                                        "t8",
00049                                        "t9"])
00050         self.assertEqual(n.charlabels, {0: 'a',
00051                                         1: 'b',
00052                                         2: 'c',
00053                                         4: 'f',
00054                                         9: 'A',
00055                                         10: 'B',
00056                                         22: 'x',
00057                                         23: "y",
00058                                         29: "1,2,3 can't decide for a name?!",
00059                                         47: "final"})
00060         self.assertEqual(n.charsets, {
00061             "big":        [0, 2, 4, 6],
00062             "bigchunk":   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46],
00063             "byname":     [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
00064             "c1":         [0, 1, 2, 3, 4, 5, 6, 7],
00065             "c2":         [8, 9, 10, 11, 12, 13, 14, 15],
00066             "c3":         [16, 17, 18, 19, 20, 21, 22, 23],
00067             "firsthalf":  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
00068             "mix":        [0, 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46],
00069             "mux":        [0, 1, 4, 7, 8, 10, 13, 16, 17, 18, 19, 20, 21, 22, 23, 25, 28, 31, 34, 37, 40, 43, 46],
00070             "pos1":       [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45],
00071             "pos2":       [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46],
00072             "pos3":       [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47],
00073             "secondhalf": [24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],
00074                                      })
00075         self.assertEqual(n.taxsets, {
00076             "normal":    ["isn'that [a] strange name?",
00077                           'one should be punished, for (that)!',
00078                           't1',
00079                           't5',
00080                           't6',
00081                           't8'],
00082             "reference": ["isn'that [a] strange name?",
00083                           'one should be punished, for (that)!',
00084                           't1',
00085                           't2 the name',
00086                           't5',
00087                           't6'],
00088             "tbyname1": ["isn'that [a] strange name?",
00089                           'one should be punished, for (that)!',
00090                           't1',
00091                           't2 the name',
00092                           't5',
00093                           't6'],
00094             "tbyname2": ["isn'that [a] strange name?",
00095                           'one should be punished, for (that)!',
00096                           't2 the name',
00097                           't5',
00098                           't6',
00099                           't7'],
00100             "tbyname3": ['t1',
00101                           't2 the name'],
00102                                     })
00103         self.assertEqual(len(n.charpartitions), 2)
00104         self.assertTrue('codons' in n.charpartitions)
00105         self.assertTrue('part' in n.charpartitions)
00106         self.assertEqual(n.charpartitions['codons'],
00107             {'a': [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45],
00108              'b': [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46],
00109              'c': [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47],
00110             })
00111         self.assertEqual(n.charpartitions['part'],
00112             {"one":   [0, 1, 2, 3, 4, 5, 6, 7],
00113              "three": [16, 17, 18, 19, 20, 21, 22, 23],
00114              "two":   [8, 9, 10, 11, 12, 13, 14, 15],
00115             })
00116         self.assertEqual(n.taxpartitions.keys(), ['taxpart'])
00117         self.assertEqual(n.taxpartitions['taxpart'], 
00118             {"badnames":  ["isn'that [a] strange name?",
00119                            'one should be punished, for (that)!',
00120                            't2 the name'],
00121              "goodnames": ['t1', 't5', 't6', 't7', 't8', 't9'],
00122             })
00123 
00124         # now we check excluding characters, deleting taxa,
00125         # and exporting adjusted sets
00126         f1=tempfile.NamedTemporaryFile("w+")
00127         n.write_nexus_data(f1,
00128                            delete=['t1','t7'],
00129                            exclude=n.invert(n.charsets['big']))
00130         f1.seek(0)
00131         nf1=Nexus.Nexus(f1)
00132         self.assertEqual(os.path.normpath(nf1.filename),
00133                          os.path.normpath(f1.name))
00134         self.assertEqual(nf1.ntax, 7)
00135         self.assertEqual(nf1.nchar, 4)
00136         self.assertEqual(nf1.datatype, "dna")
00137         self.assertEqual(nf1.interleave, False)
00138         self.assertEqual(nf1.missing, "?")
00139         self.assertEqual(nf1.gap, "-")
00140         self.assertEqual(nf1.taxlabels, ["t2 the name",
00141                                          "isn'that [a] strange name?",
00142                                          "one should be punished, for (that)!",
00143                                          "t5",
00144                                          "t6",
00145                                          "t8",
00146                                          "t9"])
00147         self.assertEqual(nf1.charlabels, {0: 'a', 1: 'c', 2: 'f'})
00148         self.assertEqual(nf1.charsets, {'big':       [0, 1, 2, 3],
00149                                         'bigchunk':  [1, 2, 3],
00150                                         'byname':    [0, 2, 3],
00151                                         'c1':        [0, 1, 2, 3],
00152                                         'firsthalf': [0, 1, 2, 3],
00153                                         'mix':       [0, 2],
00154                                         'mux':       [0, 2],
00155                                         'pos1':      [0, 3],
00156                                         'pos2':      [2],
00157                                         'pos3':      [1],
00158                                        })
00159         self.assertEqual(nf1.taxsets, {
00160             'normal':    ["isn'that [a] strange name?",
00161                           'one should be punished, for (that)!',
00162                           't5',
00163                           't6',
00164                           't8'],
00165             'reference': ["isn'that [a] strange name?",
00166                           'one should be punished, for (that)!',
00167                           't2 the name',
00168                           't5',
00169                           't6'],
00170             'tbyname1':  ["isn'that [a] strange name?",
00171                           'one should be punished, for (that)!',
00172                           't2 the name',
00173                           't5',
00174                           't6'],
00175             'tbyname2':  ["isn'that [a] strange name?",
00176                           'one should be punished, for (that)!',
00177                           't2 the name',
00178                           't5',
00179                           't6'],
00180             'tbyname3': ['t2 the name'],
00181                                        })
00182         self.assertEqual(len(nf1.charpartitions), 2)
00183         self.assertTrue('codons' in nf1.charpartitions)
00184         self.assertTrue('part' in nf1.charpartitions)
00185         self.assertEqual(nf1.charpartitions['codons'], {'a': [0, 3],
00186                                                         'b': [2],
00187                                                         'c': [1]})
00188         self.assertEqual(nf1.charpartitions['part'], {'one': [0, 1, 2, 3]})
00189 
00190         self.assertEqual(nf1.taxpartitions.keys(), ['taxpart'])
00191         self.assertEqual(nf1.taxpartitions['taxpart'],
00192             {"badnames":  ["isn'that [a] strange name?",
00193                            'one should be punished, for (that)!',
00194                            't2 the name'],
00195              "goodnames": ['t5', 't6', 't8', 't9'],
00196             })
00197 
00198         f2=tempfile.NamedTemporaryFile("w+")
00199         n.write_nexus_data(f2,
00200                            delete=['t2_the_name'],
00201                            exclude=range(3,40,4))
00202         f2.seek(0)
00203         nf2=Nexus.Nexus(f2)
00204         self.assertEqual(os.path.normpath(nf2.filename),
00205                          os.path.normpath(f2.name))
00206         self.assertEqual(nf2.ntax, 9)
00207         self.assertEqual(nf2.nchar, 38)
00208         self.assertEqual(nf2.datatype, "dna")
00209         self.assertEqual(nf2.interleave, False)
00210         self.assertEqual(nf2.missing, "?")
00211         self.assertEqual(nf2.gap, "-")
00212         self.assertEqual(nf2.taxlabels, ["t1", 
00213                                          "t2 the name", 
00214                                          "isn'that [a] strange name?", 
00215                                          "one should be punished, for (that)!", 
00216                                          "t5", 
00217                                          "t6", 
00218                                          "t7", 
00219                                          "t8", 
00220                                          "t9"])
00221         self.assertEqual(nf2.charlabels, {0: "a",
00222                                           1: "b",
00223                                           2: "c",
00224                                           3: "f",
00225                                           7: "A",
00226                                           8: "B",
00227                                           17: "x",
00228                                           22: "1,2,3 can't decide for a name?!",
00229                                           37: "final"})
00230         self.assertEqual(nf2.charsets,
00231             {"big":        [0, 2, 3, 5],
00232              "bigchunk":   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36],
00233              "byname":     [0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22],
00234              "c1":         [0, 1, 2, 3, 4, 5],
00235              "c2":         [6, 7, 8, 9, 10, 11],
00236              "c3":         [12, 13, 14, 15, 16, 17],
00237              "firsthalf":  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
00238              "mix":        [0, 1, 3, 8, 10, 12, 17, 19, 21, 26, 28, 30, 33, 36],
00239              "mux":        [0, 1, 3, 6, 8, 10, 12, 13, 14, 15, 16, 17, 19, 21, 26, 28, 30, 33, 36],
00240              "pos1":       [0, 5, 7, 9, 14, 16, 18, 23, 25, 27, 32, 35],
00241              "pos2":       [1, 3, 8, 10, 12, 17, 19, 21, 26, 28, 30, 33, 36],
00242              "pos3":       [2, 4, 6, 11, 13, 15, 20, 22, 24, 29, 31, 34, 37],
00243              "secondhalf": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37],
00244             })
00245 
00246         self.assertEqual(nf2.taxsets,
00247             {"normal":    ["isn'that [a] strange name?",
00248                            'one should be punished, for (that)!',
00249                            't1',
00250                            't5',
00251                            't6',
00252                            't8'],
00253              "reference": ["isn'that [a] strange name?",
00254                            'one should be punished, for (that)!',
00255                            't1',
00256                            't2 the name',
00257                            't5',
00258                            't6'],
00259              "tbyname1":  ["isn'that [a] strange name?",
00260                            'one should be punished, for (that)!',
00261                            't1',
00262                            't2 the name',
00263                            't5',
00264                            't6'],
00265              "tbyname2":  ["isn'that [a] strange name?",
00266                            'one should be punished, for (that)!',
00267                            't2 the name',
00268                            't5',
00269                            't6',
00270                            't7'],
00271              "tbyname3":  ['t1',
00272                            't2 the name']})
00273         self.assertEqual(len(nf2.charpartitions), 2)
00274         self.assertTrue('codons' in nf2.charpartitions)
00275         self.assertTrue('part' in nf2.charpartitions)
00276         self.assertEqual(nf2.charpartitions['codons'],
00277             {"a": [0, 5, 7, 9, 14, 16, 18, 23, 25, 27, 32, 35],
00278              "b": [1, 3, 8, 10, 12, 17, 19, 21, 26, 28, 30, 33, 36],
00279              "c": [2, 4, 6, 11, 13, 15, 20, 22, 24, 29, 31, 34, 37],
00280             })
00281         self.assertEqual(nf2.charpartitions['part'],
00282             {"one":   [0, 1, 2, 3, 4, 5],
00283              "three": [12, 13, 14, 15, 16, 17],
00284              "two":   [6, 7, 8, 9, 10, 11],
00285             })
00286         self.assertEqual(nf2.taxpartitions.keys(), ['taxpart'])
00287         self.assertEqual(nf2.taxpartitions['taxpart'],
00288             {"badnames":  ["isn'that [a] strange name?",
00289                            'one should be punished, for (that)!',
00290                            't2 the name'],
00291              "goodnames": ['t1', 't5', 't6', 't7', 't8', 't9'],
00292             })
00293         # check the stepmatrix
00294         self.assertEqual(n.weighted_stepmatrix(name='matrix_test'),
00295         """\
00296 usertype matrix_test stepmatrix=5
00297         A        C        G        T        -
00298 [A]     .       2.40     2.57     2.43     2.43     
00299 [C]    2.40      .       2.28     2.12     2.14     
00300 [G]    2.57     2.28      .       2.31     2.31     
00301 [T]    2.43     2.12     2.31      .       2.14     
00302 [-]    2.43     2.14     2.31     2.14      .       
00303 ;
00304 """)
00305 
00306 
00307     def test_TreeTest1(self):
00308         """Test Tree module."""
00309         n=Nexus.Nexus(self.handle)
00310         t3=n.trees[2]
00311         t2=n.trees[2]
00312         t3.root_with_outgroup(['t1','t5'])
00313         self.assertEqual(str(t3), "tree tree1 = (((((('one should be punished, for (that)!','isn''that [a] strange name?'),'t2 the name'),t8,t9),t6),t7),(t5,t1));")
00314         self.assertEqual(t3.is_monophyletic(['t8','t9','t6','t7']), -1)
00315         self.assertEqual(t3.is_monophyletic(['t1','t5']), 13)
00316         t3.split(parent_id=t3.search_taxon('t9'))
00317         stdout = sys.stdout
00318         try:
00319             sys.stdout = cStringIO.StringIO()
00320             t3.display()
00321             if sys.version_info[0] == 3:
00322                 output = sys.stdout.getvalue()
00323             else:
00324                 sys.stdout.reset()
00325                 output = sys.stdout.read()
00326         finally:
00327             sys.stdout = stdout 
00328         expected = """\
00329   #                            taxon            prev            succ    brlen blen (sum)  support              comment
00330   1    'isn''that [a] strange name?'               2              []   100.00     119.84    10.00                    -
00331   2                                -               4          [3, 1]     0.40      19.84     0.30                    -
00332   3 'one should be punished, for (that)!'               2              []     0.50      20.34        -                    -
00333   4                                -               6          [2, 5]     4.00      19.44     3.00                    -
00334   5                    't2 the name'               4              []     0.30      19.74        -                    -
00335   6                                -               9       [4, 7, 8]     2.00      15.44     1.00                    -
00336   7                               t8               6              []     1.20      16.64        -                    -
00337   8                               t9               6        [17, 18]     3.40      18.84        -                    -
00338   9                                -              11         [6, 10]     0.44      13.44    33.00                    -
00339  10                               t6               9              []     1.00      14.44        -                    -
00340  11                                -              16         [9, 12]    13.00      13.00    12.00                    -
00341  12                               t7              11              []    99.90     112.90        -                    -
00342  13                                -              16        [14, 15]     0.00       0.00     0.00                    -
00343  14                               t5              13              []    99.00      99.00        -                    -
00344  15                               t1              13              []     0.98       0.98        -                    -
00345  16                                -            None        [11, 13]     0.00       0.00        -                    -
00346  17                              t90               8              []     1.00      19.84        -                    -
00347  18                              t91               8              []     1.00      19.84        -                    -
00348 
00349 Root:  16
00350 """
00351         self.assertEqual(len(output.split("\n")), len(expected.split("\n")))
00352         for l1, l2 in zip(output.split("\n"), expected.split("\n")):
00353             self.assertEqual(l1, l2)
00354         self.assertEqual(output, expected)
00355         self.assertEqual(t3.is_compatible(t2,threshold=0.3), [])
00356 
00357     def test_internal_node_labels(self):
00358         """Handle text labels on internal nodes.
00359         """
00360         ts1b = "(Cephalotaxus:125.000000,(Taxus:100.000000,Torreya:100.000000)"\
00361                "TT1:25.000000)Taxaceae:90.000000;"
00362         tree = Trees.Tree(ts1b)
00363         assert self._get_flat_nodes(tree) == [('Taxaceae', 90.0, None, None),
00364                 ('Cephalotaxus', 125.0, None, None), ('TT1', 25.0, None, None),
00365                 ('Taxus', 100.0, None, None), ('Torreya', 100.0, None, None)]
00366 
00367         ts1c = "(Cephalotaxus:125.000000,(Taxus:100.000000,Torreya:100.000000)"\
00368                 "25.000000)90.000000;"
00369         tree = Trees.Tree(ts1c)
00370         assert self._get_flat_nodes(tree) == [(None, 90.0, None, None),
00371                 ('Cephalotaxus', 125.0, None, None), (None, 25.0, None, None),
00372                 ('Taxus', 100.0, None, None), ('Torreya', 100.0, None, None)]
00373 
00374         ts2 = "(((t9:0.385832, (t8:0.445135,t4:0.41401)C:0.024032)B:0.041436,"\
00375           "t6:0.392496)A:0.0291131, t2:0.497673, ((t0:0.301171,"\
00376           "t7:0.482152)E:0.0268148, ((t5:0.0984167,t3:0.488578)G:0.0349662,"\
00377           "t1:0.130208)F:0.0318288)D:0.0273876);"
00378         tree = Trees.Tree(ts2)
00379 
00380         large_ex_handle = open(os.path.join(self.testfile_dir,
00381             "int_node_labels.nwk"))
00382         tree = Trees.Tree(large_ex_handle.read())
00383         large_ex_handle.close()
00384 
00385     def _get_flat_nodes(self, tree):
00386         cur_nodes = [tree.node(tree.root)]
00387         nodedata = []
00388         while len(cur_nodes) > 0:
00389             new_nodes = []
00390             for cur_node in cur_nodes:
00391                 nodedata.append((cur_node.data.taxon,
00392                     cur_node.data.branchlength, cur_node.data.support,
00393                     cur_node.data.comment))
00394                 new_nodes.extend([tree.node(nid) for nid in
00395                     cur_node.get_succ()])
00396             cur_nodes = new_nodes
00397         return nodedata
00398 
00399 if __name__ == "__main__":
00400     runner = unittest.TextTestRunner(verbosity = 2)
00401     unittest.main(testRunner=runner)