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

Source Code for Module data_store.pipe_container

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