PhyloGenPy is a network first library, as there is no separate tree class that is required to be void of reticulations or hybridizations. Every network or tree is represented the same way, as a directed acyclic graph (the DAG class).

Furthermore, the type of network is described by the type of node that it contains. Ultrametric networks are built using UltrametricNode objects, and standard networks are built with the standard Node object.


To create a network is very easy and straightforward:

                        from phylogenpy.Graph import DAG

                        #Can initialize as an empty graph
                        tree = DAG()

                        #To make it a network, simply add in individual nodes
                        #one at a time, or pass in an array of nodes
                        tree.addNodes(individualNodeObj)
                        tree.addNodes(arrayOfNodeObjs)

                        #same applies to adding edges
                        tree.addEdges(individualEdge)
                        tree.addEdges(arrayOfEdges) #Where an edge can just be [NodeObj, NodeObj2]

                        #Now you have a complete network. To grab the newick representation...
                        newickStr = tree.newickString() 

                        #You can now visualize your graph with IcyTree
                        
                        #You can also initialize trees with node and edge lists 
                        tree2 = DAG(edgeList) #add nodes later
                        tree3 = DAG(nodes = nodeList) #add edges later
                        tree4 = DAG(edgeList, nodeList) #add both now


                        #To see a description of all the nodes in your graph:
                        tree.printGraph()

                

A Node object has the following initialization parameters, all of which are defaults:

  1. branchLen = None
  2. parNode = [ ]
  3. attr = { }
  4. isReticulation = False
  5. name = None
                        from phylogenpy.Node import Node

                        #Can initialize as an empty Node
                        new_node = Node()

                        #To set the branch length
                        new_node.setBranchLength(num)
                        
                        #To get the branch length
                        node_len = new_node.branchLen()

                        #To add a parent (must be a Node or UltrametricNode obj)
                        new_node.addParent(par_node)

                        #or to set the parent
                        new_node.setParent(par_node)

                        #To set the name of a Node
                        new_node.setName("Homo Sapiens")

                        #To get the name of the Node
                        node_name = new_node.getName()

                        #To set a custom attribute
                        new_node.setAttribute(attribute, value) #i.e "t" : 5.4
                
                        #To look up an attribute
                        attr_val = new_node.attrLookup(attribute) #i.e "t" returns 5.4

                        #To visualize the values contained in a Node obj 
                        new_node.asString()

                        #A more typical way to create a Node
                        new_node2 = Node(parNode = [par_node], attr = {"t":5.4}, name = "species2")