xmlfesatools

Python library with tools for analysis of FESA XML files

Usage: from pylib.fesa import xmlfesatools

The library contains functions and classes to navigate in FESA XML files, mainly instance files but also design files. In addition, it contains tools to fetch files from the FESA web-server.

== PAGE UNDER DEVELOPMENT ==

Class XmlFile : Abstraction of FESA XML-Structures

The class XmlFile represents FESA XML-files. It provides methods to navigate in the XML-tree and a method to write the XML-tree back to disk. Specifics of FESA instance files and FESA design files are handled in subclasses xmlfesatools.XmlInstFile (see here) and xmlfesatools.XmlDesignFile (see here).

The fesatools.XmlFile internally uses the Python lxml.etree toolset. The fesatools.XmlFile class holds the XML content as a lxml.etree._ElementTree element tree, which is available by the method get_inst_tree() . The method get_root_element() returns the root element of this tree.

Representation of Hierarchy by Path-Strings

The xmlfesatools.XmlFile class provides methods to navigate in the element tree. These methods operate with path-variables (strings). They represent the XML hierarchy, separating the elements by dots. The string
"child1.child2"

means, starting with the root element, the child element with name child1 and its child element with the name child2. The root element of this relative path is given by the !baseElement parameter, which is the lxml.etree.Element root of the relative XML tree. The default value for !baseElement is the root element of the XML file.

For access to nodes in the XML-tree, three methods are provided:
get_element(path, baseElement=None)=
return =lxml.etree.Element according to path
get_all_elements(path, baseElement=None)=
return all =lxml.etree.Element matching the path parameter
get_path(element, baseElement=None)=
return path of the =lxml.etree.Element, relative to the root element baseElement

Path elements may be nested to any level. Given
<root-element>
    <parent>
        <child>
            <grandchild>
            </grandchild>
        </child>
    </parent>
</root-element>

The sub node (<grandchild>) is accessed by the location string "parent.child.grandchild", which is relative to the root-element (unless otherwise given):

grandchild_node = get_element("parent.child.grandchild")

Identification of Elements with Attributes

Often an XML element has child nodes with identical tag names, which are identified by different attribute values, like
<root-element>
    <parent>
        <child name="AAA">
        </child>
        <child name="BBB">
            <grandchild name="XXX"/>
            <grandchild name="YYY"/>
        </child>
        <child name="CCC">
        </child>
    </parent>
</root-element>

Such child nodes can be accessed by given the attribute name and value in paranthesis, like

child_node1 = get_element("parent.child[name=AAA]")

grandchild_node = get_element("parent.child[name=BBB].grandchild[name=XXX]")

Attribute names "name" can be omitted- The following two commands are equivalent to the upper ones:

child_node1 = get_element("parent.child[AAA]")

grandchild_node = get_element("parent.child[BBB].grandchild[XXX]")

Abbreviation of Path-Strings

Names in the path string can be abbreviated. Only the leading part of the tag's name has to be specified. Given only 'info' will find a tag like <information> . If a name matches, it is prefered. Given 'accelerator' will find <accelerator> if both tags <accelerator> and <acceleratorZone> exist, while only 'accelerato' will result in a multiple elements found error.

As an example, given a xmlfesatools.XmlInstFile inst, containing a node information as
<information>=
=<fesa-version>7.0.0</fesa-version>
</information>

a call of get_element('information.fesa') will return the lxml.etree.Element for this node which results in
>>> print get_element('info.fesa').text
7.0.0

Giving only the heading of a name is sufficient in most cases when a naming has to be given to locate or access data in the XML files.

To exclude name extension, most methods provide an optional parameter exact_match. If set to True, the path elements must exactly match the names in the XML structure.

Obtaining Path-Strings

The class XmlFile provides two methods to get path-strings:
get_extended_path(path_string, baseElement=None) :

resolves all abbreviations in the path strin, returns a path string with completed names
get_path(etree_element, baseElement=None) :

returns the path string of a lxml.etree.Element in the XML tree.

As an example, presently for the instance file on scuxl0250 (presently supplying PowerSupllyHebt _DU device GTS7KS1) would provide
>>> print inst.get_extended_path('classes.Power.devi[GTS7K].con')
classes.PowerSupply.device-instance[name=GTS7KS1].configuration

first accessing an lxml.etree.Element and then printing it's path would provide
>>> elem = inst.get_element('classes.Power.devi[GTS7K].con')
>>> inst.get_path(elem)
'classes.PowerSupply.device-instance[GTS7KS1].configuration'

Fild Child Nodes

The xmlfesatools module provides two methods to find child nodes in the XML tree.
get_child_elements(path, baseElement=None)

will return all child elements of the XML node which is addressed by path, als a list of xml.etree.Element.
get_child_paths(path, baseElement=None)

will return the paths addressing all child elements of the XML node which is addressed by path, als a list of strings.

Reading and Writing XML-FIles

Provided with the filename as a parameter, XML files are read from disk during instantiation of the XmlFile objects:
inst = 1XmlFile("~myworkspace/PowerSupplyRf_DU/src/test/scuxl0037/DeviceData_PowerSupplyRf_DU.instance")

In addition to reading files from disk, FESA XML files can be fetched from a central storage, see section web server.

To write the XML contents back to disk, the method write_file is provided:

write_file(self, file_name=None, backup= True)

The name of the file can be specified by parameter file_name . If no new name is given, the name is used from which the XML-data are read.

If the file already exists, up to three backups are created by adding ~, ~~ and ~~~ to the filename. Creation of backups can be suppressed by the optional parameter backup.

Structure-like Classes

Associated information should be combined in one place. For this purpose several classes are defined which provide the descriptive information by getter methods.

Class ConfigValue

The class ConfigValue holds the data of an instance file configuration parameter for a device, e.g. <configuration><acceleratorZone> .

def get_tag(self) : returns the name of the configuration parameter, e.g acceleratorZone
get_path() : returns the path of configuraiton parameter, relative to device node
e.g. configuration.acceleratorZone , setting.dcMode
get_val() : returns the value of a configuration parameter, e.g. 'GSI_HEBT'
get_dim() : returns the value of the entry <dim>, if exists
get_dim1() : returns the value of the entry <dim1>, if exists
get_dim2() ; returns the value of the entry <dim2>, if exists

Class DeviceNode

The class DeviceNode holds information for a device (a nomenclature) which is listed in the XML instance file. The information can be accessed by the methods:
get_name() : returns the nomenclature
get_class_name() returns the name of the FESA class the device belongs to
get_device_element() returns the xml.etree.Element for the XML entry <device-instance>
get_event_mapping_element() returns the xml.etree.Element for the XML entry <events-mapping> subnode of <device-instance> entry

Class EventConfiguration

The class combines data for event-configuration elements from the <events-mapping> event-mapping name.

The content can be accessed by the methods:
get_name() : returns the name of the event configuration
get_type() : returns the type of the event configuration, types are 'Timing', 'Timer', 'OnDemand', 'OnSubscription', ...
get_data() : returns description data for the event configuration

The return data of the get_data() method is a list of tuples (type, parameter) where type is a string and parameter a dictionary of name / value pairs, as described below.

    [(type, parameter), ...]

    type : string
        the type of the event data,
        e.g. hardware-event, timer-event, on-demand-event-source-ref, on-subscription-event

    parameter : dictionary {string : string, ...}
        key : string
            the name of the parameter,
            e.g. name, period, ...

        value : string
            the value of the parameter,
            e.g. name of the hardware-event, period of timer, ...

         examples:

         parameter-type             | key      | value
         ===========================+==========+======================
         hardware-event             | name     | CMD_FG_PREP#512
         ---------------------------+----------+----------------------
         timer                      | period   | 1000
         ---------------------------+----------+----------------------
         on-demand-event-source-ref | property | VoltageSetEventSource
         ---------------------------+----------+----------------------
         on-subscription-event      | context  |
                                    | device   | YRT1LD51H
                                    | property | Acquisition

Class LogicalEvent

The class holds, for a logical event, the event configurations (the mappings), e.g. the mapping to a timing hardware-event or to a timer. The information can be access by the methods:

get_name() : get the name of the logical event
get_class_name() : get the name of the FESA class for which the logical event is defined
get_configuration(name) : get the EventConfiguration object with the name name
get_configurations() : get a list of all EventConfiguration objects for the logical event

Class Property

get:name() Returns name of property
get_access() Returns access ("acquisition", "setting")
get_type() Returns type ("GSI-Reset-Property", GSI-Setting-Property", ...)

The XmlInstFile Class

The XmlInstFile class provides information of FESA instance files and methods to access characteristic parts of the files. A subset of the implemented methods is listed below. For full information use the Python help command.

The XmlInstFile is a subclass of the XmlFile class (see here).

Provide General Information

get_class_name(deviceName)
get_class_names(fesaClass='')
get_deploy_unit_name()
get_deploy_unit_version()
get_fec_name()
get_fesa_version()
get_server_name()

Access Device Nodes (lxml.etree.Element) and Device Parameters

get_device_names(fesaClass='', deviceName = '') returns all device names, matching fesaClass and deviceName
get_device_elements(deviceName = '', fesaClass='') returns lxml.etree.Element objects, matching deviceName and fesaClass
get_device_element(deviceName = '') returns the single lxml.etree.Element object which matches deviceName and fesaClass
get_device_node(deviceName) returns a xmlfesatools.DeviceNode object, containing some data for the device
get_device_value(deviceName, valuePath) returns a ConfigValue object, containing the content of a device's configuration parameter, located by path

A ConfigValue object represents a device's configuration parameter. It provides the value as a string and, if existing, the dimension(s). The output of the get_device_value method is demonstated with the parameters <configuration><acqValue> and <setting><dcMode> :
>>> print inst.get_device_value('YR10KH','con.acq')
value: {{CURRENT,-10.0,10.0,-10.0,10.0}} dim: 1
>>> print inst.get_device_value('YR10KH','set.dcMode')
value: false

Access Events-Mapping Entries

get_event_definitions()
get_event_configuration(className, eventName, eventSetting)
get_event_mapping(deviceName, evtName)
get_event_mapping_element(deviceName, eventName)
get_event_name(deviceName, eventName)
get_event_setting(deviceName, eventName)

The XmlDesignFile Class

The !XmlDesignClass provides some information from FESA design files. This is presently limited to information on RT-actions and on properties.

The XmlDesignFile is a subclass of the XmlFile class (see here).

Get General Information

get_class_name()
get_version()

Get Information on RT-Actions and Associated Events

get_rt_action_triggers() Returns a dictionary with names of all RT-actions with lists containing the associated logical event names
get_rt_action_name(rt_action) Returns full name which matches abbreviated RT-action name rt_action
get_all_rt_action_names(rt_action) Returns list of al RT-actin names matching given name rt_action
get_logical_events(rt_action) Returns list of names of all logical events associated with RT-action matching name rt_action

Get Property Information

get_properties(access = "") Returns dictionary, name of property with xmlfesatools.Property object (see class property)
get_global_properties(access = "") Returns global properties as dictionary, similar to get_properties
get_subset_properties(subset_name, access = "") Returns properties for subset subset_name, similar to get_properties
get_subsets(self) Returns dictionary, names of subset with list of all names of properties assigned to the subset

Web-Server Files

For each FESA deploy unit which is installed in the facility, a copy of the XML instance file as well as the XML design file used to generate the FESA class is hold on a web server. These files are stored in a zip-file container.

The naming of the container is according to <deploy-unit name>_<front-end name>.zip , e.g. PowerSupplyCry_DU_scuxl0142.zip . The zip-file container contains a directory with two files, the instance file and the design file. In the given example for scuxl0142 these are
  • PowerSupply.1.26.0.design
  • scuxl0142.instance
The Python class xmlfesatools.FesaWebServer represents the connection to the FESA web server.

Connection to the Web Server

For access to the web server, a class is provide which represents a connection to the web server:
ws = xmlfesatools.FesaWebServer()

Looking for Container Files

After a connection to the web server has been established, the names of the existing zip-files may be obtained.
ws.get_all_file_names() will return a list of the names all files which are hosted on the web server.

Given parts of the names of container files, lists of matching names can be obtained.
ws.get_file_names('PowerSupply') will return a list of container files comprizing at least all PowerSupply deploy units, while
ws.get_file_names('PowerSupply', 'kp2cu') will return a list like ['PowerSupplyDev_DU_kp2cu01.zip' 'PowerSupplyTestDev_DU_kp2cu01.zip']
ws.get_file_name('PowerSupply', 'scu', '142') will return a single file name, throwing an exception in case several file names match

Fetching FESA XML-Files

A web server zip container file may be obtained from the web server by
zip_file = ws.get_web_file('PowerSupply', 'scu', '0142')

The web server zip-file contains two FESA XML-files, the design file and the instance file. The xmlfesatools library provides tools to extract the XML files from the container. Extraction from the container will provide xmlfesatools.XmlInstFile and xmlfesatools.XmlDesignFile objects, which both inherit from xmlfesatools.XmlFile class.

The XML files can be extracted from the container by the extract_web_file method, which will return a list containing xmlfesatools.FesaWebFile structures:
xml_struct_list = ws.extract_web_file('PowerSupp', '0142')

The contianed FESA XML-files may be obtained directly by the methods get_xml_file, and especially get_xml_instance and get_xml_design methods:
xml_design = ws.get_xml_design('PowerSupp', '0142') .
will return a xmlfesatools.XmlDesignFile object
xml_instance = ws.get_xml_instance('PowerSupp', '0142') .
will return a xmlfesatools.XmlInstFile object

In some cases, the zip-file contains data for several FESA classes. In such cases, the desired FESA class can be selected by providing the optional parameter fesa_class:
ws.get_xml_design('CaenHv', 'sddsc016', fesa_class='CaenHvSYx527')

will return the file for CaenHvSYx527 and not for the also contained CaenHvSYx527Channel . The name of the FESA class can be abbreviated. In case several names match, as in the example, an exact match is preferred.
Topic revision: r19 - 07 Feb 2022, UdoKrause
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback