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