1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The consistency testing analysis API object."""
25
26
27 from warnings import warn
28
29
30 from lib.errors import RelaxError, RelaxNoSequenceError, RelaxNoValueError, RelaxSpinTypeError
31 from lib.float import isInf
32 from lib.periodic_table import periodic_table
33 from lib.physical_constants import h_bar, mu0
34 from lib.warnings import RelaxDeselectWarning
35 from pipe_control.interatomic import return_interatom_list
36 from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop
37 from specific_analyses.api_base import API_base
38 from specific_analyses.api_common import API_common
39 from specific_analyses.consistency_tests.parameter_object import Consistency_tests_params
40 from target_functions.consistency_tests import Consistency
41
42
44 """Class containing functions specific to consistency testing."""
45
46
47 instance = None
48
66
67
68 - def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
69 """Calculation of the consistency functions.
70
71 @keyword spin_id: The spin identification string.
72 @type spin_id: None or str
73 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices.
74 @type scaling_matrix: list of numpy rank-2, float64 array or list of None
75 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
76 @type verbosity: int
77 @keyword sim_index: The optional MC simulation index.
78 @type sim_index: None or int
79 """
80
81
82 if not hasattr(cdp, 'ct_frq') or not isinstance(cdp.ct_frq, float):
83 raise RelaxError("The frequency has not been set up.")
84
85
86 if not exists_mol_res_spin_data():
87 raise RelaxNoSequenceError
88
89
90 for spin, id in spin_loop(spin_id, return_id=True):
91
92 if not spin.select:
93 continue
94
95
96 if not hasattr(spin, 'isotope'):
97 raise RelaxSpinTypeError
98
99
100 if not hasattr(spin, 'csa') or spin.csa == None:
101 raise RelaxNoValueError("CSA")
102
103
104 if not hasattr(spin, 'orientation') or spin.orientation == None:
105 raise RelaxNoValueError("angle Theta")
106
107
108 if not hasattr(spin, 'tc') or spin.tc == None:
109 raise RelaxNoValueError("correlation time")
110
111
112 interatoms = return_interatom_list(id)
113 for interatom in interatoms:
114
115 if not interatom.dipole_pair:
116 continue
117
118
119 if id != interatom.spin_id1:
120 spin_id2 = interatom.spin_id1
121 else:
122 spin_id2 = interatom.spin_id2
123 spin2 = return_spin(spin_id2)
124
125
126 if not hasattr(spin2, 'isotope'):
127 raise RelaxSpinTypeError
128
129
130 if not hasattr(interatom, 'r') or interatom.r == None:
131 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2)
132
133
134 if cdp.ct_frq not in list(cdp.spectrometer_frq.values()):
135 raise RelaxError("No relaxation data corresponding to the frequency %s has been loaded." % cdp.ct_frq)
136
137
138 for spin, id in spin_loop(spin_id, return_id=True):
139
140 if not spin.select:
141 continue
142
143
144 r1 = None
145 r2 = None
146 noe = None
147
148
149 for ri_id in cdp.ri_ids:
150
151 if cdp.spectrometer_frq[ri_id] != cdp.ct_frq:
152 continue
153
154
155 if cdp.ri_type[ri_id] == 'R1':
156 if sim_index == None:
157 r1 = spin.ri_data[ri_id]
158 else:
159 r1 = spin.ri_data_sim[ri_id][sim_index]
160
161
162 if cdp.ri_type[ri_id] == 'R2':
163 if sim_index == None:
164 r2 = spin.ri_data[ri_id]
165 else:
166 r2 = spin.ri_data_sim[ri_id][sim_index]
167
168
169 if cdp.ri_type[ri_id] == 'NOE':
170 if sim_index == None:
171 noe = spin.ri_data[ri_id]
172 else:
173 noe = spin.ri_data_sim[ri_id][sim_index]
174
175
176 if r1 == None or r2 == None or noe == None:
177 continue
178
179
180 interatoms = return_interatom_list(id)
181 for i in range(len(interatoms)):
182
183 if not interatoms[i].dipole_pair:
184 continue
185
186
187 if id != interatoms[i].spin_id1:
188 spin_id2 = interatoms[i].spin_id1
189 else:
190 spin_id2 = interatoms[i].spin_id2
191 spin2 = return_spin(spin_id2)
192
193
194 gx = periodic_table.gyromagnetic_ratio(spin.isotope)
195 gh = periodic_table.gyromagnetic_ratio(spin2.isotope)
196
197
198 r = interatoms[i].r
199
200
201 ct = Consistency(frq=cdp.ct_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar)
202
203
204 j0, f_eta, f_r2 = ct.func(orientation=spin.orientation, tc=spin.tc, r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe)
205
206
207 if sim_index == None:
208 spin.j0 = j0
209 spin.f_eta = f_eta
210 spin.f_r2 = f_r2
211
212
213 else:
214
215 self.data_init(id, sim=1)
216 if spin.j0_sim == None:
217 spin.j0_sim = []
218 spin.f_eta_sim = []
219 spin.f_r2_sim = []
220
221
222 spin.j0_sim.append(j0)
223 spin.f_eta_sim.append(f_eta)
224 spin.f_r2_sim.append(f_r2)
225
226
228 """Initialise the data structures.
229
230 @param data: The spin ID string from the _base_data_loop_spin() method.
231 @type data: str
232 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure.
233 @type sim: bool
234 """
235
236
237 spin = return_spin(data)
238
239
240 data_names = self.data_names()
241
242
243 for name in data_names:
244
245 if sim:
246
247 name = name + '_sim'
248
249
250 if not hasattr(spin, name):
251
252 setattr(spin, name, None)
253
254
256 """Return a vector of parameter names.
257
258 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method.
259 @type model_info: SpinContainer instance, str
260 @return: The vector of parameter names.
261 @rtype: list of str
262 """
263
264
265 return ['j0', 'f_eta', 'f_r2']
266
267
269 """Deselect spins which have insufficient data to support calculation.
270
271 @keyword data_check: A flag to signal if the presence of base data is to be checked for.
272 @type data_check: bool
273 @keyword verbose: A flag which if True will allow printouts.
274 @type verbose: bool
275 """
276
277
278 if verbose:
279 print("\nOver-fit spin deselection:")
280
281
282 if not exists_mol_res_spin_data():
283 raise RelaxNoSequenceError
284
285
286 deselect_flag = False
287 spin_count = 0
288 for spin, spin_id in spin_loop(return_id=True):
289
290 if not spin.select:
291 continue
292
293
294 interatoms = return_interatom_list(spin_id)
295
296
297 dipole_relax = False
298 for i in range(len(interatoms)):
299
300 if not interatoms[i].dipole_pair:
301 continue
302
303
304 if spin_id != interatoms[i].spin_id1:
305 spin_id2 = interatoms[i].spin_id1
306 else:
307 spin_id2 = interatoms[i].spin_id2
308 spin2 = return_spin(spin_id2)
309
310
311 dipole_relax = True
312
313
314 if not dipole_relax or not hasattr(spin, 'csa') or spin.csa == None:
315 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms'))
316 spin.select = False
317 deselect_flag = True
318 continue
319
320
321 if data_check:
322
323 data_points = 0
324 inf_data = False
325 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'):
326 for id in cdp.ri_ids:
327 if id in spin.ri_data and spin.ri_data[id] != None:
328 data_points += 1
329
330
331 if isInf(spin.ri_data[id]):
332 inf_data = True
333
334
335 if inf_data:
336 warn(RelaxDeselectWarning(spin_id, 'infinite relaxation data'))
337 spin.select = False
338 deselect_flag = True
339 continue
340
341
342 if not hasattr(spin, 'ri_data'):
343 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data'))
344 spin.select = False
345 deselect_flag = True
346 continue
347
348
349 if data_points < 3:
350 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required'))
351 spin.select = False
352 deselect_flag = True
353 continue
354
355
356 spin_count += 1
357
358
359 if spin_count == 0:
360 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed."))
361
362
363 if verbose and not deselect_flag:
364 print("No spins have been deselected.")
365
366
367 - def set_error(self, index, error, model_info=None):
368 """Set the parameter errors.
369
370 @param index: The index of the parameter to set the errors for.
371 @type index: int
372 @param error: The error value.
373 @type error: float
374 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method.
375 @type model_info: SpinContainer instance, str
376 """
377
378
379 spin, spin_id = model_info
380
381
382 if index == 0:
383 spin.j0_err = error
384
385
386 if index == 1:
387 spin.f_eta_err = error
388
389
390 if index == 2:
391 spin.f_r2_err = error
392
393
395 """Return the array of simulation parameter values.
396
397 @param index: The index of the parameter to return the array of values for.
398 @type index: int
399 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method.
400 @type model_info: SpinContainer instance, str
401 @return: The array of simulation parameter values.
402 @rtype: list of float
403 """
404
405
406 spin, spin_id = model_info
407
408
409 if not spin.select:
410 return
411
412
413 if index == 0:
414 return spin.j0_sim
415
416
417 if index == 1:
418 return spin.f_eta_sim
419
420
421 if index == 2:
422 return spin.f_r2_sim
423
424
426 """Return the array of selected simulation flags.
427
428 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method.
429 @type model_info: SpinContainer instance, str
430 @return: The array of selected simulation flags.
431 @rtype: list of int
432 """
433
434
435 spin, spin_id = model_info
436
437
438 return spin.select_sim
439