@@ -2148,10 +2148,10 @@ def nodes(self, root=None, order="preorder"):
21482148 yield from iterator (u )
21492149
21502150 # TODO make this a bit less embarrassing by using an iterative method.
2151- def __build_newick (self , node , precision , node_labels ):
2151+ def __build_newick (self , * , node , precision , node_labels , include_branch_lengths ):
21522152 """
21532153 Simple recursive version of the newick generator used when non-default
2154- node labels are needed.
2154+ node labels are needed, or when branch lengths are omitted
21552155 """
21562156 label = node_labels .get (node , "" )
21572157 if self .is_leaf (node ):
@@ -2160,12 +2160,26 @@ def __build_newick(self, node, precision, node_labels):
21602160 s = "("
21612161 for child in self .children (node ):
21622162 branch_length = self .branch_length (child )
2163- subtree = self .__build_newick (child , precision , node_labels )
2164- s += subtree + ":{0:.{1}f}," .format (branch_length , precision )
2163+ subtree = self .__build_newick (
2164+ node = child ,
2165+ precision = precision ,
2166+ node_labels = node_labels ,
2167+ include_branch_lengths = include_branch_lengths ,
2168+ )
2169+ if include_branch_lengths :
2170+ subtree += ":{0:.{1}f}" .format (branch_length , precision )
2171+ s += subtree + ","
21652172 s = s [:- 1 ] + f"){ label } "
21662173 return s
21672174
2168- def newick (self , precision = 14 , root = None , node_labels = None ):
2175+ def newick (
2176+ self ,
2177+ precision = 14 , # Should probably be keyword only, left positional for legacy use
2178+ * ,
2179+ root = None ,
2180+ node_labels = None ,
2181+ include_branch_lengths = True ,
2182+ ):
21692183 """
21702184 Returns a `newick encoding <https://en.wikipedia.org/wiki/Newick_format>`_
21712185 of this tree. If the ``root`` argument is specified, return a representation
@@ -2187,6 +2201,8 @@ def newick(self, precision=14, root=None, node_labels=None):
21872201 :param dict node_labels: If specified, show custom labels for the nodes
21882202 that are present in the map. Any nodes not specified in the map will
21892203 not have a node label.
2204+ :param include_branch_lengths: If True (default), output branch lengths in the
2205+ Newick file. If False, only output the topology, without branch lengths.
21902206 :return: A newick representation of this tree.
21912207 :rtype: str
21922208 """
@@ -2198,6 +2214,9 @@ def newick(self, precision=14, root=None, node_labels=None):
21982214 "newick trees, one for each root."
21992215 )
22002216 root = self .root
2217+ if not include_branch_lengths and node_labels is None :
2218+ # Force the python generator for simplicity, by specifying the default labels
2219+ node_labels = {i : str (i + 1 ) for i in self .leaves ()}
22012220 if node_labels is None :
22022221 root_time = max (1 , self .time (root ))
22032222 max_label_size = math .ceil (math .log10 (self .tree_sequence .num_nodes ))
@@ -2210,7 +2229,15 @@ def newick(self, precision=14, root=None, node_labels=None):
22102229 )
22112230 s = s .decode ()
22122231 else :
2213- return self .__build_newick (root , precision , node_labels ) + ";"
2232+ s = (
2233+ self .__build_newick (
2234+ node = root ,
2235+ precision = precision ,
2236+ node_labels = node_labels ,
2237+ include_branch_lengths = include_branch_lengths ,
2238+ )
2239+ + ";"
2240+ )
22142241 return s
22152242
22162243 def as_dict_of_dicts (self ):
@@ -4489,7 +4516,7 @@ def to_nexus(self, precision=14):
44894516 for tree in self .trees ():
44904517 start_interval = "{0:.{1}f}" .format (tree .interval .left , precision )
44914518 end_interval = "{0:.{1}f}" .format (tree .interval .right , precision )
4492- newick = tree .newick (precision , node_labels = node_labels )
4519+ newick = tree .newick (precision = precision , node_labels = node_labels )
44934520 s += f"\t TREE tree{ start_interval } _{ end_interval } = { newick } \n "
44944521
44954522 s += "END;\n "
0 commit comments