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

Source Code for Module data.pipe_container

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2007-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program 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 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Python module imports. 
 23  from re import match 
 24  from warnings import warn 
 25   
 26  # relax module imports. 
 27  from data.align_tensor import AlignTensorList 
 28  from data.diff_tensor import DiffTensorData 
 29  from data.exp_info import ExpInfo 
 30  from data.interatomic import InteratomList 
 31  from data.mol_res_spin import MoleculeList 
 32  from data.prototype import Prototype 
 33  from data.relax_xml import fill_object_contents, node_value_to_python, xml_to_object 
 34  import generic_fns 
 35  from relax_errors import RelaxFromXMLNotEmptyError 
 36  from relax_warnings import RelaxWarning 
 37   
 38   
39 -class PipeContainer(Prototype):
40 """Class containing all the program data.""" 41
42 - def __init__(self):
43 """Set up all the PipeContainer data structures.""" 44 45 # The molecule-residue-spin object. 46 self.mol = MoleculeList() 47 48 # The interatomic data object. 49 self.interatomic = InteratomList() 50 51 # The data pipe type. 52 self.pipe_type = None 53 54 # Hybrid models. 55 self.hybrid_pipes = []
56 57
58 - def __repr__(self):
59 """The string representation of the object. 60 61 Rather than using the standard Python conventions (either the string representation of the 62 value or the "<...desc...>" notation), a rich-formatted description of the object is given. 63 """ 64 65 # Intro text. 66 text = "The data pipe storage object.\n" 67 68 # Special objects/methods (to avoid the getattr() function call on). 69 spec_obj = ['exp_info', 'mol', 'interatomic', 'diff_tensor', 'structure'] 70 71 # Objects. 72 text = text + "\n" 73 text = text + "Objects:\n" 74 for name in dir(self): 75 # Molecular list. 76 if name == 'mol': 77 text = text + " mol: The molecule list (for the storage of the spin system specific data)\n" 78 79 # Interatomic data list. 80 if name == 'interatomic': 81 text = text + " interatomic: The interatomic data list (for the storage of the inter-spin system data)\n" 82 83 # Diffusion tensor. 84 if name == 'diff_tensor': 85 text = text + " diff_tensor: The Brownian rotational diffusion tensor data object\n" 86 87 # Molecular structure. 88 if name == 'structure': 89 text = text + " structure: The 3D molecular data object\n" 90 91 # The experimental info data container. 92 if name == 'exp_info': 93 text = text + " exp_info: The data container for experimental information\n" 94 95 # Skip the PipeContainer methods. 96 if name in list(self.__class__.__dict__.keys()): 97 continue 98 99 # Skip certain objects. 100 if match("^_", name) or name in spec_obj: 101 continue 102 103 # Add the object's attribute to the text string. 104 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n" 105 106 # Return the text representation. 107 return text
108 109
110 - def _back_compat_hook(self, file_version=None):
111 """Method for converting old data structures to the new ones. 112 113 @keyword file_version: The relax XML version of the XML file. 114 @type file_version: int 115 """ 116 117 # Relaxation data. 118 self._back_compat_hook_ri_data()
119 120
122 """Converting the old relaxation data structures to the new ones.""" 123 124 # Nothing to do. 125 if not (hasattr(cdp, 'frq_labels') and hasattr(cdp, 'noe_r1_table') and hasattr(cdp, 'remap_table')): 126 return 127 128 # Initialise the new structures. 129 cdp.ri_ids = [] 130 cdp.ri_type = {} 131 frq = {} # This will be placed into cdp later as cdp.frq still exists. 132 133 # Generate the new structures. 134 for i in range(cdp.num_ri): 135 # The ID. 136 ri_id = "%s_%s" % (cdp.ri_labels[i], cdp.frq_labels[cdp.remap_table[i]]) 137 138 # Not unique. 139 if ri_id in cdp.ri_ids: 140 # Loop until a unique ID is found. 141 for j in range(100): 142 # New id. 143 new_id = "%s_%s" % (ri_id, j) 144 145 # Unique. 146 if not new_id in cdp.ri_ids: 147 ri_id = new_id 148 break 149 150 # Add the ID. 151 cdp.ri_ids.append(ri_id) 152 153 # The relaxation data type. 154 cdp.ri_type[ri_id] = cdp.ri_labels[i] 155 156 # The frequency data. 157 frq[ri_id] = cdp.frq[cdp.remap_table[i]] 158 159 # Delete the old structures. 160 del cdp.frq 161 del cdp.frq_labels 162 del cdp.noe_r1_table 163 del cdp.num_frq 164 del cdp.num_ri 165 del cdp.remap_table 166 del cdp.ri_labels 167 168 # Set the frequencies. 169 cdp.frq = frq
170 171
172 - def from_xml(self, pipe_node, file_version=None, dir=None):
173 """Read a pipe container XML element and place the contents into this pipe. 174 175 @param pipe_node: The data pipe XML node. 176 @type pipe_node: xml.dom.minidom.Element instance 177 @keyword file_version: The relax XML version of the XML file. 178 @type file_version: int 179 @keyword dir: The name of the directory containing the results file (needed for loading external files). 180 @type dir: str 181 """ 182 183 # Test if empty. 184 if not self.is_empty(): 185 raise RelaxFromXMLNotEmptyError(self.__class__.__name__) 186 187 # Get the global data node, and fill the contents of the pipe. 188 global_node = pipe_node.getElementsByTagName('global')[0] 189 xml_to_object(global_node, self, file_version=file_version) 190 191 # Backwards compatibility transformations. 192 self._back_compat_hook(file_version) 193 194 # Get the hybrid node (and its sub-node), and recreate the hybrid object. 195 hybrid_node = pipe_node.getElementsByTagName('hybrid')[0] 196 pipes_node = hybrid_node.getElementsByTagName('pipes')[0] 197 setattr(self, 'hybrid_pipes', node_value_to_python(pipes_node.childNodes[0])) 198 199 # Get the experimental information data nodes and, if they exist, fill the contents. 200 exp_info_nodes = pipe_node.getElementsByTagName('exp_info') 201 if exp_info_nodes: 202 # Create the data container. 203 self.exp_info = ExpInfo() 204 205 # Fill its contents. 206 self.exp_info.from_xml(exp_info_nodes[0], file_version=file_version) 207 208 # Get the diffusion tensor data nodes and, if they exist, fill the contents. 209 diff_tensor_nodes = pipe_node.getElementsByTagName('diff_tensor') 210 if diff_tensor_nodes: 211 # Create the diffusion tensor object. 212 self.diff_tensor = DiffTensorData() 213 214 # Fill its contents. 215 self.diff_tensor.from_xml(diff_tensor_nodes[0], file_version=file_version) 216 217 # Get the alignment tensor data nodes and, if they exist, fill the contents. 218 align_tensor_nodes = pipe_node.getElementsByTagName('align_tensors') 219 if align_tensor_nodes: 220 # Create the alignment tensor object. 221 self.align_tensors = AlignTensorList() 222 223 # Fill its contents. 224 self.align_tensors.from_xml(align_tensor_nodes[0], file_version=file_version) 225 226 # Recreate the interatomic data structure (this needs to be before the 'mol' structure as the backward compatibility hooks can create interatomic data containers!). 227 interatom_nodes = pipe_node.getElementsByTagName('interatomic') 228 self.interatomic.from_xml(interatom_nodes, file_version=file_version) 229 230 # Recreate the molecule, residue, and spin data structure. 231 mol_nodes = pipe_node.getElementsByTagName('mol') 232 self.mol.from_xml(mol_nodes, file_version=file_version) 233 234 # Get the structural object nodes and, if they exist, fill the contents. 235 str_nodes = pipe_node.getElementsByTagName('structure') 236 if str_nodes: 237 # Get the object type. 238 parser = str(str_nodes[0].getAttribute('id')) 239 240 # Create the structural object. 241 fail = False 242 if parser == 'scientific': 243 self.structure = generic_fns.structure.scientific.Scientific_data() 244 elif parser == 'internal': 245 self.structure = generic_fns.structure.internal.Internal() 246 else: 247 warn(RelaxWarning("The structural file parser " + repr(parser) + " is unknown. The structure will not be loaded.")) 248 fail = True 249 250 # Fill its contents. 251 if not fail: 252 self.structure.from_xml(str_nodes[0], dir=dir, id=parser, file_version=file_version)
253 254
255 - def is_empty(self):
256 """Method for testing if the data pipe is empty. 257 258 @return: True if the data pipe is empty, False otherwise. 259 @rtype: bool 260 """ 261 262 # Is the molecule structure data object empty? 263 if hasattr(self, 'structure') and not self.structure.is_empty(): 264 return False 265 266 # Is the molecule/residue/spin data object empty? 267 if not self.mol.is_empty(): 268 return False 269 270 # Is the interatomic data object empty? 271 if not self.interatomic.is_empty(): 272 return False 273 274 # Tests for the initialised data (the pipe type can be set in an empty data pipe, so this isn't checked). 275 if self.hybrid_pipes: 276 return False 277 278 # An object has been added to the container. 279 for name in dir(self): 280 # Skip the objects initialised in __init__(). 281 if name in ['mol', 'interatomic', 'pipe_type', 'hybrid_pipes']: 282 continue 283 284 # Skip the PipeContainer methods. 285 if name in list(self.__class__.__dict__.keys()): 286 continue 287 288 # Skip special objects. 289 if match("^_", name): 290 continue 291 292 # An object has been added. 293 return False 294 295 # The data pipe is empty. 296 return True
297 298
299 - def to_xml(self, doc, element):
300 """Create a XML element for the current data pipe. 301 302 @param doc: The XML document object. 303 @type doc: xml.dom.minidom.Document instance 304 @param element: The XML element to add the pipe XML element to. 305 @type element: XML element object 306 """ 307 308 # Add all simple python objects within the PipeContainer to the global element. 309 global_element = doc.createElement('global') 310 element.appendChild(global_element) 311 global_element.setAttribute('desc', 'Global data located in the top level of the data pipe') 312 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())) 313 314 # Hybrid info. 315 self.xml_create_hybrid_element(doc, element) 316 317 # Add the experimental information. 318 if hasattr(self, 'exp_info'): 319 self.exp_info.to_xml(doc, element) 320 321 # Add the diffusion tensor data. 322 if hasattr(self, 'diff_tensor'): 323 self.diff_tensor.to_xml(doc, element) 324 325 # Add the alignment tensor data. 326 if hasattr(self, 'align_tensors'): 327 self.align_tensors.to_xml(doc, element) 328 329 # Add the molecule-residue-spin data. 330 self.mol.to_xml(doc, element) 331 332 # Add the interatomic data. 333 self.interatomic.to_xml(doc, element) 334 335 # Add the structural data, if it exists. 336 if hasattr(self, 'structure'): 337 self.structure.to_xml(doc, element)
338 339
340 - def xml_create_hybrid_element(self, doc, element):
341 """Create an XML element for the data pipe hybridisation information. 342 343 @param doc: The XML document object. 344 @type doc: xml.dom.minidom.Document instance 345 @param element: The element to add the hybridisation info to. 346 @type element: XML element object 347 """ 348 349 # Create the hybrid element and add it to the higher level element. 350 hybrid_element = doc.createElement('hybrid') 351 element.appendChild(hybrid_element) 352 353 # Set the hybridisation attributes. 354 hybrid_element.setAttribute('desc', 'Data pipe hybridisation information') 355 356 # Create an element to store the pipes list. 357 list_element = doc.createElement('pipes') 358 hybrid_element.appendChild(list_element) 359 360 # Add the pipes list. 361 text_val = doc.createTextNode(str(self.hybrid_pipes)) 362 list_element.appendChild(text_val)
363