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