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

Source Code for Module data_store.interatomic

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2007-2013 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  # Module docstring. 
 23  """The interatomic data containers of the relax data store.""" 
 24   
 25  # Python module imports. 
 26  from re import match 
 27   
 28  # relax module imports. 
 29  import pipe_control 
 30  from data_store.prototype import Prototype 
 31  from data_store.relax_xml import fill_object_contents, object_to_xml, xml_to_object 
 32  from lib.errors import RelaxFromXMLNotEmptyError, RelaxImplementError 
 33  import specific_analyses 
 34   
 35   
36 -class InteratomContainer(Prototype):
37 """Class containing the interatomic data.""" 38
39 - def __init__(self, spin_id1=None, spin_id2=None, select=True):
40 """Set up the objects of the interatomic data container. 41 42 @keyword spin_id1: The spin ID string of the first atom. 43 @type spin_id1: str 44 @keyword spin_id2: The spin ID string of the second atom. 45 @type spin_id2: str 46 @keyword select: The selection flag. 47 @type select: bool 48 """ 49 50 # Store the spin IDs. 51 self.spin_id1 = spin_id1 52 self.spin_id2 = spin_id2 53 54 # Class variable defaults. 55 self.dipole_pair = False 56 self.select = select
57 58
59 - def __repr__(self):
60 """The string representation of the object. 61 62 Rather than using the standard Python conventions (either the string representation of the 63 value or the "<...desc...>" notation), a rich-formatted description of the object is given. 64 """ 65 66 # Intro. 67 text = "Class containing all the interatomic specific data between spins %s and %s.\n\n" % (self.spin_id1, self.spin_id2) 68 69 # Objects. 70 text = text + "\n" 71 text = text + "Objects:\n" 72 for name in dir(self): 73 # Skip the SpinContainer methods. 74 if name in ['is_empty']: 75 continue 76 77 # Skip special objects. 78 if match("^_", name): 79 continue 80 81 # Add the object's attribute to the text string. 82 text += " %s: %s\n" % (name, repr(getattr(self, name))) 83 84 return text
85 86
87 - def is_empty(self):
88 """Method for testing if this InteratomContainer object is empty. 89 90 @return: True if this container is empty, False otherwise. 91 @rtype: bool 92 """ 93 94 # An object has been added to the container. 95 for name in dir(self): 96 # Skip the objects initialised in __init__(). 97 if name in ['dipole_pair', 'spin_id1', 'spin_id2', 'select']: 98 continue 99 100 # Skip the SpinContainer methods. 101 if name in ['is_empty']: 102 continue 103 104 # Skip special objects. 105 if match("^_", name): 106 continue 107 108 # An object has been added. 109 return False 110 111 # The SpinContainer is unmodified. 112 return True
113 114 115
116 -class InteratomList(list):
117 """List type data container for interatomic specific data.""" 118
119 - def __repr__(self):
120 """The string representation of the object. 121 122 Rather than using the standard Python conventions (either the string representation of the value or the "<...desc...>" notation), a rich-formatted description of the object is given. 123 """ 124 125 # Intro. 126 text = "Interatomic data.\n\n" 127 128 # The data. 129 text += "%-25s%-25s%-25s" % ("Index", "Spin ID 1", "Spin ID 2") + "\n" 130 for i in range(len(self)): 131 text += "%-25i%-25s%-25s\n\n" % (i, self[i].spin_id1, self[i].spin_id2) 132 133 return text
134 135
136 - def add_item(self, spin_id1=None, spin_id2=None):
137 """Append an empty container to the list. 138 139 @keyword spin_id1: The spin ID string of the first atom. 140 @type spin_id1: str 141 @keyword spin_id2: The spin ID string of the first atom. 142 @type spin_id2: str 143 @return: The new interatomic data container. 144 @rtype: InteratomContainer instance 145 """ 146 147 # Append a new InteratomContainer. 148 cont = InteratomContainer(spin_id1, spin_id2) 149 self.append(cont) 150 151 # Return the container. 152 return cont
153 154
155 - def is_empty(self):
156 """Method for testing if this InteratomList object is empty. 157 158 @return: True if this list contains no InteratomContainers, False otherwise. 159 @rtype: bool 160 """ 161 162 # There are no InteratomContainers. 163 if len(self) == 0: 164 return True 165 166 # Otherwise. 167 return False
168 169
170 - def from_xml(self, interatom_nodes, file_version=None):
171 """Recreate an interatomic list data structure from the XML spin nodes. 172 173 @param interatom_nodes: The spin XML nodes. 174 @type interatom_nodes: xml.dom.minicompat.NodeList instance 175 @keyword file_version: The relax XML version of the XML file. 176 @type file_version: int 177 """ 178 179 # Test if empty. 180 if not self.is_empty(): 181 raise RelaxFromXMLNotEmptyError(self.__class__.__name__) 182 183 # Loop over the containers. 184 for interatom_node in interatom_nodes: 185 # Get the interatomic spin details and add a container to the InteratomList structure. 186 spin_id1 = str(interatom_node.getAttribute('spin_id1')) 187 spin_id2 = str(interatom_node.getAttribute('spin_id2')) 188 self.add_item(spin_id1=spin_id1, spin_id2=spin_id2) 189 190 # Recreate the current container. 191 xml_to_object(interatom_node, self[-1], file_version=file_version)
192 193
194 - def to_xml(self, doc, element):
195 """Create XML elements for each spin. 196 197 @param doc: The XML document object. 198 @type doc: xml.dom.minidom.Document instance 199 @param element: The element to add the spin XML elements to. 200 @type element: XML element object 201 """ 202 203 # Get the specific functions. 204 data_names = specific_analyses.setup.get_specific_fn('data_names', pipe_control.pipes.get_type(), raise_error=False) 205 return_data_desc = specific_analyses.setup.get_specific_fn('return_data_desc', pipe_control.pipes.get_type(), raise_error=False) 206 207 # Loop over the containers. 208 for i in range(len(self)): 209 # Create an XML element for this container and add it to the higher level element. 210 interatom_element = doc.createElement('interatomic') 211 element.appendChild(interatom_element) 212 213 # Set the spin attributes. 214 interatom_element.setAttribute('desc', 'Interatomic data container') 215 interatom_element.setAttribute('spin_id1', str(self[i].spin_id1)) 216 interatom_element.setAttribute('spin_id2', str(self[i].spin_id2)) 217 218 # Get the specific object names and loop over them to get their descriptions. 219 object_info = [] 220 try: 221 for name in data_names(error_names=True, sim_names=True): 222 # Get the description. 223 if return_data_desc: 224 desc = return_data_desc(name) 225 else: 226 desc = None 227 228 # Append the two. 229 object_info.append([name, desc]) 230 except RelaxImplementError: 231 pass 232 233 # Add the ordered objects. 234 blacklist = [] 235 for name, desc in object_info: 236 # Add the name to the blacklist. 237 blacklist.append(name) 238 239 # Skip the object if it is missing from the InteratomContainer. 240 if not hasattr(self[i], name): 241 continue 242 243 # Create a new element for this object, and add it to the main element. 244 sub_element = doc.createElement(name) 245 interatom_element.appendChild(sub_element) 246 247 # Add the object description. 248 if desc: 249 sub_element.setAttribute('desc', desc) 250 251 # Get the object. 252 object = getattr(self[i], name) 253 254 # Convert to XML. 255 object_to_xml(doc, sub_element, value=object) 256 257 # Add all simple python objects within the InteratomContainer to the XML element. 258 fill_object_contents(doc, interatom_element, object=self[i], blacklist=['spin_id1', 'spin_id2'] + blacklist + list(self[i].__class__.__dict__.keys()))
259