Source code for tvb.adapters.uploaders.brco.parser

# -*- coding: utf-8 -*-
#
#
# TheVirtualBrain-Framework Package. This package holds all Data Management, and 
# Web-UI helpful to run brain-simulations. To use it, you also need to download
# TheVirtualBrain-Scientific Package (for simulators). See content of the
# documentation-folder for more details. See also http://www.thevirtualbrain.org
#
# (c) 2012-2023, Baycrest Centre for Geriatric Care ("Baycrest") and others
#
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this
# program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#   CITATION:
# When using The Virtual Brain for scientific publications, please cite it as explained here:
# https://www.thevirtualbrain.org/tvb/zwei/neuroscience-publications
#
#

"""
.. moduleauthor:: Lia Domide <lia.domide@codemart.ro>
"""

import xml.dom.minidom
from xml.dom.minidom import Node
from tvb.basic.logger.builder import get_logger
from tvb.core.adapters.exceptions import ParseException
from tvb.adapters.datatypes.db.annotation import AnnotationTerm


[docs]class XMLParser(object): """ Parser for XML with Connectivity annotations """ LOGGER = get_logger(__name__) ATTR_TVB_ID = "id" ATTR_TVB_LABEL = "label" PREFIX_TVB_ID = "http://thevirtualbrain.org#" PREFIX_LEFT = ["l", "L", "left", "Left"] PREFIX_RIGHT = ["r", "R", "right", "Right"] ATTR_ONTOLOGY_URI = "uri" ATTR_ONTOLOGY_RELATION = "relation" ATTR_ONTOLOGY_LABEL = "label" ATTR_ONTOLOGY_SYN = "synonym" ATTR_ONTOLOGY_DEFINITION = "definition" def __init__(self, xml_file, region_labels): self.doc_xml = xml.dom.minidom.parse(xml_file) self.connectivity_labels = [rl.lower() for rl in region_labels] self.last_id = 0 def _generate_new_id(self): self.last_id += 1 return self.last_id def _find_region_idxs(self, region_label): """ Find IDX in Connectivity based on label read from XML :param region_label: Label ar read from XML (including PREFIX_TVB_ID) :return: (left_hemisphere, right_hemisphere_idx) :raise: ParseException in case of not match """ short_name = region_label.lower().replace(self.PREFIX_TVB_ID, "") left_idx = [self.connectivity_labels.index(prefix + short_name) for prefix in self.PREFIX_LEFT if prefix + short_name in self.connectivity_labels] right_idx = [self.connectivity_labels.index(prefix + short_name) for prefix in self.PREFIX_RIGHT if prefix + short_name in self.connectivity_labels] if len(left_idx) > 0 and len(right_idx) > 0: return left_idx[0], right_idx[0] raise ParseException("Could not match regionID '%s' from XML with the chosen connectivity" % region_label) def _parse_ontology_children(self, parent_node, parent_term_id, region_left, region_right): """ To be called recursively, for processing OntologyTerm XML tags. """ result = [] for ont_node in parent_node.childNodes: if ont_node.nodeType != Node.ELEMENT_NODE: continue ont_uri = ont_node.getAttribute(self.ATTR_ONTOLOGY_URI) ont_relation = ont_node.getAttribute(self.ATTR_ONTOLOGY_RELATION) ont_label = ont_node.getAttribute(self.ATTR_ONTOLOGY_LABEL) ont_syn = ont_node.getAttribute(self.ATTR_ONTOLOGY_SYN) ont_definition = ont_node.getAttribute(self.ATTR_ONTOLOGY_DEFINITION) # if len(ont_syn) > 0 and ont_syn[:len(ont_syn) / 2] == ont_syn[len(ont_syn) / 2 + 1:]: # ont_syn = ont_syn[:len(ont_syn) / 2] try: # Check if it is a TVB region syn_left, syn_right = self._find_region_idxs(ont_uri) ont_term = AnnotationTerm(self._generate_new_id(), parent_term_id, region_left, region_right, ont_relation, ont_label, ont_definition, ont_syn, ont_uri, syn_left, syn_right) except ParseException: ont_term = AnnotationTerm(self._generate_new_id(), parent_term_id, region_left, region_right, ont_relation, ont_label, ont_definition, ont_syn, ont_uri) # Call recursively for all child nodes child_terms = self._parse_ontology_children(ont_node, ont_term.id, region_left, region_right) result.append(ont_term) result.extend(child_terms) return result
[docs] def read_annotation_terms(self): """ Process XML file. :return List of AnnotationTerm instances. """ result = [] for tvb_node in self.doc_xml.lastChild.childNodes: if tvb_node.nodeType != Node.ELEMENT_NODE: continue tvb_id = tvb_node.getAttribute(self.ATTR_TVB_ID) tvb_label = tvb_node.getAttribute(self.ATTR_TVB_LABEL) self.LOGGER.debug("Processing region %s:%s" % (tvb_id, tvb_label)) region_left, region_right = self._find_region_idxs(tvb_id) self.LOGGER.debug("Matched %s == (%d, %d)" % (tvb_label, region_left, region_right)) ont_terms = self._parse_ontology_children(tvb_node, -1, region_left, region_right) result.extend(ont_terms) return result