1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for handling atomic coordinate information."""
24
25
26 from numpy import array, float64, int16, zeros
27
28
29 from lib.errors import RelaxFault
30
31
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
63 print(" Object ID: %s" % object_names[struct_index])
64
65
66 objects[struct_index].validate_models(verbosity=0)
67
68
69 num_models = objects[struct_index].num_models()
70
71
72 selection = objects[struct_index].selection(atom_id=atom_id)
73
74
75 for model in objects[struct_index].model_loop():
76
77 if models != None and model.num not in models[struct_index]:
78 continue
79
80
81 print(" Model: %s" % model.num)
82
83
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
88 if molecules != None and mol_name not in molecules[struct_index]:
89 continue
90
91
92 if mol_name != current_mol:
93
94 print(" Molecule: %s" % mol_name)
95
96
97 current_mol = mol_name
98 current_res = None
99
100
101 object_id_list.append(object_names[struct_index])
102 model_list.append(model.num)
103 molecule_list.append(mol_name)
104
105
106 one_letter_codes.append(objects[struct_index].one_letter_codes(mol_name=mol_name, selection=selection))
107
108
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
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
127 if res_num != current_res:
128
129 current_res = res_num
130
131
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
140 atom_names[-1][-1].append(atom_name)
141 atom_pos[-1][-1][atom_name] = pos[0]
142
143
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
150 num_mols = len(atom_names)
151
152
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
166 if mol_names == []:
167 return [], [], [], [], [], []
168
169
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
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
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
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
208 for atom_name in atom_names[0][res_indices[0]]:
209
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
217 if not present:
218 continue
219
220
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
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
232 coord = array(coord, float64)
233
234
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
252 id = ''
253
254
255 if object_id != None:
256 id += "Object '%s'" % object_id
257
258
259 if model != None:
260 if len(id):
261 id += '; '
262 id += "Model %i" % model
263
264
265 if len(id):
266 id += '; '
267 if molecule != None:
268 id += "Molecule '%s'" % molecule
269
270
271 if not len(id):
272 raise RelaxError("No alignment ID could be constructed.")
273
274
275 return id
276
277
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
294 for struct_index in range(len(objects)):
295
296 objects[struct_index].validate_models(verbosity=0)
297
298
299 num_models = objects[struct_index].num_models()
300
301
302 selection = objects[struct_index].selection(atom_id=atom_id)
303
304
305 for model in objects[struct_index].model_loop():
306
307 if models != None and model.num not in models[struct_index]:
308 continue
309
310
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
314 if molecules != None and mol_name not in molecules[struct_index]:
315 continue
316
317
318 if mol_name != current_mol:
319
320 current_mol = mol_name
321
322
323 yield struct_index, model.num, mol_name
324