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