Package: python-nexus
python-nexusA Generic phylogenetic nexus format (.nex, .trees) reader and writer for python.Descriptionpython-nexus provides simple nexus file-format reading/writing tools, and a small
collection of nexus manipulation scripts.Please note that this library works with the phylogenetics data format (e.g.https://en.wikipedia.org/wiki/Nexus_file)
and not the phyics data format (e.g.https://manual.nexusformat.org/).Note: Due to a name clash with another python package, this package must beinstalledaspip install python-nexusbutimportedasimport nexus.UsageCLIpython-nexusinstalls a commandnexusfor cli use. You can inspect its help vianexus-hPython APIReading a Nexus:>>>fromnexusimportNexusReader>>>n=NexusReader.from_file('tests/examples/example.nex')You can also load from a string:>>>n=NexusReader.from_string('#NEXUS\n\nbegin foo; ... end;')NexusReader will load each of the nexusblocksit identifies using specifichandlers.>>>n.blocks{'foo':<nexus.handlers.GenericHandlerobjectat0x7f55d94140f0>}>>>n=NexusReader('tests/examples/example.nex')>>>n.blocks{'data':<NexusDataBlock:2charactersfrom4taxa>}A dictionary mapping blocks to handlers is available as `nexus.reader.HANDLERS:>>>fromnexus.readerimportHANDLERS>>>HANDLERS{'trees':<class'nexus.handlers.tree.TreeHandler'>,'taxa':<class'nexus.handlers.taxa.TaxaHandler'>,'characters':<class'nexus.handlers.data.CharacterHandler'>,'data':<class'nexus.handlers.data.DataHandler'>}Any blocks that aren't in this dictionary will be parsed usingnexus.handlers.GenericHandler.NexusReadercan then write the nexus to a string usingNexusReader.writeor to another
file usingNexusReader.write_to_file:>>>output=n.write()>>>n.write_to_file("mynewnexus.nex")Note: if you want more fine-grained control over generating nexus files, then tryNexusWriterdiscussed below.Block Handlers:There are specific "Handlers" to parse certain known nexus blocks, including the
common 'data', 'trees', and 'taxa' blocks. Any blocks that are unknown will be
parsed with GenericHandler.ALL handlers extend theGenericHandlerclass and have the following methods.__init__(self, name=None, data=None)__init__is called byNexusReaderto parse the contents of the block (indata)
appropriately.write(self)write is called byNexusReaderto write the contents of a block to a string
(i.e. for regenerating the nexus format for saving a file to disk)genericblock handlerThe generic block handler simply stores each line of the block in.block:n.blockname.block
['line1', 'line2', ... ]datablock handlerThese are the main blocks encountered in nexus files - and contain the data matrix.So, given the following nexus file with a data block:#NEXUS 

Begin data;
Dimensions ntax=4 nchar=2;
Format datatype=standard symbols="01" gap=-;
    Matrix
Harry              00
Simon              01
Betty              10
Louise             11
    ;
End;

begin trees;
    tree A = ((Harry:0.1,Simon:0.2),Betty:0.2)Louise:0.1;;
    tree B = ((Simon:0.1,Harry:0.2),Betty:0.2)Louise:0.1;;
end;You can do the following:Find out how many characters:>>>n.data.nchar2Ask about how many taxa:>>>n.data.ntaxa4Get the taxa names:>>>n.data.taxa['Harry','Simon','Betty','Louise']Get theformatinfo:>>>n.data.format{'datatype':'standard','symbols':'01','gap':'-'}The actual data matrix is a dictionary, which you can get to in.matrix:>>>n.data.matrixdefaultdict(<class'list'>, {'Harry': ['0', '0'], 'Simon': ['0', '1'], 'Betty': ['1', '0'], 'Louise': ['1', '1']})Or, you could access the data matrix via taxon:>>>n.data.matrix['Simon']['0','1']Or even loop over it like this:>>>fortaxon,charactersinn.data:...print(taxon,characters)...Harry['0','0']Simon['0','1']Betty['1','0']Louise['1','1']You can also iterate over the sites (rather than the taxa):>>>forsite,datainn.data.characters.items():...print(site,data)...0{'Harry':'0','Simon':'0','Betty':'1','Louise':'1'}1{'Harry':'0','Simon':'1','Betty':'0','Louise':'1'}..or you can access the characters matrix directly:>>>n.data.characters[0]{'Harry':'0','Simon':'0','Betty':'1','Louise':'1'}Note: that sites are zero-indexed!treesblock handlerIf there's atreesblock, then you can do the followingYou can get the number of trees:>>>n.trees.ntrees2You can access the trees via the.treesdictionary:>>>n.trees.trees[0]'tree A = ((Harry:0.1,Simon:0.2):0.1,Betty:0.2):Louise:0.1);'Or loop over them:>>>fortreeinn.trees:...print(tree)...treeA=((Harry:0.1,Simon:0.2):0.1,Betty:0.2):Louise:0.1);treeB=((Simon:0.1,Harry:0.2):0.1,Betty:0.2):Louise:0.1);For further inspection of trees via  thenewick package, you can retrieve
anexus.Nodeobject for a tree:>>>print(n.trees.trees[0].newick_tree.ascii_art())┌─Harry┌────────┤──Louise─┤└─Simon└─Bettytaxablock handlerPrograms like SplitsTree understand "TAXA" blocks in Nexus files:BEGIN Taxa;
DIMENSIONS ntax=4;
TAXLABELS
[1] 'John'
[2] 'Paul'
[3] 'George'
[4] 'Ringo'
;
END; [Taxa]In a taxa block you can get the number of taxa and the taxa list:>>>n.taxa.ntaxa4>>>n.taxa.taxa['John','Paul','George','Ringo']NOTE: with this alternate nexus format the Characters blocksshouldbe parsed by
DataHandler.Writing a Nexus File using NexusWriterNexusWriterprovides more fine-grained control over writing nexus files, and
is useful if you're programmatically generating a nexus file rather than loading
a pre-existing one.>>>fromnexusimportNexusWriter>>>n=NexusWriter()>>>#Add a comment to appear in the header of the file>>>n.add_comment("I am a comment")Data are added by using the "add" function - which takes 3 arguments, a taxon,
a character name, and a value.>>>n.add('taxon1','Character1','A')>>>n.data{'Character1':{'taxon1':'A'}}>>>n.add('taxon2','Character1','C')>>>n.add('taxon3','Character1','A')Characters and values can be strings or integers (but youcannotmix string and
integer characters).>>>n.add('taxon1',2,1)>>>n.add('taxon2',2,2)>>>n.add('taxon3',2,3)NexusWriter will interpolate missing entries (i.e. taxon2 in this case)>>>n.add('taxon1',"Char3",'4')>>>n.add('taxon3',"Char3",'4')... when you're ready, you can generate the nexus usingmake_nexusorwrite_to_file:>>>data=n.make_nexus(interleave=True,charblock=True,preserve_order=False)>>>n.write_to_file("output.nex",interleave=True,charblock=True,preserve_order=False)... you can make an interleaved nexus by settinginterleaveto True, and you can
include a character block in the nexus (if you have character labels for example)
by setting charblock to True. Furthermore you can specify whether the order of added
taxa and characters should be preserved by settingpreserve_orderto True, otherwise they will
be sorted alphanumerically.There is rudimentary support for handling trees e.g.:>>>n.trees.append("tree tree1 = (a,b,c);")>>>n.trees.append("tree tree2 = (a,b,c);")