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
27
28
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
60 print(" Object ID: %s" % object_names[struct_index])
61
62
63 objects[struct_index].validate_models(verbosity=0)
64
65
66 num_models = objects[struct_index].num_models()
67
68
69 selection = objects[struct_index].selection(atom_id=atom_id)
70
71
72 for model in objects[struct_index].model_loop():
73
74 if models != None and model.num not in models[struct_index]:
75 continue
76
77
78 print(" Model: %s" % model.num)
79
80
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
85 if molecules != None and mol_name not in molecules[struct_index]:
86 continue
87
88
89 if mol_name != current_mol:
90
91 print(" Molecule: %s" % mol_name)
92
93
94 current_mol = mol_name
95 current_res = None
96
97
98 object_id_list.append(object_names[struct_index])
99 model_list.append(model.num)
100 molecule_list.append(mol_name)
101
102
103 one_letter_codes.append(objects[struct_index].one_letter_codes(mol_name=mol_name, selection=selection))
104
105
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
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
124 if res_num != current_res:
125
126 current_res = res_num
127
128
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
137 atom_names[-1][-1].append(atom_name)
138 atom_pos[-1][-1][atom_name] = pos[0]
139
140
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
147 num_mols = len(atom_names)
148
149
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
163 if mol_names == []:
164 return [], [], [], [], [], []
165
166
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
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
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
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
205 for atom_name in atom_names[0][res_indices[0]]:
206
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
214 if not present:
215 continue
216
217
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
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
229 coord = array(coord, float64)
230
231
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
249 id = ''
250
251
252 if object_id != None:
253 id += "Object '%s'" % object_id
254
255
256 if model != None:
257 if len(id):
258 id += '; '
259 id += "Model %i" % model
260
261
262 if len(id):
263 id += '; '
264 if molecule != None:
265 id += "Molecule '%s'" % molecule
266
267
268 if not len(id):
269 raise RelaxError("No alignment ID could be constructed.")
270
271
272 return id
273
274
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
291 for struct_index in range(len(objects)):
292
293 objects[struct_index].validate_models(verbosity=0)
294
295
296 num_models = objects[struct_index].num_models()
297
298
299 selection = objects[struct_index].selection(atom_id=atom_id)
300
301
302 for model in objects[struct_index].model_loop():
303
304 if models != None and model.num not in models[struct_index]:
305 continue
306
307
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
311 if molecules != None and mol_name not in molecules[struct_index]:
312 continue
313
314
315 if mol_name != current_mol:
316
317 current_mol = mol_name
318
319
320 yield struct_index, model.num, mol_name
321