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

Source Code for Module generic_fns.interatomic

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 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  # Module docstring. 
 23  """Module for the manipulation of the interatomic data structures in the relax data store.""" 
 24   
 25  # Python module imports. 
 26  from copy import deepcopy 
 27  from re import search 
 28  import sys 
 29   
 30  # relax module imports. 
 31  from generic_fns import pipes 
 32  from generic_fns.mol_res_spin import Selection, return_spin 
 33  from relax_errors import RelaxError, RelaxInteratomError, RelaxNoInteratomError 
 34  from relax_io import write_data 
 35  from relax_warnings import RelaxNoSpinWarning 
 36   
 37   
38 -def copy(pipe_from=None, pipe_to=None, verbose=True):
39 """Copy the interatomic data from one data pipe to another. 40 41 @keyword pipe_from: The data pipe to copy the interatomic data from. This defaults to the current data pipe. 42 @type pipe_from: str 43 @keyword pipe_to: The data pipe to copy the interatomic data to. This defaults to the current data pipe. 44 @type pipe_to: str 45 @keyword verbose: A flag which if True will cause info about each spin pair to be printed out. 46 @type verbose: bool 47 """ 48 49 # Defaults. 50 if pipe_from == None and pipe_to == None: 51 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.") 52 elif pipe_from == None: 53 pipe_from = pipes.cdp_name() 54 elif pipe_to == None: 55 pipe_to = pipes.cdp_name() 56 57 # Test if the pipe_from and pipe_to data pipes exist. 58 pipes.test(pipe_from) 59 pipes.test(pipe_to) 60 61 # Test if pipe_from contains interatomic data (skipping the rest of the function if it is missing). 62 if not exists_data(pipe_from): 63 return 64 65 # Test if pipe_to contains interatomic data. 66 if exists_data(pipe_to): 67 raise RelaxInteratomError 68 69 # Loop over the interatomic data of the pipe_from data pipe. 70 ids = [] 71 for interatom in interatomic_loop(pipe=pipe_from): 72 # Create a new container. 73 new_interatom = create_interatom(spin_id1=interatom.spin_id1, spin_id2=interatom.spin_id2, pipe=pipe_to) 74 75 # Duplicate all the objects of the container. 76 for name in dir(interatom): 77 # Skip special objects. 78 if search('^_', name): 79 continue 80 81 # Skip the spin IDs. 82 if name in ['spin_id1', 'spin_id2']: 83 continue 84 85 # Skip class methods. 86 if name in list(interatom.__class__.__dict__.keys()): 87 continue 88 89 # Duplicate all other objects. 90 obj = deepcopy(getattr(interatom, name)) 91 setattr(new_interatom, name, obj) 92 93 # Store the IDs for the printout. 94 ids.append([repr(interatom.spin_id1), repr(interatom.spin_id2)]) 95 96 # Print out. 97 if verbose: 98 write_data(out=sys.stdout, headings=["Spin_ID_1", "Spin_ID_2"], data=ids)
99 100
101 -def create_interatom(spin_id1=None, spin_id2=None, pipe=None):
102 """Create and return the interatomic data container for the two spins. 103 104 @keyword spin_id1: The spin ID string of the first atom. 105 @type spin_id1: str 106 @keyword spin_id2: The spin ID string of the first atom. 107 @type spin_id2: str 108 @keyword pipe: The data pipe to create the interatomic data container for. This defaults to the current data pipe if not supplied. 109 @type pipe: str or None 110 @return: The newly created interatomic data container. 111 @rtype: data.interatomic.InteratomContainer instance 112 """ 113 114 # The data pipe. 115 if pipe == None: 116 pipe = pipes.cdp_name() 117 118 # Get the data pipe. 119 dp = pipes.get_pipe(pipe) 120 121 # Check that the spin IDs exist. 122 spin = return_spin(spin_id1, pipe) 123 if spin == None: 124 raise RelaxNoSpinWarning(spin_id1) 125 spin = return_spin(spin_id2, pipe) 126 if spin == None: 127 raise RelaxNoSpinWarning(spin_id2) 128 129 # Check if the two spin IDs have already been added. 130 for i in range(len(dp.interatomic)): 131 if id_match(spin_id=spin_id1, interatom=dp.interatomic[i], pipe=pipe) and id_match(spin_id=spin_id2, interatom=dp.interatomic[i], pipe=pipe): 132 raise RelaxError("The spin pair %s and %s have already been added." % (spin_id1, spin_id2)) 133 134 # Add and return the data. 135 return dp.interatomic.add_item(spin_id1=spin_id1, spin_id2=spin_id2)
136 137
138 -def exists_data(pipe=None):
139 """Determine if any interatomic data exists. 140 141 @keyword pipe: The data pipe in which the interatomic data will be checked for. 142 @type pipe: str 143 @return: The answer to the question about the existence of data. 144 @rtype: bool 145 """ 146 147 # The current data pipe. 148 if pipe == None: 149 pipe = pipes.cdp_name() 150 151 # Test the data pipe. 152 pipes.test(pipe) 153 154 # Get the data pipe. 155 dp = pipes.get_pipe(pipe) 156 157 # The interatomic data structure is empty. 158 if dp.interatomic.is_empty(): 159 return False 160 161 # Otherwise. 162 return True
163 164
165 -def id_match(spin_id=None, interatom=None, pipe=None):
166 """Test if the spin ID matches one of the two spins of the given container. 167 168 @keyword spin_id: The spin ID string of the first atom. 169 @type spin_id: str 170 @keyword interatom: The interatomic data container. 171 @type interatom: InteratomContainer instance 172 @keyword pipe: The data pipe containing the interatomic data container. Defaults to the current data pipe. 173 @type pipe: str or None 174 @return: True if the spin ID matches one of the two spins, False otherwise. 175 @rtype: bool 176 """ 177 178 # Get the spin containers. 179 spin1 = return_spin(interatom.spin_id1, pipe=pipe) 180 spin2 = return_spin(interatom.spin_id2, pipe=pipe) 181 182 # No spins. 183 if spin1 == None or spin2 == None: 184 return False 185 186 # Check if the ID is in the private metadata list. 187 if spin_id in spin1._spin_ids or spin_id in spin2._spin_ids: 188 return True 189 190 # Nothing found. 191 return False
192 193
194 -def interatomic_loop(selection1=None, selection2=None, pipe=None, selected=True):
195 """Generator function for looping over all the interatomic data containers. 196 197 @keyword selection1: The optional spin ID selection of the first atom. 198 @type selection1: str 199 @keyword selection2: The optional spin ID selection of the second atom. 200 @type selection2: str 201 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe. 202 @type pipe: str 203 @keyword selected: A flag which if True will only return selected interatomic data containers. 204 @type selected: bool 205 """ 206 207 # The data pipe. 208 if pipe == None: 209 pipe = pipes.cdp_name() 210 211 # Get the data pipe. 212 dp = pipes.get_pipe(pipe) 213 214 # Parse the spin ID selection strings. 215 select_obj = None 216 select_obj1 = None 217 select_obj2 = None 218 if selection1 and selection2: 219 select_obj1 = Selection(selection1) 220 select_obj2 = Selection(selection2) 221 elif selection1: 222 select_obj = Selection(selection1) 223 elif selection2: 224 select_obj = Selection(selection2) 225 226 # Loop over the containers, yielding them. 227 for i in range(len(dp.interatomic)): 228 # Skip deselected containers. 229 if selected and not dp.interatomic[i].select: 230 continue 231 232 # Aliases. 233 interatom = dp.interatomic[i] 234 mol_index1, res_index1, spin_index1 = cdp.mol._spin_id_lookup[interatom.spin_id1] 235 mol_index2, res_index2, spin_index2 = cdp.mol._spin_id_lookup[interatom.spin_id2] 236 mol1 = cdp.mol[mol_index1] 237 res1 = cdp.mol[mol_index1].res[res_index1] 238 spin1 = cdp.mol[mol_index1].res[res_index1].spin[spin_index1] 239 mol2 = cdp.mol[mol_index2] 240 res2 = cdp.mol[mol_index2].res[res_index2] 241 spin2 = cdp.mol[mol_index2].res[res_index2].spin[spin_index2] 242 243 # Check that the selections are met. 244 if select_obj: 245 if (mol1, res1, spin1) not in select_obj and (mol2, res2, spin2) not in select_obj: 246 continue 247 if select_obj1: 248 if not ((mol1, res1, spin1) in select_obj1 or (mol2, res2, spin2) in select_obj1) or not ((mol1, res1, spin1) in select_obj2 or (mol2, res2, spin2) in select_obj2): 249 continue 250 251 # Return the container. 252 yield interatom
253 254
255 -def return_interatom(spin_id1=None, spin_id2=None, pipe=None):
256 """Return the list of interatomic data containers for the two spins. 257 258 @keyword spin_id1: The spin ID string of the first atom. 259 @type spin_id1: str 260 @keyword spin_id2: The spin ID string of the second atom. 261 @type spin_id2: str 262 @keyword pipe: The data pipe holding the container. Defaults to the current data pipe. 263 @type pipe: str or None 264 @return: The matching interatomic data container, if it exists. 265 @rtype: data.interatomic.InteratomContainer instance or None 266 """ 267 268 # Checks. 269 if spin_id1 == None: 270 raise RelaxError("The first spin ID must be supplied.") 271 if spin_id2 == None: 272 raise RelaxError("The second spin ID must be supplied.") 273 274 # The data pipe. 275 if pipe == None: 276 pipe = pipes.cdp_name() 277 278 # Get the data pipe. 279 dp = pipes.get_pipe(pipe) 280 281 # Return the matching container. 282 for i in range(len(dp.interatomic)): 283 if id_match(spin_id=spin_id1, interatom=dp.interatomic[i], pipe=pipe) and id_match(spin_id=spin_id2, interatom=dp.interatomic[i], pipe=pipe): 284 return dp.interatomic[i] 285 286 # No matchs. 287 return None
288 289
290 -def return_interatom_list(spin_id=None, pipe=None):
291 """Return the list of interatomic data containers for the given spin. 292 293 @keyword spin_id: The spin ID string. 294 @type spin_id: str 295 @keyword pipe: The data pipe holding the container. This defaults to the current data pipe. 296 @type pipe: str or None 297 @return: The list of matching interatomic data containers, if any exist. 298 @rtype: list of data.interatomic.InteratomContainer instances 299 """ 300 301 # Check. 302 if spin_id == None: 303 raise RelaxError("The spin ID must be supplied.") 304 305 # The data pipe. 306 if pipe == None: 307 pipe = pipes.cdp_name() 308 309 # Get the data pipe. 310 dp = pipes.get_pipe(pipe) 311 312 # Initialise. 313 interatoms = [] 314 315 # Find and append all containers. 316 for i in range(len(dp.interatomic)): 317 if id_match(spin_id=spin_id, interatom=dp.interatomic[i], pipe=pipe) or id_match(spin_id=spin_id, interatom=dp.interatomic[i], pipe=pipe): 318 interatoms.append(dp.interatomic[i]) 319 320 # Return the list of containers. 321 return interatoms
322