Package data :: Module relax_xml
[hide private]
[frames] | no frames]

Source Code for Module data.relax_xml

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2008-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """Module containing generic fns for creation and parsing of XML representations of python objects.""" 
 25   
 26  # Python module imports. 
 27  import numpy 
 28  from numpy import set_printoptions, array, float32, float64, inf, nan, ndarray, zeros 
 29  try: 
 30      from numpy import float16 
 31  except ImportError: 
 32      float16 = float32    # Support for old numpy versions. 
 33  try: 
 34      from numpy import float128 
 35  except ImportError: 
 36      float128 = float64    # Support for 32-bit numpy versions. 
 37  from re import search 
 38  from string import strip 
 39   
 40  # Modify numpy for better output of numbers and structures. 
 41  set_printoptions(precision=15, threshold=nan) 
 42   
 43  # relax module imports. 
 44  import arg_check 
 45  from float import floatAsByteArray, packBytesAsPyFloat 
 46  from relax_errors import RelaxError 
 47   
 48   
49 -def fill_object_contents(doc, elem, object=None, blacklist=[]):
50 """Place all simple python objects into the XML element namespace. 51 52 @param doc: The XML document object. 53 @type doc: xml.dom.minidom.Document instance 54 @param elem: The element to add all python objects to. 55 @type elem: XML element object 56 @keyword object: The python class instance containing the objects to add. 57 @type object: instance 58 @keyword blacklist: A list of object names to exclude. 59 @type blacklist: list of str 60 """ 61 62 # Loop over the elements of the object. 63 for name in dir(object): 64 # Skip blacklisted objects. 65 if name in blacklist: 66 continue 67 68 # Skip special objects. 69 if search("^_", name): 70 continue 71 72 # Only pack objects in the __mod_attr__ list, if that list exists. 73 if hasattr(object, '__mod_attr__') and name not in object.__mod_attr__: 74 continue 75 76 # Create a new element for this object, and add it to the main element. 77 sub_elem = doc.createElement(name) 78 elem.appendChild(sub_elem) 79 80 # Get the sub-object. 81 subobj = getattr(object, name) 82 83 # Convert to XML. 84 object_to_xml(doc, sub_elem, value=subobj)
85 86
87 -def node_value_to_python(elem):
88 """Convert the node value to a python expression. 89 90 @param elem: The XML element. 91 @type elem: xml.dom.minidom.Element instance 92 """ 93 94 # Remove whitespace. 95 val = strip(elem.nodeValue) 96 97 # Convert to python and return. 98 return eval(val)
99 100
101 -def object_to_xml(doc, elem, value=None):
102 """Convert the given value into an XML form. 103 104 @param doc: The XML document object. 105 @type doc: xml.dom.minidom.Document instance 106 @param elem: The element to add the Python objects to. 107 @type elem: XML element object 108 @keyword value: The Python object to convert. 109 @type value: anything 110 """ 111 112 # Add the text value to the sub element. 113 val_elem = doc.createElement('value') 114 elem.appendChild(val_elem) 115 val_elem.appendChild(doc.createTextNode(repr(value))) 116 117 # The object type. 118 if value == None: 119 py_type = 'None' 120 elif isinstance(value, bool): 121 py_type = 'bool' 122 elif isinstance(value, str): 123 py_type = 'str' 124 elif isinstance(value, float): 125 py_type = 'float' 126 elif isinstance(value, int): 127 py_type = 'int' 128 elif isinstance(value, list): 129 py_type = 'list' 130 elif isinstance(value, dict): 131 py_type = 'dict' 132 elif isinstance(value, ndarray): 133 py_type = repr(value.dtype) 134 else: 135 raise RelaxError("Unknown type for the value '%s'." % value) 136 137 # Store as an attribute. 138 elem.setAttribute('type', py_type) 139 140 # Store floats as IEEE-754 byte arrays (for full precision storage). 141 if arg_check.check_float(value): 142 val_elem = doc.createElement('ieee_754_byte_array') 143 elem.appendChild(val_elem) 144 val_elem.appendChild(doc.createTextNode(repr(floatAsByteArray(value)))) 145 146 # Store lists with floats as IEEE-754 byte arrays. 147 elif (isinstance(value, list) or isinstance(value, ndarray)) and len(value) and arg_check.check_float(value[0]): 148 # The converted list. 149 ieee_obj = [] 150 conv = False 151 for i in range(len(value)): 152 # A float. 153 if arg_check.check_float(value[i]): 154 ieee_obj.append(floatAsByteArray(value[i])) 155 conv = True 156 157 # All other data. 158 else: 159 ieee_obj.append(value) 160 161 # Store as XML. 162 if conv: 163 # The element. 164 val_elem = doc.createElement('ieee_754_byte_array') 165 elem.appendChild(val_elem) 166 167 # Add the text. 168 val_elem.appendChild(doc.createTextNode(repr(ieee_obj))) 169 170 # Store dictionaries with floats as IEEE-754 byte arrays. 171 elif py_type == 'dict': 172 # The converted dict. 173 ieee_obj = {} 174 conv = False 175 for key in value.keys(): 176 if arg_check.check_float(value[key]): 177 ieee_obj[key] = floatAsByteArray(value[key]) 178 conv = True 179 180 # Store as XML. 181 if conv: 182 # The element. 183 val_elem = doc.createElement('ieee_754_byte_array') 184 elem.appendChild(val_elem) 185 186 # Add the text. 187 val_elem.appendChild(doc.createTextNode(repr(ieee_obj))) 188 189 # Store matrices of floats as IEEE-754 byte arrays. 190 elif arg_check.is_float_matrix(value, raise_error=False): 191 # The converted list. 192 ieee_obj = [] 193 for i in range(len(value)): 194 ieee_obj.append([]) 195 for j in range(len(value[i])): 196 ieee_obj[-1].append(floatAsByteArray(value[i][j])) 197 198 # The element. 199 val_elem = doc.createElement('ieee_754_byte_array') 200 elem.appendChild(val_elem) 201 202 # Add the text. 203 val_elem.appendChild(doc.createTextNode(repr(ieee_obj)))
204 205
206 -def xml_to_object(elem, base_object=None, set_fn=None, file_version=1, blacklist=[]):
207 """Convert the XML elements into python objects, and place these into the base object. 208 209 @param elem: The element to extract all python objects from. 210 @type elem: xml.dom.minidom.Element instance 211 @keyword base_object: The python class instance to place the objects into. 212 @type base_object: instance 213 @keyword set_fn: A function used to replace setattr for placing the object into the base 214 object. 215 @type set_fn: function 216 @keyword file_version: The relax XML version of the XML file. 217 @type file_version: int 218 @keyword blacklist: A list of object names to exclude. 219 @type blacklist: list of str 220 """ 221 222 # Loop over the nodes of the element 223 for node in elem.childNodes: 224 # Skip empty nodes. 225 if node.localName == None: 226 continue 227 228 # The name of the python object to recreate. 229 name = str(node.localName) 230 231 # Skip blacklisted objects. 232 if name in blacklist: 233 continue 234 235 # The value - original file version. 236 if file_version == 1: 237 # IEEE-754 floats (for full precision restoration). 238 ieee_array = node.getAttribute('ieee_754_byte_array') 239 if ieee_array: 240 value = packBytesAsPyFloat(eval(ieee_array)) 241 242 # Get the node contents. 243 else: 244 value = node_value_to_python(node.childNodes[0]) 245 246 # The value - second file version. 247 elif file_version == 2: 248 # Get the type. 249 py_type = node.getAttribute('type') 250 if not search('dtype', py_type): 251 py_type = eval(py_type) 252 253 # Loop over the info nodes of the Python object. 254 ieee_value = None 255 for sub_node in node.childNodes: 256 # Get the value. 257 if sub_node.localName == 'value': 258 value = node_value_to_python(sub_node.childNodes[0]) 259 260 # IEEE-754 floats (for full precision restoration). 261 if sub_node.localName == 'ieee_754_byte_array': 262 ieee_value = node_value_to_python(sub_node.childNodes[0]) 263 264 # Use IEEE-754 floats when possible. 265 if ieee_value: 266 # Simple float. 267 if py_type == float: 268 value = packBytesAsPyFloat(ieee_value) 269 270 # Convert dictionaries. 271 elif py_type == dict: 272 for key in ieee_value: 273 value[key] = packBytesAsPyFloat(ieee_value[key]) 274 275 # Convert lists. 276 elif py_type == list: 277 # Loop over the first dimension. 278 for i in range(len(value)): 279 # List of lists. 280 if isinstance(value[i], list) or isinstance(value[i], ndarray): 281 for j in range(len(value[i])): 282 value[i][j] = packBytesAsPyFloat(ieee_value[i][j]) 283 284 # Normal list. 285 else: 286 value[i] = packBytesAsPyFloat(ieee_value[i]) 287 288 # Numpy types. 289 elif search('dtype', py_type): 290 # The specific type. 291 numpy_type = getattr(numpy, py_type[7:-2]) 292 293 # Build a new array of the correct type. 294 value = zeros(value.shape, numpy_type) 295 296 # A matrix. 297 if isinstance(value[0], ndarray): 298 for i in range(len(value)): 299 for j in range(len(value[i])): 300 value[i, j] = packBytesAsPyFloat(ieee_value[i][j]) 301 302 # A vector. 303 else: 304 for i in range(len(value)): 305 value[i] = packBytesAsPyFloat(ieee_value[i]) 306 307 # Set the value. 308 setattr(base_object, name, value)
309