Author: bugman
Date: Mon Dec 8 17:40:35 2014
New Revision: 27022
URL: http://svn.gna.org/viewcvs/relax?rev=27022&view=rev
Log:
Full support for saving and loading nmrglue data in the relax data store.
This is for XML formatted relax state and results files. The implementation
was complicated as a
special data_store.data_classes.RelaxDictType object with to_xml() and
from_xml() method has been
introduced to handle custom dictionary-type objects.
The cdp.nmrglue object is the data_store.nmrglue.Nmrglue_dict object which
inherits from the
RelaxDictType object. This has elements set to data_store.nmrglue.Nmrglue
instances. This Nmrglue
object inherits from data_store.data_classes.Element, however the to_xml() and
from_xml() methods
have been copied and modified for this special object. This Nmrglue container
has three main
attributes, the nmrglue dic, udic, and data objects.
The Nmrglue to_xml() and from_xml() methods handle the 'data' object by
encoding and decoding it in
the Base64 string format. All the other objects are handled by the
fill_object_contents() or
xml_to_object() functions of lib.xml.
Modified:
branches/nmrglue/data_store/data_classes.py
branches/nmrglue/data_store/nmrglue.py
branches/nmrglue/data_store/pipe_container.py
branches/nmrglue/pipe_control/nmrglue.py
Modified: branches/nmrglue/data_store/data_classes.py
URL:
http://svn.gna.org/viewcvs/relax/branches/nmrglue/data_store/data_classes.py?rev=27022&r1=27021&r2=27022&view=diff
==============================================================================
--- branches/nmrglue/data_store/data_classes.py (original)
+++ branches/nmrglue/data_store/data_classes.py Mon Dec 8 17:40:35 2014
@@ -162,6 +162,110 @@
# Execute the object to_xml() methods.
for obj in to_xml_list:
obj.to_xml(doc, cont_element)
+
+
+
+class RelaxDictType(dict):
+ """An empty dict type container."""
+
+ def __init__(self):
+ """Initialise some class variables."""
+
+ # Execute the base class __init__() method.
+ super(RelaxDictType, self).__init__()
+
+ # Some generic initial names.
+ self.dict_name = 'relax_dict'
+ self.dict_desc = 'relax dict container'
+ self.element_name = 'relax_dict_element'
+ self.element_desc = 'relax container'
+
+ # Blacklisted objects.
+ self.blacklist = []
+
+
+ def from_xml(self, super_node, file_version=1):
+ """Recreate the data structure from the XML node.
+
+ @param super_node: The XML nodes.
+ @type super_node: xml.dom.minicompat.Element instance
+ @keyword file_version: The relax XML version of the XML file.
+ @type file_version: int
+ """
+
+ # Recreate all the data structures.
+ xml_to_object(super_node, self, file_version=file_version,
blacklist=self.blacklist)
+
+ # Get the individual elements.
+ nodes = super_node.getElementsByTagName(self.element_name)
+
+ # Loop over the child nodes (each element).
+ for node in nodes:
+ # Get the key.
+ key = str(node.getAttribute('key'))
+ key = key.strip("'")
+
+ # Add the data container.
+ self.add_item(key=key, node=node, file_version=file_version)
+
+
+ def to_xml(self, doc, element):
+ """Create an XML element for the dict data structure.
+
+ @param doc: The XML document object.
+ @type doc: xml.dom.minidom.Document instance
+ @param element: The element to add the dict data structure XML element
to.
+ @type element: XML element object
+ """
+
+ # Create the element and add it to the higher level element.
+ dict_element = doc.createElement(self.dict_name)
+ element.appendChild(dict_element)
+
+ # Set the dict attributes.
+ dict_element.setAttribute('desc', self.dict_desc)
+
+ # Blacklisted objects.
+ blacklist = ['dict_name', 'dict_desc', 'element_name', 'element_desc',
'blacklist'] + list(self.__dict__.keys()) + list(RelaxListType.__dict__.keys())
+ list(self.__class__.__dict__.keys()) + list(dict.__dict__.keys()) +
list(dict.__dict__.keys())
+
+ # Add all simple python objects within the list to the list element.
+ fill_object_contents(doc, dict_element, object=self,
blacklist=blacklist)
+
+ # Loop over the keys.
+ for key in self:
+ # Create an XML element for each container.
+ dict_item_element = doc.createElement(self.element_name)
+ dict_element.appendChild(dict_item_element)
+ dict_item_element.setAttribute('key', repr(key))
+ dict_item_element.setAttribute('desc', self.element_desc)
+
+ # The element has its own to_xml() method.
+ if hasattr(self[key], 'to_xml'):
+ self[key].to_xml(doc, dict_item_element)
+
+ # Normal element.
+ else:
+ # Blacklisted objects.
+ blacklist = list(self[key].__class__.__dict__.keys())
+
+ # Add objects which have to_xml() methods.
+ for name in dir(self[key]):
+ # Skip blacklisted objects.
+ if name in blacklist:
+ continue
+
+ # Skip special objects.
+ if search('^_', name):
+ continue
+
+ # Execute any to_xml() methods, and add that object to the
blacklist.
+ obj = getattr(self[key], name)
+ if hasattr(obj, 'to_xml'):
+ obj.to_xml(doc, list_item_element)
+ blacklist = blacklist + [name]
+
+ # Add all simple python objects within the container to the
XML element.
+ fill_object_contents(doc, dict_item_element, object=self[key],
blacklist=blacklist)
Modified: branches/nmrglue/data_store/nmrglue.py
URL:
http://svn.gna.org/viewcvs/relax/branches/nmrglue/data_store/nmrglue.py?rev=27022&r1=27021&r2=27022&view=diff
==============================================================================
--- branches/nmrglue/data_store/nmrglue.py (original)
+++ branches/nmrglue/data_store/nmrglue.py Mon Dec 8 17:40:35 2014
@@ -25,14 +25,43 @@
# Python module imports.
from base64 import b64encode, decodestring
from numpy import float32, frombuffer
+from re import search
# relax module imports.
-from data_store.data_classes import Element
-from lib.xml import object_to_xml, xml_to_object
+from data_store.data_classes import Element, RelaxDictType
+from lib.xml import fill_object_contents, xml_to_object
class Nmrglue(Element):
"""Container for the global GUI data structures."""
+
+ def __repr__(self):
+ # Header.
+ text = "%-25s%-100s\n\n" % ("Data structure", "Value")
+
+ # Data structures.
+ for name in dir(self):
+ # Skip Nmrglue and derived class methods.
+ if name in Nmrglue.__dict__ or name in self.__class__.__dict__:
+ continue
+
+ # Skip special objects.
+ if search("^_", name):
+ continue
+
+ # Get the object.
+ obj = getattr(self, name)
+
+ # The data.
+ if name == 'data':
+ obj = obj.shape
+
+ # Generate the text.
+ text = text + "%-25s %-100s\n" % (name, repr(obj))
+
+ # Return the lot.
+ return text
+
def __init__(self, dic=None, udic=None, data=None):
"""Initialise the container info.
@@ -52,6 +81,7 @@
self.dic = dic
self.udic = udic
self.data = data
+ self.element_name = 'nmrglue_container'
def from_xml(self, nmrglue_node, file_version=1):
@@ -67,21 +97,25 @@
data_nodes = nmrglue_node.getElementsByTagName('data')
# Loop over the info nodes of the Python object.
- for sub_node in node.childNodes:
- # Get the value.
- if sub_node.localName == 'value':
+ for sub_node in nmrglue_node.childNodes:
+ # Get the numpy data.
+ if sub_node.localName == 'data':
+ # Get the value node.
+ value_node = sub_node.getElementsByTagName('value')[0]
+
# Convert from Base64 to numpy.float32.
- buffer = decodestring(sub_node.childNodes[0])
- self.data = frombuffer(buffer, dtype=np.float32)
+ value = value_node.childNodes[0].nodeValue.strip()
+ buffer = decodestring(value)
+ self.data = frombuffer(buffer, dtype=float32)
# The shape attribute.
- shape = eval(node.getAttribute('shape'))
+ shape = eval(sub_node.getAttribute('shape'))
# Reshape the data.
- self.data.reshape(shape)
+ self.data = self.data.reshape(shape)
# Recreate all the other data structures.
- xml_to_object(gui_node, self, file_version=file_version,
blacklist=['data'])
+ xml_to_object(nmrglue_node, self, file_version=file_version,
blacklist=['data'])
def to_xml(self, doc, element):
@@ -93,18 +127,69 @@
@type element: XML element object
"""
- # Call the parent class method for all but the data variable.
- self.blacklist.append('data')
- super(Nmrglue, self).to_xml(doc, element)
+ # Create an XML element for the numpy data.
+ data_elem = doc.createElement('data')
+ element.appendChild(data_elem)
# Convert the data into a Base64 string.
string = b64encode(self.data)
# Store the value as the string.
val_elem = doc.createElement('value')
- element.appendChild(val_elem)
+ data_elem.appendChild(val_elem)
val_elem.appendChild(doc.createTextNode(string))
# Set the type and shape as attributes.
- element.setAttribute('type', 'base64, numpy.float32')
- element.setAttribute('shape', repr(self.data.shape))
+ data_elem.setAttribute('type', 'base64, numpy.float32')
+ data_elem.setAttribute('shape', repr(self.data.shape))
+
+ # Add all simple Python objects within the container to the XML
element.
+ fill_object_contents(doc, element, object=self, blacklist=['name',
'desc', 'blacklist', 'data', 'is_empty', 'element_name'] +
list(Nmrglue.__dict__.keys()) + list(self.__class__.__dict__.keys()))
+
+
+
+class Nmrglue_dict(RelaxDictType):
+ """The main storage structure for all nmrglue data."""
+
+ def __init__(self):
+ """Initialise the class."""
+
+ # Call the base class method.
+ super(Nmrglue_dict, self).__init__()
+
+ # The metadata.
+ self.dict_name = 'nmrglue'
+ self.dict_desc = 'main storage for nmrglue data'
+ self.element_name = 'nmrglue_container'
+ self.element_desc = 'nmrglue container'
+
+ # Blacklist.
+ self.blacklist.append('nmrglue_container')
+
+
+ def from_xml(self, super_node, file_version=1):
+ """Recreate the data structure from the XML node.
+
+ @param super_node: The XML nodes.
+ @type super_node: xml.dom.minicompat.Element instance
+ @keyword file_version: The relax XML version of the XML file.
+ @type file_version: int
+ """
+
+ # Recreate all the data structures.
+ xml_to_object(super_node, self, file_version=file_version,
blacklist=self.blacklist)
+
+ # Get the individual elements.
+ nodes = super_node.getElementsByTagName(self.element_name)
+
+ # Loop over the child nodes (each element).
+ for node in nodes:
+ # Get the key.
+ key = str(node.getAttribute('key'))
+ key = key.strip("'")
+
+ # Create a new element.
+ self[key] = Nmrglue()
+
+ # Recreate from the XML.
+ self[key].from_xml(node, file_version=file_version)
Modified: branches/nmrglue/data_store/pipe_container.py
URL:
http://svn.gna.org/viewcvs/relax/branches/nmrglue/data_store/pipe_container.py?rev=27022&r1=27021&r2=27022&view=diff
==============================================================================
--- branches/nmrglue/data_store/pipe_container.py (original)
+++ branches/nmrglue/data_store/pipe_container.py Mon Dec 8 17:40:35 2014
@@ -31,6 +31,7 @@
from data_store.exp_info import ExpInfo
from data_store.interatomic import InteratomList
from data_store.mol_res_spin import MoleculeList
+from data_store.nmrglue import Nmrglue, Nmrglue_dict
from data_store.prototype import Prototype
from lib.errors import RelaxFromXMLNotEmptyError
from lib.structure.internal.object import Internal
@@ -224,6 +225,15 @@
# Fill its contents.
self.align_tensors.from_xml(align_tensor_nodes[0],
file_version=file_version)
+ # Get the nmrglue data nodes and, if they exist, fill the contents.
+ nmrglue_nodes = pipe_node.getElementsByTagName('nmrglue')
+ if nmrglue_nodes:
+ # Create the data container.
+ self.nmrglue = Nmrglue_dict()
+
+ # Fill its contents.
+ self.nmrglue.from_xml(nmrglue_nodes[0], file_version=file_version)
+
# Recreate the interatomic data structure (this needs to be before the
'mol' structure as the backward compatibility hooks can create interatomic data
containers!).
interatom_nodes = pipe_node.getElementsByTagName('interatomic')
self.interatomic.from_xml(interatom_nodes, file_version=file_version)
@@ -303,7 +313,7 @@
global_element = doc.createElement('global')
element.appendChild(global_element)
global_element.setAttribute('desc', 'Global data located in the top
level of the data pipe')
- fill_object_contents(doc, global_element, object=self,
blacklist=['align_tensors', 'diff_tensor', 'exp_info', 'interatomic',
'hybrid_pipes', 'mol', 'pipe_type', 'structure'] +
list(self.__class__.__dict__.keys()))
+ fill_object_contents(doc, global_element, object=self,
blacklist=['align_tensors', 'diff_tensor', 'exp_info', 'interatomic',
'hybrid_pipes', 'mol', 'pipe_type', 'structure', 'nmrglue'] +
list(self.__class__.__dict__.keys()))
# Hybrid info.
self.xml_create_hybrid_element(doc, element)
@@ -319,6 +329,10 @@
# Add the alignment tensor data.
if hasattr(self, 'align_tensors'):
self.align_tensors.to_xml(doc, element)
+
+ # Add the experimental information.
+ if hasattr(self, 'nmrglue'):
+ self.nmrglue.to_xml(doc, element)
# Add the molecule-residue-spin data.
self.mol.to_xml(doc, element, pipe_type=pipe_type)
Modified: branches/nmrglue/pipe_control/nmrglue.py
URL:
http://svn.gna.org/viewcvs/relax/branches/nmrglue/pipe_control/nmrglue.py?rev=27022&r1=27021&r2=27022&view=diff
==============================================================================
--- branches/nmrglue/pipe_control/nmrglue.py (original)
+++ branches/nmrglue/pipe_control/nmrglue.py Mon Dec 8 17:40:35 2014
@@ -23,30 +23,32 @@
"""Module for the using of nmrglue."""
# relax module imports.
+from data_store.nmrglue import Nmrglue, Nmrglue_dict
from lib.errors import RelaxError
from lib.software.nmrglue import contour_plot, hist_plot, read_spectrum
from pipe_control.pipes import check_pipe
from pipe_control.spectrum import check_spectrum_id, delete
-def add_nmrglue_data(object_name=None, nmrglue_id=None, nmrglue_data=None):
+def add_nmrglue_data(nmrglue_id=None, dic=None, udic=None, data=None):
"""Add the nmrglue data to the data store under the the given object_name
within a dictionary with nmrglue_id key.
- @keyword object_name: The object name for where to store the data.
As cdp.object_name.
- @type object_name: str
- @keyword nmrglue_id: The dictionary key, to access the data. As As
cdp.object_name['nmrglue_id']
- @type nmrglue_id: str
- @keyword nmrglue_data: The type of data depending on called function.
- @type nmrglue_data: depend on function
+ @keyword nmrglue_id: The dictionary key, to access the data as
cdp.nmrglue['nmrglue_id'].
+ @type nmrglue_id: str
+ @keyword dic: The dic structure from nmrglue.
+ @type dic: dict
+ @keyword udic: The dic structure from nmrglue.
+ @type udic: dict
+ @keyword data: The type of data depending on called function.
+ @type data: depend on function
"""
# Initialise the structure, if needed.
- if not hasattr(cdp, object_name):
- setattr(cdp, object_name, {})
+ if not hasattr(cdp, 'nmrglue'):
+ cdp.nmrglue = Nmrglue_dict()
# Add the data under the dictionary key.
- obj_dict = getattr(cdp, object_name)
- obj_dict[nmrglue_id] = nmrglue_data
+ cdp.nmrglue[nmrglue_id] = Nmrglue(dic=dic, udic=udic, data=data)
def add_nmrglue_id(nmrglue_id=None):
@@ -130,9 +132,7 @@
dic, udic, data = read_spectrum(file=file_i, dir=dir)
# Store the data.
- add_nmrglue_data(object_name='nmrglue_dic', nmrglue_id=nmrglue_id_i,
nmrglue_data=dic)
- add_nmrglue_data(object_name='nmrglue_udic', nmrglue_id=nmrglue_id_i,
nmrglue_data=udic)
- add_nmrglue_data(object_name='nmrglue_data', nmrglue_id=nmrglue_id_i,
nmrglue_data=data)
+ add_nmrglue_data(nmrglue_id=nmrglue_id_i, dic=dic, udic=udic,
data=data)
def plot_contour(nmrglue_id=None, contour_start=30000., contour_num=20,
contour_factor=1.20, ppm=True, show=False):
_______________________________________________
relax (http://www.nmr-relax.com)
This is the relax-commits mailing list
[email protected]
To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-commits