Warning
This document is for an old release of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.
Source code for galaxy.visualization.data_providers.phyloviz.phyloxmlparser
from galaxy.util import parse_xml
from .baseparser import (
Base_Parser,
Node,
PhyloTree
)
[docs]class Phyloxml_Parser(Base_Parser):
"""Parses a phyloxml file into a json file that will be passed to PhyloViz for display"""
[docs] def __init__(self):
super().__init__()
self.phyloTree = PhyloTree()
self.tagsOfInterest = {
"clade": "",
"name" : "name",
"branch_length" : "length",
"confidence" : "bootstrap",
"events" : "events"
}
[docs] def parseFile(self, filePath):
"""passes a file and extracts its Phylogeny Tree content."""
xmlTree = parse_xml(filePath)
xmlRoot = xmlTree.getroot()[0]
self.nameSpaceIndex = xmlRoot.tag.rfind("}") + 1 # used later by the clean tag method to remove the name space in every element.tag
phyloRoot = None
for child in xmlRoot:
childTag = self.cleanTag(child.tag)
if childTag == "clade":
phyloRoot = child
elif childTag == "name":
self.phyloTree.title = child.text
self.phyloTree.root = self.parseNode(phyloRoot, 0)
jsonDict = self.phyloTree.generateJsonableDict()
return [jsonDict], "Success"
[docs] def parseNode(self, node, depth):
"""Parses any node within a phyloxml tree and looks out for claude, which signals the creation of
nodes - internal OR leaf"""
tag = self.cleanTag(node.tag)
if not tag == "clade":
return None
hasInnerClade = False
# peeking once for parent and once for child to check if the node is internal
for child in node:
childTag = self.cleanTag(child.tag)
if childTag == "clade":
hasInnerClade = True
break
if hasInnerClade: # this node is an internal node
currentNode = self._makeInternalNode(node, depth=depth)
for child in node:
child = self.parseNode(child, depth + 1)
if isinstance(child, Node):
currentNode.addChildNode(child)
else: # this node is a leaf node
currentNode = self._makeLeafNode(node, depth=depth + 1)
return currentNode
def _makeLeafNode(self, leafNode, depth=0):
"""Makes leaf nodes by calling Phylotree methods"""
node = {}
for child in leafNode:
childTag = self.cleanTag(child.tag)
if childTag in self.tagsOfInterest:
key = self.tagsOfInterest[childTag] # need to map phyloxml terms to ours
node[key] = child.text
node["depth"] = depth
return self.phyloTree.makeNode(self._getNodeName(leafNode), **node)
def _getNodeName(self, node, depth=-1):
"""Gets the name of a claude. It handles the case where a taxonomy node is involved"""
def getTagFromTaxonomyNode(node):
"""Returns the name of a taxonomy node. A taxonomy node have to be treated differently as the name
is embedded one level deeper"""
phyloxmlTaxoNames = {
"common_name" : "",
"scientific_name" : "",
"code" : ""
}
for child in node:
childTag = self.cleanTag(child.tag)
if childTag in phyloxmlTaxoNames:
return child.text
return ""
nodeName = ""
for child in node:
childTag = self.cleanTag(child.tag)
if childTag == "name" :
nodeName = child.text
break
elif childTag == "taxonomy":
nodeName = getTagFromTaxonomyNode(child)
break
return nodeName
def _makeInternalNode(self, internalNode, depth=0):
""" Makes an internal node from an element object that is guranteed to be a parent node.
Gets the value of interests like events and appends it to a custom node object that will be passed to PhyloTree to make nodes
"""
node = {}
for child in internalNode:
childTag = self.cleanTag(child.tag)
if childTag == "clade":
continue
elif childTag in self.tagsOfInterest:
if childTag == "events": # events is nested 1 more level deeper than others
key, text = "events", self.cleanTag(child[0].tag)
else:
key = self.tagsOfInterest[childTag]
text = child.text
node[key] = text
return self.phyloTree.makeNode(self._getNodeName(internalNode, depth), **node)