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