Source code for drtsans.mono.spice_xml_parser

"""
Module contains class and method to parse SPICE SANS XML file for DAS sample logs.
"""
from xml.etree import ElementTree
import numpy as np


[docs] class SpiceXMLParser(object): """ Class to parse SPICE SANS data file in XML format """ def __init__(self, spice_xml_name): """ Parameters ---------- spice_xml_name: str SPICE XML file """ # Store file name for reference self._spice_name = spice_xml_name # open the file self._xml_file = open(spice_xml_name, "r") # parse self._xml_root = ElementTree.parse(self._xml_file).getroot()
[docs] def close(self): """Close the opened XML file Returns ------- """ if self._xml_file is not None: self._xml_file.close()
[docs] def get_xml_node(self, node_name, required_attribs=None): """Get an XML node by its name regardless its level in XML tree Parameters ---------- node_name: str Name of the XML node to retrieve required_attribs: dict, None required attributes for the node Returns ------- xlm.etree.Element """ # Most of the node in SPICE XML file are in 2nd level xml_node_list = self._xml_root.findall(f".//{node_name}") # Only allow unique solution if len(xml_node_list) == 0: raise KeyError(f"SPICE file {self._spice_name}: XML node {node_name} does not exist.") # Check required attributes if required_attribs is not None: filtered_nodes = list() # filter for xml_node in xml_node_list: is_good = True for attr_name, attr_value in required_attribs.items(): if xml_node.attrib[attr_name] != attr_value: is_good = False break if is_good: filtered_nodes.append(xml_node) # replace xml_node_list = filtered_nodes # check whether it is unique solution if len(xml_node_list) > 1: raise RuntimeError(f"XML node {node_name} is not unique") return xml_node_list[0]
[docs] def get_node_value(self, node_name, value_type): """Get an XML node value regardless of the level of the node in the XML tree Parameters ---------- node_name: str Name of the XML node to retrieve value_type: type type to cast the value Returns ------- tuple value, unit """ value_type = ( value_type if type(value_type) is type else { "str": np.string_, "string": np.string_, "float": float, "double": float, "int": int, "integer": int, }[value_type.lower()] ) if node_name == "attenuator": # Attenuator is special value, units = self._read_attenuator() else: # regular node # Get node xml_node = self.get_xml_node(node_name) # Get value str_value = xml_node.text # Get unit if "units" in xml_node.attrib: units = xml_node.attrib["units"] else: units = None value = value_type(str_value) return value, units
def _read_attenuator(self): """Use this attenuator_pos and the attribute pos="open" Returns ------- """ # get attenuator position node xml_node = self.get_xml_node("attenuator_pos", required_attribs={"pos": "open"}) value = float(xml_node.text) unit = xml_node.attrib["units"] return value, unit