def ALEtreeToReconciledTree(ALEtree, isDead=False, isUndated=False, sepSp="_"): """ Recursively builds the reconciled tree Takes: - ALEtree (ete3.TreeNode) : a tree read from a reconciled ttree in the ALE format (ie. reconciliation annotations are in the .name field) - isDead (bool) [default = False] : indicates whether or not this lineage starts in a dead/unsampled species Returns: (ReconciledTree) """ isLeaf = ALEtree.is_leaf() annotation = None name = ALEtree.name if isLeaf: name, annotation = separateLeafNameFromLeafAnnotation(ALEtree.name, sepSp=sepSp) #print("leaf parsing :", name , annotation) else: annotation = ALEtree.name #print "name : ",ALEtree.name events = parse_node_annotation(annotation, isLeaf, isDead=isDead, isUndated=isUndated) if isLeaf: ## we specify the species of the leaf event events[-1].species = getLeafSpeciesFromLeafName(ALEtree.name, sepSp=sepSp) #print [str(e) for e in events] if events[-1].eventCode == "Bo": isDead = True ## means that both children must begin by an event in the dead RT = ReconciledTree() RT.setName(name) current = RT for e in events: # if e.eventCode.endswith("L"): # #print "plep" # current = treatLossEvent(current, e , ".c") # else: # current.addEvent(e) # current.addEvent(e) for c in ALEtree.children: ##recursion on successors current.add_child( ALEtreeToReconciledTree(c, isDead, isUndated, sepSp=sepSp)) return RT
def NHXtreeToBasicRecTree(nhxTree, spTree=None): """ *RECURSIVE* From a tree read in a NHX format file to a ReconciledTree without any intermediary events (SpeciationLoss events) Takes: - nhxTree (ete3.TreeNode) : tree read from a NHX formatted line - spTree (ete3.Tree or None) [default = None] : if different from None, internal node's events associated to species whose name is in the species tree will be kept as such if equal to None, only leaves get to keep their associated species (and species of other events will have to be re-associated later) Returns: (ReconciledTree) """ RT = ReconciledTree() eventCode = None species = None ## only terminal events in a DL context are considered here : leaf, speciation or duplication if nhxTree.is_leaf(): eventCode = "C" species = nhxTree.S ## we only get the species for the leaves ##( as they are the only one where we are sure the species is one that is present in the species tree) elif nhxTree.D == "Y": eventCode = "D" else: eventCode = "S" if not spTree is None: if len(spTree.search_nodes( name=nhxTree.S)) == 1: ## not at all efficient ... species = nhxTree.S ##additional info: for f in nhxTree.features: RT.add_feature(f, nhxTree.__getattribute__( f)) ## stinks that we call thi __method__ ... evt = RecEvent(eventCode, species) RT.addEvent(evt) for c in nhxTree.children: RT.add_child(NHXtreeToBasicRecTree(c)) return RT
def read_leaf(s): annot = parsePrIMEAnnotations(s) evt = PrIMEAnnotationToRecEvent(annot) leafNode = ReconciledTree() leafNode.setName(annot["name"]) if annot.has_key("BL"): leafNode.dist = annot["BL"] leafNode.addEvent(evt) #print leafNode.getTreeRecPhyloXML() return leafNode
def read_leaf(s): annot = parseNotungAnnotations(s) evt = NotungAnnotationToRecEvent(annot) leafNode = ReconciledTree() leafNode.setName(annot["name"]) if annot.has_key("BL"): leafNode.dist = annot["BL"] leafNode.addEvent(evt) if isSpeciationNode(leafNode): setNodeAsLeaf(leafNode) if ( not isLeafNode(leafNode) ) and (not isLossNode(leafNode)): AddLeafEvent(leafNode) return leafNode
def MakeLossIndependentNode(node, LossIndex, lostSpecies="", lostTS=None, lostAdditional={}, keptChildNameSuffix=".c"): """ *modifies node* Takes: - node (ReconciledTree): reconciled node where the *Loss event occurs - LossIndex (int): index of the speciationLoss or speciationOutLoss event - lostSpecies (str) [default = ""] : species of the loss - lostTS (int) [default = None]: timeSlice is the loss - lostAdditional [default = {}]: additional information to give to the new loss event - keptChildNameSuffix (str) [default = ".c"] : suffix to add to the name of the new child of node that is NOT a loss """ # 1. create the loss child lossNode = ReconciledTree() lossNode.addEvent( RecEvent("loss", lostSpecies, ts=lostTS, additionnalInfo=lostAdditional)) lossNode.name = "LOSS" # 2. create the kept child keptNode = ReconciledTree() keptNode.name = node.name + keptChildNameSuffix while len(node.eventRecs) > (LossIndex + 1): #print LossIndex, LossIndex+1 , len(node.eventRecs) keptNode.addEvent(node.popEvent(LossIndex + 1)) # 3. link children to kept child while len(node.children) > 0: c = node.children[0] c.detach() keptNode.add_child(c) # 4. branching loss and kept to original node node.add_child(lossNode) node.add_child(keptNode) # 5. editing the event e = node.eventRecs[LossIndex].eventCode node.eventRecs[LossIndex].eventCode = e[:-1] return
def readPrIMEParenthesis(s): if not s.startswith("("): print "error, should begin with a parenthesis" return #### parsiing parentheses i = 1 new_n = "" info = "" childrenNodes = [] inComment = False beginCommentChar = "[" endCommentChar = "]" while i < len(s): if s[i] == beginCommentChar: inComment = True elif s[i] == endCommentChar: inComment = False #print i , s[i] , inComment if inComment: new_n += s[i] else: if s[i] == "(": ##new parenthesis offset, child = readPrIMEParenthesis(s[i:]) i += offset childrenNodes.append(child) #print "added new internal." if s[i] in [")", ","]: if not new_n == "": #print "added leaf",new_n,"parent: current node" childrenNodes.append(read_leaf(new_n)) #info = new_n new_n = "" if s[i] == ")": ##end of the parenthesis i += 1 break else: new_n += s[i] i += 1 ##reading the internal node info while i < len(s): if s[i] == beginCommentChar: inComment = True elif s[i] == endCommentChar: inComment = False #print i , s[i] , inComment if not inComment: if s[i] in [")", ";", ","]: break info += s[i] i += 1 #### building tree annot = parsePrIMEAnnotations(info) #print annot , [c.name for c in childrenNodes] evt = PrIMEAnnotationToRecEvent(annot) IntNode = ReconciledTree() IntNode.setName(annot["name"]) if annot.has_key("BL"): IntNode.dist = annot["BL"] IntNode.addEvent(evt) ## checking if we are transfer if isTansferNode(IntNode): for c in childrenNodes: if not c.sameSpeciesAsParent( parent=IntNode): ## we found a children node addTbEvent(c) ## we add the transferBack event if len(childrenNodes) > 1: ## two or more children, add them for c in childrenNodes: IntNode.add_child(c) elif len(childrenNodes) == 1: ## only one children. add its events to the current node for e in childrenNodes[0].getEvents(): #print e IntNode.addEvent(e) for c in childrenNodes[0].get_children(): IntNode.add_child(c) #print annot["name"],"-->",[n.getTreeNewick() for n in childrenNodes] return i, IntNode
def addSpeciationAndLoss(node , keptSpeciesNode): """ *modifies node in place* Takes: - node (ReconciledTree): node where a SpeciationLoss must take place - keptSpeciesNode (ete3.TreeNode): node of the species tree where the lineage survived (ie. the sister species of the one where the loss occured) """ parentSpeciesNode = keptSpeciesNode.up lossSpeciesNode = getSister(keptSpeciesNode) lossNode = ReconciledTree() lossNode.addEvent( RecEvent("loss" , lossSpeciesNode.name) ) lossNode.name="LOSS" # 2. create the kept child keptNode = ReconciledTree() ##transfering the events of node to keptNode while len(node.eventRecs) > 0: keptNode.addEvent( node.popEvent(0), append=False ) # 3. link children to kept child while len(node.children) > 0: c = node.children[0] c.detach() keptNode.add_child(c) # 4. branching loss and kept to original node node.add_child(lossNode) node.add_child(keptNode) # 5. editing the event e = RecEvent( "S" , keptSpeciesNode.up.name ) node.addEvent( e,append = False) ##will insert the evt in first position return
def parse_clade(self, element, reconciled=True, obsoleteTagsBehaviour=1): """ *recursive funtion* Takes: - element (Element) : element with the "clade" tag - reconciled (bool) [default = True] : whether the element passed should be considered a ReconciledTree or not - obsoleteTagsBehaviour (int) [default = 1]: 0 : ignore 1 : warning 2 : throw exception Returns: None : error or (ReconciledTree) : the reconciled tree """ TAG = "clade" if not self.isOfTag(element, TAG): raise Exception('BadTagException. The element is of tag ' + element.tag + " instead of " + TAG + ".") children = element.getchildren() name = None childrenNodes = [] events = [] additionnalInfo = {} for ch in children: if self.isOfTag(ch, "clade"): childrenNodes.append( self.parse_clade(ch, reconciled, obsoleteTagsBehaviour)) elif self.isOfTag(ch, "name"): name = self.parseSimpletextElement(ch) elif self.isOfTag(ch, "eventsRec"): events = self.parse_eventsRec(ch, obsoleteTagsBehaviour) else: ### treatment for other children additionnalInfo[self.tagCorrection(ch.tag)] = ch ### treatment for keys for k, v in element.items(): if k != "rooted": additionnalInfo[k] = v node = None if reconciled: node = ReconciledTree() else: node = ete3.Tree() node.name = name if reconciled: for e in events: node.addEvent(e) for ch in childrenNodes: node.add_child(ch) if additionnalInfo.has_key("branch_length"): node.dist = float(additionnalInfo.pop("branch_length").text) if additionnalInfo.has_key("confidence"): node.support = float(additionnalInfo.pop("confidence").text) if len(additionnalInfo) > 0: node.add_features(**additionnalInfo) return node
def readNotungParenthesis(s): if not s.startswith("("): print "error, should begin with a parenthesis" return i = 1 new_n = "" info = "" childrenNodes = [] while i < len(s): if s[i] == "(":##new parenthesis offset , child = readNotungParenthesis(s[i:]) i += offset childrenNodes.append(child) # print "added new internal." if s[i] in [")",","]: if not new_n == "": #print "added leaf",new_n,"parent: current node" childrenNodes.append( read_leaf(new_n) ) #info = new_n new_n = "" if s[i] == ")":##end of the parenthesis i+=1 break else: new_n += s[i] i+=1 ##reading the internal node info while s[i] not in [")",";",","] and i < len(s): info += s[i] i+=1 annot = parseNotungAnnotations( info ) evt = NotungAnnotationToRecEvent(annot) IntNode = ReconciledTree() IntNode.setName(annot["name"]) if annot.has_key("BL"): IntNode.dist = annot["BL"] IntNode.addEvent(evt) ## checking if : one of the child is a loss and/or a child is a transfer reception hasLoss = False hasTransfer = False j = 0 while j < len(childrenNodes): c = childrenNodes[j] if isLossNode(c): hasLoss = True #childrenNodes.pop(j) #continue if isTransferBackNode(c): hasTransfer = True j +=1 if hasTransfer: setNodeAsTransfer(IntNode) #if hasLoss: # setNodeAsXloss(IntNode) if len(childrenNodes) > 1: ## two or more children, add them for c in childrenNodes: IntNode.add_child(c) elif len(childrenNodes) == 1: ## only one children. add its events to the current node for e in childrenNodes[0].getEvents(): #print e IntNode.addEvent(e) for c in childrenNodes[0].get_children(): IntNode.add_child(c) #print IntNode.getTreeRecPhyloXML() #print annot["name"],"-->",[n.getTreeNewick() for n in childrenNodes] return i, IntNode