3
$\begingroup$

I want to edit a tree that I got from BEAST2 treeannotator in nexus-format.

Usually I use the module Phylo from Biopython for such work but Phylo.read(r"filename.tree", "nexus") gave me the next exception:

---------------------------------------------------------------------------
NexusError                                Traceback (most recent call last)
Input In [29], in <cell line: 1>()
----> 1 Phylo.read(r"filename.tree", "nexus")

File ~\miniconda3\lib\site-packages\Bio\Phylo\_io.py:60, in read(file, format, **kwargs)
     58 try:
     59     tree_gen = parse(file, format, **kwargs)
---> 60     tree = next(tree_gen)
     61 except StopIteration:
     62     raise ValueError("There are no trees in this file.") from None

File ~\miniconda3\lib\site-packages\Bio\Phylo\_io.py:49, in parse(file, format, **kwargs)
     34 """Parse a file iteratively, and yield each of the trees it contains.
     35 
     36 If a file only contains one tree, this still returns an iterable object that
   (...)
     46 
     47 """
     48 with File.as_handle(file) as fp:
---> 49     yield from getattr(supported_formats[format], "parse")(fp, **kwargs)

File ~\miniconda3\lib\site-packages\Bio\Phylo\NexusIO.py:40, in parse(handle)
     32 def parse(handle):
     33     """Parse the trees in a Nexus file.
     34 
     35     Uses the old Nexus.Trees parser to extract the trees, converts them back to
   (...)
     38     eventually change Nexus to use the new NewickIO parser directly.)
     39     """
---> 40     nex = Nexus.Nexus(handle)
     42     # NB: Once Nexus.Trees is modified to use Tree.Newick objects, do this:
     43     # return iter(nex.trees)
     44     # Until then, convert the Nexus.Trees.Tree object hierarchy:
     45     def node2clade(nxtree, node):

File ~\miniconda3\lib\site-packages\Bio\Nexus\Nexus.py:668, in Nexus.__init__(self, input)
    665 self.options["gapmode"] = "missing"
    667 if input:
--> 668     self.read(input)
    669 else:
    670     self.read(DEFAULTNEXUS)

File ~\miniconda3\lib\site-packages\Bio\Nexus\Nexus.py:718, in Nexus.read(self, input)
    716     break
    717 if title in KNOWN_NEXUS_BLOCKS:
--> 718     self._parse_nexus_block(title, contents)
    719 else:
    720     self._unknown_nexus_block(title, contents)

File ~\miniconda3\lib\site-packages\Bio\Nexus\Nexus.py:759, in Nexus._parse_nexus_block(self, title, contents)
    757 for line in block.commandlines:
    758     try:
--> 759         getattr(self, "_" + line.command)(line.options)
    760     except AttributeError:
    761         raise NexusError("Unknown command: %s " % line.command) from None

File ~\miniconda3\lib\site-packages\Bio\Nexus\Nexus.py:1144, in Nexus._translate(self, options)
   1142         break
   1143     elif c != ",":
-> 1144         raise NexusError("Missing ',' in line %s." % options)
   1145 except NexusError:
   1146     raise

NexusError: Missing ',' in line 1 AB298157.1_2015_-7.9133750332192605_114.8086828279248, 2 AB298158.1_2007_-8.41698974207…

Using Nexus.read(Nexus(), input=r"filename.tree") gave the same result. Please could anyone help with this? I cannot understand the reason of this error because nexus file looks correct.


Nexus format

A NEXUS tree file is a rigid but very useful format which can be used to store a phylogenetic tree, along with associated metadata, for example, the alignment.

It will always comprise a:

TAXA block

The TAXA block contains information about taxa. ... can comprise a,

DATA block

The DATA block contains the data matrix (e.g. sequence alignment). ... in this context importantly will have a,

TREES block

The TREES block contains trees described via the format, e.g. ((A,B),C);:

Each block will open with a BEGIN statement and terminate with an END statement. Again its versatility to store specific information within a block is valuable property of the format.


NB! I encountered some problems with my following work. So I would like to warn readers about them. It is allowed in the newick format to surround the label with quotes, & some programmes or scripts add them to those names that have ambiguous characters. But it can lead to exceptions during the following phylogenetic analysis, for instance, in BEAST. I wish you would be careful with this.

$\endgroup$

1 Answer 1

1
$\begingroup$

That's a complicated output.

Two solutions, the easiest is simply to use Andrew Rambaut's figtree http://tree.bio.ed.ac.uk/software/figtree/ . Figtree is a very, very good tree drawing program and it will work; it works on Mac, Windows and Linux.

You can then export the file from Figure - from memory in numerous formats, e.g. phylip format, and import it into Biopython if that is where it is needed. If you are parsing Beast output, Beast has A LOT of internal tools and you might be attempting to replace those via Biopython. I would avoid it. Also there is the package for processing Beast output (which I forget), I think its called Tracer.

With Biopython try parse, it might help if there are multiple trees:

from Bio import Phylo
trees = Phylo.parse("examples.nex", "nexus")
for tree in trees:
    print(tree.name)

I would avoid the 'r'. I agree it makes no difference, but really you'd need to be using unusual file names for 'r' to be needed. Its possible you are using it to get around \s, i.e. spaces in the file name. You could just think about simply not including \ and space type characters in file names. In regex it is used for certain but that's because its 'inescapable' (no pun intended, but I thought it was funny).


Just to wrap up and clarify, I recommended:

  • To open the tree in Figtree;
  • Find the export menu and output as either 'newick' or preferably 'nexus' or both;
  • Re-run Biopython importing as 'nexus' or 'newick' (if nexus fails).

The OP reported ...

I have just compared them (nexus->FigTree->nexus).

Good so it opened up in FigTree and exported, this was expected.

Fig Tree compose all this actually in newick & stash it in nexus block decor. While in the previous case newick tree contains IDs, & there is a seclude block with ID-name pairs

I missed this bit, "newick stashed in a nexus block". That is potentially really cool because I suspect that is within the TREES block. If that's correct then that is nexus format. This should now open Biopython.

Why the bug?

One of the issues with Nexus is there are two variants regarding how the TAXA block relates to the TREES block. In one format they recode the taxa - I definitely understand why. Recoding is possibly (very likely) be being used in Beast to increase algorithm efficiency - it makes no sense slushing a load of taxa names around a convergence algorithm. Writing all that stuff out is not cool either.

However, when you are looking at a tree that's not what you want at all - efficiency is an irrelevance and readability is important. Thus recoding the taxa labels is definitely not wanted. This is a possible explanation for the read error.

Whatever the reason for the bug I am certain Biopython has a work around because in phylip alignment format this is certainly true. There is a custom module that handles the specific issues the format generates.

It was fun but time to move on.

$\endgroup$
5
  • $\begingroup$ Could I use Figtree algorithms through command line? If it has to be converted to another format, I would like to do this automatically. $\endgroup$
    – Vovin
    Commented Mar 22, 2022 at 14:57
  • 1
    $\begingroup$ My advice is to get it working, even if point and click, - it will work then compare the input formats to understand what the issue is. You can then script the parsing. $\endgroup$
    – M__
    Commented Mar 22, 2022 at 15:08
  • $\begingroup$ So do you suggest to convert nexus to nexus & compare the difference? $\endgroup$
    – Vovin
    Commented Mar 22, 2022 at 15:14
  • 1
    $\begingroup$ I have just compared them (nexus->FigTree->nexus). Fig Tree compose all this actually in newick & stash it in nexus block decor. While in the previous case newick tree contains IDs, & there is a seclude block with ID-name pairs. $\endgroup$
    – Vovin
    Commented Mar 22, 2022 at 15:23
  • $\begingroup$ Good, should work. I've rewritten the answer to accommodate this. $\endgroup$
    – M__
    Commented Mar 22, 2022 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.