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