Package lib :: Package structure :: Package internal :: Module coordinates
[hide private]
[frames] | no frames]

Source Code for Module lib.structure.internal.coordinates

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2014-2015 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 handling atomic coordinate information.""" 
 24   
 25  # Python module imports. 
 26  from numpy import array, float64, int16, zeros 
 27   
 28  # relax module imports. 
 29  from lib.errors import RelaxFault 
 30   
 31   
32 -def assemble_atomic_coordinates(objects=None, object_names=None, molecules=None, models=None, atom_id=None):
33 """Assemble the atomic coordinates of all structures. 34 35 @keyword objects: The list of internal structural objects to assemble the coordinates from. 36 @type objects: list of str 37 @keyword object_names: The list of names for each structural object to use in printouts. 38 @type object_names: list of str 39 @keyword models: The list of models for each structural object. The number of elements must match the objects argument. If set to None, then all models will be used. 40 @type models: None or list of lists of int 41 @keyword molecules: The list of molecules for each structural object. The number of elements must match the objects argument. If set to None, then all molecules will be used. 42 @type molecules: None or list of lists of str 43 @keyword atom_id: The molecule, residue, and atom identifier string of the coordinates of interest. This matches the spin ID string format. 44 @type atom_id: None or str 45 @return: The list of structure IDs for each molecule, the object ID list per molecule, the model number list per molecule, the molecule name list per molecule, the atom positions per molecule and per residue, the molecule names per molecule and per residue, the residue names per molecule and per residue, the residue numbers per molecule and per residue, the atom names per molecule and per residue, the atomic elements per molecule and per residue, the one letter codes for the residue sequence, the number of molecules. 46 @rtype: list of str, list of str, list of int, list of str, list of list of dict of str, list of list of dict of str, list of list of dict of str, list of list of dict of str, list of list of dict of str, list of list of dict of str, list of str, int 47 """ 48 49 print("Assembling all atomic coordinates:") 50 ids = [] 51 object_id_list = [] 52 model_list = [] 53 molecule_list = [] 54 atom_pos = [] 55 mol_names = [] 56 res_names = [] 57 res_nums = [] 58 atom_names = [] 59 elements = [] 60 one_letter_codes = [] 61 for struct_index in range(len(objects)): 62 # Printout. 63 print(" Object ID: %s" % object_names[struct_index]) 64 65 # Validate the models. 66 objects[struct_index].validate_models(verbosity=0) 67 68 # The number of models. 69 num_models = objects[struct_index].num_models() 70 71 # The selection object. 72 selection = objects[struct_index].selection(atom_id=atom_id) 73 74 # Loop over the models. 75 for model in objects[struct_index].model_loop(): 76 # No model match. 77 if models != None and model.num not in models[struct_index]: 78 continue 79 80 # Printout. 81 print(" Model: %s" % model.num) 82 83 # Add all coordinates and elements. 84 current_mol = '' 85 current_res = None 86 for mol_name, res_num, res_name, atom_name, elem, pos in objects[struct_index].atom_loop(selection=selection, model_num=model.num, mol_name_flag=True, res_num_flag=True, res_name_flag=True, atom_name_flag=True, pos_flag=True, element_flag=True): 87 # No molecule match, so skip. 88 if molecules != None and mol_name not in molecules[struct_index]: 89 continue 90 91 # A new molecule. 92 if mol_name != current_mol: 93 # Printout. 94 print(" Molecule: %s" % mol_name) 95 96 # Change the current molecule name and residue number. 97 current_mol = mol_name 98 current_res = None 99 100 # Update the molecule lists. 101 object_id_list.append(object_names[struct_index]) 102 model_list.append(model.num) 103 molecule_list.append(mol_name) 104 105 # Store the one letter codes for sequence alignment. 106 one_letter_codes.append(objects[struct_index].one_letter_codes(mol_name=mol_name, selection=selection)) 107 108 # Extend the lists. 109 atom_names.append([]) 110 atom_pos.append([]) 111 mol_names.append([]) 112 res_names.append([]) 113 res_nums.append([]) 114 elements.append([]) 115 116 # Create a new structure ID. 117 if len(object_names) > 1 and num_models > 1: 118 ids.append('%s, model %i, %s' % (object_names[struct_index], model.num, mol_name)) 119 elif len(object_names) > 1: 120 ids.append('%s, %s' % (object_names[struct_index], mol_name)) 121 elif num_models > 1: 122 ids.append('model %i, %s' % (model.num, mol_name)) 123 else: 124 ids.append('%s' % mol_name) 125 126 # A new residue. 127 if res_num != current_res: 128 # Change the current residue 129 current_res = res_num 130 131 # Extend the lists. 132 atom_names[-1].append([]) 133 atom_pos[-1].append({}) 134 mol_names[-1].append({}) 135 res_names[-1].append({}) 136 res_nums[-1].append({}) 137 elements[-1].append({}) 138 139 # Store the per-structure ID and coordinate. 140 atom_names[-1][-1].append(atom_name) 141 atom_pos[-1][-1][atom_name] = pos[0] 142 143 # Store the per-structure sequence information. 144 mol_names[-1][-1][atom_name] = mol_name 145 res_names[-1][-1][atom_name] = res_name 146 res_nums[-1][-1][atom_name] = res_num 147 elements[-1][-1][atom_name] = elem 148 149 # The total number of molecules. 150 num_mols = len(atom_names) 151 152 # Return the data. 153 return ids, object_id_list, model_list, molecule_list, atom_pos, mol_names, res_names, res_nums, atom_names, elements, one_letter_codes, num_mols
154 155
156 -def assemble_coord_array(atom_pos=None, mol_names=None, res_names=None, res_nums=None, atom_names=None, elements=None, sequences=None, skip=None):
157 """Assemble the atomic coordinates as a numpy array. 158 159 @keyword sequences: The list of residue sequences for the alignment as one letter codes. 160 @type sequences: list of str 161 @return: The array of atomic coordinates (first dimension is the model and/or molecule, the second are the atoms, and the third are the coordinates); the common list of molecule names; the common list of residue names; the common list of residue numbers; the common list of atom names; the common list of element names. 162 @rtype: numpy rank-3 float64 array, list of str, list of str, list of int, list of str, list of str 163 """ 164 165 # No data to assemble. 166 if mol_names == []: 167 return [], [], [], [], [], [] 168 169 # Set up the structures for common coordinates. 170 num_mols = len(skip) 171 coord = [] 172 mol_name_common = [] 173 res_name_common = [] 174 res_num_common = [] 175 atom_name_common = [] 176 element_common = [] 177 for mol_index in range(num_mols): 178 coord.append([]) 179 180 # Find the common atoms and create the coordinate data structure. 181 res_indices = [-1]*num_mols 182 max_res = -1 183 for mol_index in range(num_mols): 184 if len(sequences[mol_index]) > max_res: 185 max_res = len(sequences[mol_index]) 186 while 1: 187 # Move to the next non-skipped residues in each molecule. 188 for mol_index in range(num_mols): 189 terminate = False 190 while 1: 191 res_indices[mol_index] += 1 192 if res_indices[mol_index] >= len(skip[mol_index]): 193 terminate = True 194 break 195 if not skip[mol_index][res_indices[mol_index]]: 196 break 197 198 # Termination. 199 for mol_index in range(num_mols): 200 if res_indices[0] >= len(atom_names[0]): 201 terminate = True 202 if res_indices[mol_index] >= len(atom_names[mol_index]): 203 terminate = True 204 if terminate: 205 break 206 207 # Loop over the residue atoms in the first molecule. 208 for atom_name in atom_names[0][res_indices[0]]: 209 # Is the atom ID present in all other structures? 210 present = True 211 for mol_index in range(1, num_mols): 212 if atom_name not in atom_names[mol_index][res_indices[mol_index]]: 213 present = False 214 break 215 216 # Not present, so skip the atom. 217 if not present: 218 continue 219 220 # Add the atomic position to the coordinate list and the element to the element list. 221 for mol_index in range(num_mols): 222 coord[mol_index].append(atom_pos[mol_index][res_indices[mol_index]][atom_name]) 223 224 # The common sequence information. 225 mol_name_common.append(mol_names[0][res_indices[0]][atom_name]) 226 res_name_common.append(res_names[0][res_indices[0]][atom_name]) 227 res_num_common.append(res_nums[0][res_indices[0]][atom_name]) 228 atom_name_common.append(atom_name) 229 element_common.append(elements[0][res_indices[0]][atom_name]) 230 231 # Convert to a numpy array. 232 coord = array(coord, float64) 233 234 # Return the information. 235 return coord, mol_name_common, res_name_common, res_num_common, atom_name_common, element_common
236 237
238 -def generate_id(object_id=None, model=None, molecule=None):
239 """Generate a unique ID. 240 241 @keyword object_id: The structural object ID. 242 @type object_id: str 243 @keyword model: The model number. 244 @type model: int 245 @keyword molecule: The molecule name. 246 @type molecule: str 247 @return: The unique ID constructed from the object ID, model number and molecule name. 248 @rtype: str 249 """ 250 251 # Init. 252 id = '' 253 254 # The object ID. 255 if object_id != None: 256 id += "Object '%s'" % object_id 257 258 # The model number. 259 if model != None: 260 if len(id): 261 id += '; ' 262 id += "Model %i" % model 263 264 # The molecule name. 265 if len(id): 266 id += '; ' 267 if molecule != None: 268 id += "Molecule '%s'" % molecule 269 270 # Sanity check. 271 if not len(id): 272 raise RelaxError("No alignment ID could be constructed.") 273 274 # Return the ID. 275 return id
276 277
278 -def loop_coord_structures(objects=None, molecules=None, models=None, atom_id=None):
279 """Generator function for looping over all internal structural objects, models and molecules. 280 281 @keyword objects: The list of internal structural objects to loop over. 282 @type objects: list of str 283 @keyword models: The list of models for each structural object. The number of elements must match the objects argument. If set to None, then all models will be used. 284 @type models: None or list of lists of int 285 @keyword molecules: The list of molecules for each structural object. The number of elements must match the objects argument. If set to None, then all molecules will be used. 286 @type molecules: None or list of lists of str 287 @keyword atom_id: The molecule, residue, and atom identifier string of the coordinates of interest. This matches the spin ID string format. 288 @type atom_id: None or str 289 @return: The structural object index, model number, and molecule name. 290 @rtype: int, int or None, str 291 """ 292 293 # Loop over all structural objects. 294 for struct_index in range(len(objects)): 295 # Validate the models. 296 objects[struct_index].validate_models(verbosity=0) 297 298 # The number of models. 299 num_models = objects[struct_index].num_models() 300 301 # The selection object. 302 selection = objects[struct_index].selection(atom_id=atom_id) 303 304 # Loop over the models. 305 for model in objects[struct_index].model_loop(): 306 # No model match. 307 if models != None and model.num not in models[struct_index]: 308 continue 309 310 # Coordinate loop. 311 current_mol = '' 312 for mol_name, res_num, res_name, atom_name, elem, pos in objects[struct_index].atom_loop(selection=selection, model_num=model.num, mol_name_flag=True, res_num_flag=True, res_name_flag=True, atom_name_flag=True, pos_flag=True, element_flag=True): 313 # No molecule match, so skip. 314 if molecules != None and mol_name not in molecules[struct_index]: 315 continue 316 317 # A new molecule. 318 if mol_name != current_mol: 319 # Change the current molecule name. 320 current_mol = mol_name 321 322 # Yield the data. 323 yield struct_index, model.num, mol_name
324