1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The main methods of the specific API for model-free analysis."""
24
25
26 from copy import deepcopy
27 from math import pi
28 from numpy import float64, array, identity, zeros
29 from re import match, search
30 from types import MethodType
31 from warnings import warn
32
33
34 import arg_check
35 from generic_fns import diffusion_tensor, interatomic, pipes, sequence
36 from generic_fns.mol_res_spin import count_spins, exists_mol_res_spin_data, find_index, return_spin, return_spin_from_index, return_spin_indices, spin_loop
37 import specific_fns
38 from relax_errors import RelaxError, RelaxFault, RelaxFuncSetupError, RelaxNoModelError, RelaxNoSequenceError, RelaxNoTensorError, RelaxTensorError
39 from relax_warnings import RelaxDeselectWarning, RelaxWarning
40 from user_functions.data import Uf_tables; uf_tables = Uf_tables()
41 from user_functions.objects import Desc_container
42
43
44
46 """Class containing functions specific to model-free analysis."""
47
48 default_value_doc = Desc_container("Model-free default values")
49 _table = uf_tables.add_table(label="table: mf default values", caption="Model-free default values.")
50 _table.add_headings(["Data type", "Object name", "Value"])
51 _table.add_row(["Local tm", "'local_tm'", "10 * 1e-9"])
52 _table.add_row(["Order parameters S2, S2f, and S2s", "'s2', 's2f', 's2s'", "0.8"])
53 _table.add_row(["Correlation time te", "'te'", "100 * 1e-12"])
54 _table.add_row(["Correlation time tf", "'tf'", "10 * 1e-12"])
55 _table.add_row(["Correlation time ts", "'ts'", "1000 * 1e-12"])
56 _table.add_row(["Chemical exchange relaxation", "'rex'", "0.0"])
57 _table.add_row(["CSA", "'csa'", "-172 * 1e-6"])
58 default_value_doc.add_table(_table.label)
59
60 return_data_name_doc = Desc_container("Model-free data type string matching patterns")
61 _table = uf_tables.add_table(label="table: mf data type patterns", caption="Model-free data type string matching patterns.")
62 _table.add_headings(["Data type", "Object name"])
63 _table.add_row(["Local tm", "'local_tm'"])
64 _table.add_row(["Order parameter S2", "'s2'"])
65 _table.add_row(["Order parameter S2f", "'s2f'"])
66 _table.add_row(["Order parameter S2s", "'s2s'"])
67 _table.add_row(["Correlation time te", "'te'"])
68 _table.add_row(["Correlation time tf", "'tf'"])
69 _table.add_row(["Correlation time ts", "'ts'"])
70 _table.add_row(["Chemical exchange", "'rex'"])
71 _table.add_row(["CSA", "'csa'"])
72 return_data_name_doc.add_table(_table.label)
73
74 set_doc = Desc_container("Model-free set details")
75 set_doc.add_paragraph("Setting a parameter value may have no effect depending on which model-free model is chosen, for example if S2f values and S2s values are set but the run corresponds to model-free model 'm4' then, because these data values are not parameters of the model, they will have no effect.")
76 set_doc.add_paragraph("Note that the Rex values are scaled quadratically with field strength and should be supplied as a field strength independent value. Use the following formula to get the correct value:")
77 set_doc.add_verbatim(" value = rex / (2.0 * pi * frequency) ** 2")
78 set_doc.add_paragraph("where:")
79 set_doc.add_list_element("rex is the chemical exchange value for the current frequency.")
80 set_doc.add_list_element("pi is in the namespace of relax, ie just type 'pi'.")
81 set_doc.add_list_element("frequency is the proton frequency corresponding to the data.")
82
83 write_doc = Desc_container("Model-free parameter writing details")
84 write_doc.add_paragraph("For the model-free theory, it is assumed that Rex values are scaled quadratically with field strength. The values will seem quite small as they will be written out as a field strength independent value. Hence please use the following formula to convert the value to that expected for a given magnetic field strength:")
85 write_doc.add_verbatim(" Rex = value * (2.0 * pi * frequency) ** 2")
86 write_doc.add_paragraph("The frequency is that of the proton in Hertz.")
87
88
89 - def _are_mf_params_set(self, spin):
90 """Test if the model-free parameter values are set.
91
92 @param spin: The spin container object.
93 @type spin: SpinContainer instance
94 @return: The name of the first parameter in the parameter list in which the
95 corresponding parameter value is None. If all parameters are set, then None
96 is returned.
97 @rtype: str or None
98 """
99
100
101 if spin.select == 0:
102 return
103
104
105 for j in range(len(spin.params)):
106
107 if spin.params[j] == 'local_tm' and spin.local_tm == None:
108 return spin.params[j]
109
110
111 elif spin.params[j] == 's2' and spin.s2 == None:
112 return spin.params[j]
113
114
115 elif spin.params[j] == 's2f' and spin.s2f == None:
116 return spin.params[j]
117
118
119 elif spin.params[j] == 's2s' and spin.s2s == None:
120 return spin.params[j]
121
122
123 elif spin.params[j] == 'te' and spin.te == None:
124 return spin.params[j]
125
126
127 elif spin.params[j] == 'tf' and spin.tf == None:
128 return spin.params[j]
129
130
131 elif spin.params[j] == 'ts' and spin.ts == None:
132 return spin.params[j]
133
134
135 elif spin.params[j] == 'rex' and spin.rex == None:
136 return spin.params[j]
137
138
139 elif spin.params[j] == 'r' and spin.r == None:
140 return spin.params[j]
141
142
143 elif spin.params[j] == 'csa' and spin.csa == None:
144 return spin.params[j]
145
146
147 - def _assemble_param_names(self, model_type, spin_id=None):
148 """Function for assembling a list of all the model parameter names.
149
150 @param model_type: The model-free model type. This must be one of 'mf', 'local_tm',
151 'diff', or 'all'.
152 @type model_type: str
153 @param spin_id: The spin identification string.
154 @type spin_id: str
155 @return: A list containing all the parameters of the model-free model.
156 @rtype: list of str
157 """
158
159
160 param_names = []
161
162
163 if model_type == 'diff' or model_type == 'all':
164
165 if cdp.diff_tensor.type == 'sphere':
166 param_names.append('tm')
167
168
169 elif cdp.diff_tensor.type == 'spheroid':
170 param_names.append('tm')
171 param_names.append('Da')
172 param_names.append('theta')
173 param_names.append('phi')
174
175
176 elif cdp.diff_tensor.type == 'ellipsoid':
177 param_names.append('tm')
178 param_names.append('Da')
179 param_names.append('Dr')
180 param_names.append('alpha')
181 param_names.append('beta')
182 param_names.append('gamma')
183
184
185 if model_type != 'diff':
186
187 for spin in spin_loop(spin_id):
188
189 if not spin.select:
190 continue
191
192
193 param_names = param_names + spin.params
194
195
196 return param_names
197
198
199 - def _assemble_param_vector(self, spin=None, spin_id=None, sim_index=None, model_type=None):
200 """Assemble the model-free parameter vector (as numpy array).
201
202 If the spin argument is supplied, then the spin_id argument will be ignored.
203
204 @keyword spin: The spin data container.
205 @type spin: SpinContainer instance
206 @keyword spin_id: The spin identification string.
207 @type spin_id: str
208 @keyword sim_index: The optional MC simulation index.
209 @type sim_index: int
210 @keyword model_type: The optional model type, one of 'all', 'diff', 'mf', or 'local_tm'.
211 @type model_type: str or None
212 @return: An array of the parameter values of the model-free model.
213 @rtype: numpy array
214 """
215
216
217 param_vector = []
218
219
220 if not model_type:
221 model_type = self._determine_model_type()
222
223
224 if model_type == 'diff' or model_type == 'all':
225
226 if sim_index == None:
227
228 if cdp.diff_tensor.type == 'sphere':
229 param_vector.append(cdp.diff_tensor.tm)
230
231
232 elif cdp.diff_tensor.type == 'spheroid':
233 param_vector.append(cdp.diff_tensor.tm)
234 param_vector.append(cdp.diff_tensor.Da)
235 param_vector.append(cdp.diff_tensor.theta)
236 param_vector.append(cdp.diff_tensor.phi)
237
238
239 elif cdp.diff_tensor.type == 'ellipsoid':
240 param_vector.append(cdp.diff_tensor.tm)
241 param_vector.append(cdp.diff_tensor.Da)
242 param_vector.append(cdp.diff_tensor.Dr)
243 param_vector.append(cdp.diff_tensor.alpha)
244 param_vector.append(cdp.diff_tensor.beta)
245 param_vector.append(cdp.diff_tensor.gamma)
246
247
248 else:
249
250 if cdp.diff_tensor.type == 'sphere':
251 param_vector.append(cdp.diff_tensor.tm_sim[sim_index])
252
253
254 elif cdp.diff_tensor.type == 'spheroid':
255 param_vector.append(cdp.diff_tensor.tm_sim[sim_index])
256 param_vector.append(cdp.diff_tensor.Da_sim[sim_index])
257 param_vector.append(cdp.diff_tensor.theta_sim[sim_index])
258 param_vector.append(cdp.diff_tensor.phi_sim[sim_index])
259
260
261 elif cdp.diff_tensor.type == 'ellipsoid':
262 param_vector.append(cdp.diff_tensor.tm_sim[sim_index])
263 param_vector.append(cdp.diff_tensor.Da_sim[sim_index])
264 param_vector.append(cdp.diff_tensor.Dr_sim[sim_index])
265 param_vector.append(cdp.diff_tensor.alpha_sim[sim_index])
266 param_vector.append(cdp.diff_tensor.beta_sim[sim_index])
267 param_vector.append(cdp.diff_tensor.gamma_sim[sim_index])
268
269
270 if model_type != 'diff':
271
272 if spin:
273 loop = [spin]
274 else:
275 loop = spin_loop(spin_id)
276
277
278 for spin in loop:
279
280 if not spin.select:
281 continue
282
283
284 if not hasattr(spin, 'params'):
285 continue
286
287
288 for i in range(len(spin.params)):
289
290 if spin.params[i] == 'local_tm':
291 if sim_index == None:
292 param_vector.append(spin.local_tm)
293 else:
294 param_vector.append(spin.local_tm_sim[sim_index])
295
296
297 elif spin.params[i] == 's2':
298 if sim_index == None:
299 param_vector.append(spin.s2)
300 else:
301 param_vector.append(spin.s2_sim[sim_index])
302
303
304 elif spin.params[i] == 's2f':
305 if sim_index == None:
306 param_vector.append(spin.s2f)
307 else:
308 param_vector.append(spin.s2f_sim[sim_index])
309
310
311 elif spin.params[i] == 's2s':
312 if sim_index == None:
313 param_vector.append(spin.s2s)
314 else:
315 param_vector.append(spin.s2s_sim[sim_index])
316
317
318 elif spin.params[i] == 'te':
319 if sim_index == None:
320 param_vector.append(spin.te)
321 else:
322 param_vector.append(spin.te_sim[sim_index])
323
324
325 elif spin.params[i] == 'tf':
326 if sim_index == None:
327 param_vector.append(spin.tf)
328 else:
329 param_vector.append(spin.tf_sim[sim_index])
330
331
332 elif spin.params[i] == 'ts':
333 if sim_index == None:
334 param_vector.append(spin.ts)
335 else:
336 param_vector.append(spin.ts_sim[sim_index])
337
338
339 elif spin.params[i] == 'rex':
340 if sim_index == None:
341 param_vector.append(spin.rex)
342 else:
343 param_vector.append(spin.rex_sim[sim_index])
344
345
346 elif spin.params[i] == 'r':
347 if sim_index == None:
348 param_vector.append(spin.r)
349 else:
350 param_vector.append(spin.r_sim[sim_index])
351
352
353 elif spin.params[i] == 'csa':
354 if sim_index == None:
355 param_vector.append(spin.csa)
356 else:
357 param_vector.append(spin.csa_sim[sim_index])
358
359
360 else:
361 raise RelaxError("Unknown parameter.")
362
363
364 for i in range(len(param_vector)):
365 if param_vector[i] == None:
366 param_vector[i] = 0.0
367
368
369 return array(param_vector, float64)
370
371
372 - def _assemble_scaling_matrix(self, num_params, model_type=None, spin=None, spin_id=None, scaling=True):
373 """Create and return the scaling matrix.
374
375 If the spin argument is supplied, then the spin_id argument will be ignored.
376
377 @param num_params: The number of parameters in the model.
378 @type num_params: int
379 @keyword model_type: The model type, one of 'all', 'diff', 'mf', or 'local_tm'.
380 @type model_type: str
381 @keyword spin: The spin data container.
382 @type spin: SpinContainer instance
383 @keyword spin_id: The spin identification string.
384 @type spin_id: str
385 @return: The diagonal and square scaling matrix.
386 @rtype: numpy diagonal matrix
387 """
388
389
390 if num_params == 0:
391 scaling_matrix = zeros((0, 0), float64)
392 else:
393 scaling_matrix = identity(num_params, float64)
394 i = 0
395
396
397 if not scaling:
398 return scaling_matrix
399
400
401 ti_scaling = 1e-12
402
403
404 if model_type == 'diff' or model_type == 'all':
405
406 if cdp.diff_tensor.type == 'sphere':
407
408 scaling_matrix[i, i] = ti_scaling
409
410
411 i = i + 1
412
413
414 elif cdp.diff_tensor.type == 'spheroid':
415
416 scaling_matrix[i, i] = ti_scaling
417 scaling_matrix[i+1, i+1] = 1e7
418 scaling_matrix[i+2, i+2] = 1.0
419 scaling_matrix[i+3, i+3] = 1.0
420
421
422 i = i + 4
423
424
425 elif cdp.diff_tensor.type == 'ellipsoid':
426
427 scaling_matrix[i, i] = ti_scaling
428 scaling_matrix[i+1, i+1] = 1e7
429 scaling_matrix[i+2, i+2] = 1.0
430 scaling_matrix[i+3, i+3] = 1.0
431 scaling_matrix[i+4, i+4] = 1.0
432 scaling_matrix[i+5, i+5] = 1.0
433
434
435 i = i + 6
436
437
438 if model_type != 'diff':
439
440 if spin:
441 loop = [spin]
442 else:
443 loop = spin_loop(spin_id)
444
445
446 for spin in loop:
447
448 if not spin.select:
449 continue
450
451
452 for k in range(len(spin.params)):
453
454 if spin.params[k] == 'local_tm' or search('^t', spin.params[k]):
455 scaling_matrix[i, i] = ti_scaling
456
457
458 elif spin.params[k] == 'rex':
459 scaling_matrix[i, i] = 1.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]]) ** 2
460
461
462 elif spin.params[k] == 'r':
463 scaling_matrix[i, i] = 1e-10
464
465
466 elif spin.params[k] == 'csa':
467 scaling_matrix[i, i] = 1e-4
468
469
470 i = i + 1
471
472
473 return scaling_matrix
474
475
476 - def back_calc_ri(self, spin_index=None, ri_id=None, ri_type=None, frq=None):
477 """Back-calculation of relaxation data from the model-free parameter values.
478
479 @keyword spin_index: The global spin index.
480 @type spin_index: int
481 @keyword ri_id: The relaxation data ID string.
482 @type ri_id: str
483 @keyword ri_type: The relaxation data type.
484 @type ri_type: str
485 @keyword frq: The field strength.
486 @type frq: float
487 @return: The back calculated relaxation data value corresponding to the index.
488 @rtype: float
489 """
490
491
492 spin, spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True)
493
494
495 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'):
496 interatoms = interatomic.return_interatom_list(spin_id)
497 for i in range(len(interatoms)):
498
499 if not interatoms[i].dipole_pair:
500 continue
501
502
503 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector == None:
504 warn(RelaxDeselectWarning(spin_id, 'missing structural data'))
505 return
506
507
508 self.overfit_deselect(data_check=False, verbose=False)
509
510
511 value = self.minimise(min_algor='back_calc', min_options=(spin_index, ri_id, ri_type, frq))
512
513
514 return value
515
516
517 - def _compare_objects(self, object_from, object_to, pipe_from, pipe_to):
518 """Compare the contents of the two objects and raise RelaxErrors if they are not the same.
519
520 @param object_from: The first object.
521 @type object_from: any object
522 @param object_to: The second object.
523 @type object_to: any object
524 @param pipe_from: The name of the data pipe containing the first object.
525 @type pipe_from: str
526 @param pipe_to: The name of the data pipe containing the second object.
527 @type pipe_to: str
528 """
529
530
531 for data_name in dir(object_from):
532
533 if search('^_', data_name) or data_name in list(object_from.__class__.__dict__.keys()) or (hasattr(object_from.__class__, '__bases__') and len(object_from.__class__.__bases__) and data_name in list(object_from.__class__.__bases__[0].__dict__.keys())):
534 continue
535
536
537 if data_name in ['structural_data']:
538 continue
539
540
541 data_from = None
542 if hasattr(object_from, data_name):
543 data_from = getattr(object_from, data_name)
544
545
546 if data_from and not hasattr(object_to, data_name):
547 raise RelaxError("The structural object " + repr(data_name) + " of the " + repr(pipe_from) + " data pipe is not located in the " + repr(pipe_to) + " data pipe.")
548 elif data_from:
549 data_to = getattr(object_to, data_name)
550 else:
551 continue
552
553
554 if data_from != data_to:
555 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
556
557
559 """Calculate and return the Rex conversion factor.
560
561 @return: The Rex conversion factor.
562 @rtype: float
563 """
564
565
566 if not hasattr(cdp, 'frq'):
567 raise RelaxError("No spectrometer frequency information is present in the current data pipe.")
568
569
570 if hasattr(cdp, 'ri_ids'):
571 frq = cdp.frq[cdp.ri_ids[0]]
572
573
574 else:
575 frqs = sorted(cdp.frq.values())
576 frq = frqs[-1]
577
578
579 return 1.0 / (2.0 * pi * frq)**2
580
581
582 - def _create_model(self, model=None, equation=None, params=None, spin_id=None):
583 """Function for creating a custom model-free model.
584
585 @param model: The name of the model.
586 @type model: str
587 @param equation: The equation type to use. The 3 allowed types are: 'mf_orig' for the original model-free equations with parameters {s2, te}; 'mf_ext' for the extended model-free equations with parameters {s2f, tf, s2, ts}; and 'mf_ext2' for the extended model-free equations with parameters {s2f, tf, s2s, ts}.
588 @type equation: str
589 @param params: A list of the parameters to include in the model. The allowed parameter names includes those for the equation type as well as chemical exchange 'rex', the bond length 'r', and the chemical shift anisotropy 'csa'.
590 @type params: list of str
591 @param spin_id: The spin identification string.
592 @type spin_id: str
593 """
594
595
596 pipes.test()
597
598
599 function_type = pipes.get_type()
600 if function_type != 'mf':
601 raise RelaxFuncSetupError(specific_fns.get_string(function_type))
602
603
604 if not exists_mol_res_spin_data():
605 raise RelaxNoSequenceError
606
607
608 valid_types = ['mf_orig', 'mf_ext', 'mf_ext2']
609 if not equation in valid_types:
610 raise RelaxError("The model-free equation type argument " + repr(equation) + " is invalid and should be one of " + repr(valid_types) + ".")
611
612
613 s2, te, s2f, tf, s2s, ts, rex, csa, r = 0, 0, 0, 0, 0, 0, 0, 0, 0
614 for i in range(len(params)):
615
616 invalid_param = 0
617
618
619 if params[i] == 's2':
620
621 if s2:
622 invalid_param = 1
623 s2 = 1
624
625
626 s2s_flag = 0
627 for j in range(len(params)):
628 if params[j] == 's2s':
629 s2s_flag = 1
630 if s2s_flag:
631 invalid_param = 1
632
633
634 elif params[i] == 'te':
635
636 if equation == 'mf_ext' or te:
637 invalid_param = 1
638 te = 1
639
640
641 s2_flag = 0
642 for j in range(len(params)):
643 if params[j] == 's2':
644 s2_flag = 1
645 if not s2_flag:
646 invalid_param = 1
647
648
649 elif params[i] == 's2f':
650
651 if equation == 'mf_orig' or s2f:
652 invalid_param = 1
653 s2f = 1
654
655
656 elif params[i] == 's2s':
657
658 if equation == 'mf_orig' or s2s:
659 invalid_param = 1
660 s2s = 1
661
662
663 elif params[i] == 'tf':
664
665 if equation == 'mf_orig' or tf:
666 invalid_param = 1
667 tf = 1
668
669
670 s2f_flag = 0
671 for j in range(len(params)):
672 if params[j] == 's2f':
673 s2f_flag = 1
674 if not s2f_flag:
675 invalid_param = 1
676
677
678 elif params[i] == 'ts':
679
680 if equation == 'mf_orig' or ts:
681 invalid_param = 1
682 ts = 1
683
684
685 flag = 0
686 for j in range(len(params)):
687 if params[j] == 's2' or params[j] == 's2f':
688 flag = 1
689 if not flag:
690 invalid_param = 1
691
692
693 elif params[i] == 'rex':
694 if rex:
695 invalid_param = 1
696 rex = 1
697
698
699 elif params[i] == 'r':
700 if r:
701 invalid_param = 1
702 r = 1
703
704
705 elif params[i] == 'csa':
706 if csa:
707 invalid_param = 1
708 csa = 1
709
710
711 else:
712 raise RelaxError("The parameter " + params[i] + " is not supported.")
713
714
715 if invalid_param:
716 raise RelaxError("The parameter array " + repr(params) + " contains an invalid combination of parameters.")
717
718
719 self._model_setup(model, equation, params, spin_id)
720
721
723 """Delete all the model-free data."""
724
725
726 pipes.test()
727
728
729 function_type = pipes.get_type()
730 if function_type != 'mf':
731 raise RelaxFuncSetupError(specific_fns.setup.get_string(function_type))
732
733
734 if not exists_mol_res_spin_data():
735 raise RelaxNoSequenceError
736
737
738 names = self.data_names(scope='spin')
739
740
741 for spin in spin_loop():
742
743 for name in names:
744
745 if not hasattr(spin, name):
746 continue
747
748
749 delattr(spin, name)
750
751
753 """Determine the global model type.
754
755 @return: The name of the model type, which will be one of 'all', 'diff', 'mf', or 'local_tm'. If all parameters are fixed (and no spins selected), None is returned.
756 @rtype: str or None
757 """
758
759
760 if not exists_mol_res_spin_data():
761 raise RelaxNoSequenceError
762
763
764 local_tm = False
765 for spin in spin_loop():
766
767 if not spin.select:
768 continue
769
770
771 if not hasattr(spin, 'params') or not spin.params:
772 continue
773
774
775 if not local_tm and 'local_tm' in spin.params:
776 local_tm = True
777
778
779 elif local_tm and not 'local_tm' in spin.params:
780 raise RelaxError("All spins must either have a local tm parameter or not.")
781
782
783 mf_all_fixed = True
784 mf_all_deselected = True
785 for spin in spin_loop():
786
787 if not spin.select:
788 continue
789
790
791 mf_all_deselected = False
792
793
794 if not hasattr(spin, 'fixed'):
795 mf_all_fixed = False
796 break
797 if not spin.fixed:
798 mf_all_fixed = False
799 break
800
801
802 if mf_all_deselected:
803
804 if not hasattr(cdp, 'diff_tensor') or cdp.diff_tensor.fixed:
805 return None
806
807 return 'diff'
808
809
810 if local_tm:
811 return 'local_tm'
812
813
814 if not diffusion_tensor.diff_data_exists():
815
816 for spin in spin_loop():
817 if hasattr(spin, 'local_tm') and spin.local_tm != None and not 'local_tm' in spin.params:
818 raise RelaxError("The local tm value is set but not located in the model parameter list.")
819
820
821 raise RelaxNoTensorError('diffusion')
822
823
824 if mf_all_fixed:
825
826 if cdp.diff_tensor.fixed:
827 return None
828
829 return 'diff'
830
831
832 if cdp.diff_tensor.fixed:
833 return 'mf'
834
835
836 else:
837 return 'all'
838
839
840 - def _model_map(self, model):
841 """Return the equation name and parameter list corresponding to the given model.
842
843 @param model: The model-free model.
844 @type model: str
845 @return: The equation type (either 'mf_orig' or 'mf_ext') and the model-free parameter list corresponding to the model.
846 @rtype: str, list
847 """
848
849
850 if model == 'm0':
851 equation = 'mf_orig'
852 params = []
853 elif model == 'm1':
854 equation = 'mf_orig'
855 params = ['s2']
856 elif model == 'm2':
857 equation = 'mf_orig'
858 params = ['s2', 'te']
859 elif model == 'm3':
860 equation = 'mf_orig'
861 params = ['s2', 'rex']
862 elif model == 'm4':
863 equation = 'mf_orig'
864 params = ['s2', 'te', 'rex']
865 elif model == 'm5':
866 equation = 'mf_ext'
867 params = ['s2f', 's2', 'ts']
868 elif model == 'm6':
869 equation = 'mf_ext'
870 params = ['s2f', 'tf', 's2', 'ts']
871 elif model == 'm7':
872 equation = 'mf_ext'
873 params = ['s2f', 's2', 'ts', 'rex']
874 elif model == 'm8':
875 equation = 'mf_ext'
876 params = ['s2f', 'tf', 's2', 'ts', 'rex']
877 elif model == 'm9':
878 equation = 'mf_orig'
879 params = ['rex']
880
881
882 elif model == 'm10':
883 equation = 'mf_orig'
884 params = ['csa']
885 elif model == 'm11':
886 equation = 'mf_orig'
887 params = ['csa', 's2']
888 elif model == 'm12':
889 equation = 'mf_orig'
890 params = ['csa', 's2', 'te']
891 elif model == 'm13':
892 equation = 'mf_orig'
893 params = ['csa', 's2', 'rex']
894 elif model == 'm14':
895 equation = 'mf_orig'
896 params = ['csa', 's2', 'te', 'rex']
897 elif model == 'm15':
898 equation = 'mf_ext'
899 params = ['csa', 's2f', 's2', 'ts']
900 elif model == 'm16':
901 equation = 'mf_ext'
902 params = ['csa', 's2f', 'tf', 's2', 'ts']
903 elif model == 'm17':
904 equation = 'mf_ext'
905 params = ['csa', 's2f', 's2', 'ts', 'rex']
906 elif model == 'm18':
907 equation = 'mf_ext'
908 params = ['csa', 's2f', 'tf', 's2', 'ts', 'rex']
909 elif model == 'm19':
910 equation = 'mf_orig'
911 params = ['csa', 'rex']
912
913
914 elif model == 'm20':
915 equation = 'mf_orig'
916 params = ['r']
917 elif model == 'm21':
918 equation = 'mf_orig'
919 params = ['r', 's2']
920 elif model == 'm22':
921 equation = 'mf_orig'
922 params = ['r', 's2', 'te']
923 elif model == 'm23':
924 equation = 'mf_orig'
925 params = ['r', 's2', 'rex']
926 elif model == 'm24':
927 equation = 'mf_orig'
928 params = ['r', 's2', 'te', 'rex']
929 elif model == 'm25':
930 equation = 'mf_ext'
931 params = ['r', 's2f', 's2', 'ts']
932 elif model == 'm26':
933 equation = 'mf_ext'
934 params = ['r', 's2f', 'tf', 's2', 'ts']
935 elif model == 'm27':
936 equation = 'mf_ext'
937 params = ['r', 's2f', 's2', 'ts', 'rex']
938 elif model == 'm28':
939 equation = 'mf_ext'
940 params = ['r', 's2f', 'tf', 's2', 'ts', 'rex']
941 elif model == 'm29':
942 equation = 'mf_orig'
943 params = ['r', 'rex']
944
945
946 elif model == 'm30':
947 equation = 'mf_orig'
948 params = ['r', 'csa']
949 elif model == 'm31':
950 equation = 'mf_orig'
951 params = ['r', 'csa', 's2']
952 elif model == 'm32':
953 equation = 'mf_orig'
954 params = ['r', 'csa', 's2', 'te']
955 elif model == 'm33':
956 equation = 'mf_orig'
957 params = ['r', 'csa', 's2', 'rex']
958 elif model == 'm34':
959 equation = 'mf_orig'
960 params = ['r', 'csa', 's2', 'te', 'rex']
961 elif model == 'm35':
962 equation = 'mf_ext'
963 params = ['r', 'csa', 's2f', 's2', 'ts']
964 elif model == 'm36':
965 equation = 'mf_ext'
966 params = ['r', 'csa', 's2f', 'tf', 's2', 'ts']
967 elif model == 'm37':
968 equation = 'mf_ext'
969 params = ['r', 'csa', 's2f', 's2', 'ts', 'rex']
970 elif model == 'm38':
971 equation = 'mf_ext'
972 params = ['r', 'csa', 's2f', 'tf', 's2', 'ts', 'rex']
973 elif model == 'm39':
974 equation = 'mf_orig'
975 params = ['r', 'csa', 'rex']
976
977
978
979
980
981
982 elif model == 'tm0':
983 equation = 'mf_orig'
984 params = ['local_tm']
985 elif model == 'tm1':
986 equation = 'mf_orig'
987 params = ['local_tm', 's2']
988 elif model == 'tm2':
989 equation = 'mf_orig'
990 params = ['local_tm', 's2', 'te']
991 elif model == 'tm3':
992 equation = 'mf_orig'
993 params = ['local_tm', 's2', 'rex']
994 elif model == 'tm4':
995 equation = 'mf_orig'
996 params = ['local_tm', 's2', 'te', 'rex']
997 elif model == 'tm5':
998 equation = 'mf_ext'
999 params = ['local_tm', 's2f', 's2', 'ts']
1000 elif model == 'tm6':
1001 equation = 'mf_ext'
1002 params = ['local_tm', 's2f', 'tf', 's2', 'ts']
1003 elif model == 'tm7':
1004 equation = 'mf_ext'
1005 params = ['local_tm', 's2f', 's2', 'ts', 'rex']
1006 elif model == 'tm8':
1007 equation = 'mf_ext'
1008 params = ['local_tm', 's2f', 'tf', 's2', 'ts', 'rex']
1009 elif model == 'tm9':
1010 equation = 'mf_orig'
1011 params = ['local_tm', 'rex']
1012
1013
1014 elif model == 'tm10':
1015 equation = 'mf_orig'
1016 params = ['local_tm', 'csa']
1017 elif model == 'tm11':
1018 equation = 'mf_orig'
1019 params = ['local_tm', 'csa', 's2']
1020 elif model == 'tm12':
1021 equation = 'mf_orig'
1022 params = ['local_tm', 'csa', 's2', 'te']
1023 elif model == 'tm13':
1024 equation = 'mf_orig'
1025 params = ['local_tm', 'csa', 's2', 'rex']
1026 elif model == 'tm14':
1027 equation = 'mf_orig'
1028 params = ['local_tm', 'csa', 's2', 'te', 'rex']
1029 elif model == 'tm15':
1030 equation = 'mf_ext'
1031 params = ['local_tm', 'csa', 's2f', 's2', 'ts']
1032 elif model == 'tm16':
1033 equation = 'mf_ext'
1034 params = ['local_tm', 'csa', 's2f', 'tf', 's2', 'ts']
1035 elif model == 'tm17':
1036 equation = 'mf_ext'
1037 params = ['local_tm', 'csa', 's2f', 's2', 'ts', 'rex']
1038 elif model == 'tm18':
1039 equation = 'mf_ext'
1040 params = ['local_tm', 'csa', 's2f', 'tf', 's2', 'ts', 'rex']
1041 elif model == 'tm19':
1042 equation = 'mf_orig'
1043 params = ['local_tm', 'csa', 'rex']
1044
1045
1046 elif model == 'tm20':
1047 equation = 'mf_orig'
1048 params = ['local_tm', 'r']
1049 elif model == 'tm21':
1050 equation = 'mf_orig'
1051 params = ['local_tm', 'r', 's2']
1052 elif model == 'tm22':
1053 equation = 'mf_orig'
1054 params = ['local_tm', 'r', 's2', 'te']
1055 elif model == 'tm23':
1056 equation = 'mf_orig'
1057 params = ['local_tm', 'r', 's2', 'rex']
1058 elif model == 'tm24':
1059 equation = 'mf_orig'
1060 params = ['local_tm', 'r', 's2', 'te', 'rex']
1061 elif model == 'tm25':
1062 equation = 'mf_ext'
1063 params = ['local_tm', 'r', 's2f', 's2', 'ts']
1064 elif model == 'tm26':
1065 equation = 'mf_ext'
1066 params = ['local_tm', 'r', 's2f', 'tf', 's2', 'ts']
1067 elif model == 'tm27':
1068 equation = 'mf_ext'
1069 params = ['local_tm', 'r', 's2f', 's2', 'ts', 'rex']
1070 elif model == 'tm28':
1071 equation = 'mf_ext'
1072 params = ['local_tm', 'r', 's2f', 'tf', 's2', 'ts', 'rex']
1073 elif model == 'tm29':
1074 equation = 'mf_orig'
1075 params = ['local_tm', 'r', 'rex']
1076
1077
1078 elif model == 'tm30':
1079 equation = 'mf_orig'
1080 params = ['local_tm', 'r', 'csa']
1081 elif model == 'tm31':
1082 equation = 'mf_orig'
1083 params = ['local_tm', 'r', 'csa', 's2']
1084 elif model == 'tm32':
1085 equation = 'mf_orig'
1086 params = ['local_tm', 'r', 'csa', 's2', 'te']
1087 elif model == 'tm33':
1088 equation = 'mf_orig'
1089 params = ['local_tm', 'r', 'csa', 's2', 'rex']
1090 elif model == 'tm34':
1091 equation = 'mf_orig'
1092 params = ['local_tm', 'r', 'csa', 's2', 'te', 'rex']
1093 elif model == 'tm35':
1094 equation = 'mf_ext'
1095 params = ['local_tm', 'r', 'csa', 's2f', 's2', 'ts']
1096 elif model == 'tm36':
1097 equation = 'mf_ext'
1098 params = ['local_tm', 'r', 'csa', 's2f', 'tf', 's2', 'ts']
1099 elif model == 'tm37':
1100 equation = 'mf_ext'
1101 params = ['local_tm', 'r', 'csa', 's2f', 's2', 'ts', 'rex']
1102 elif model == 'tm38':
1103 equation = 'mf_ext'
1104 params = ['local_tm', 'r', 'csa', 's2f', 'tf', 's2', 'ts', 'rex']
1105 elif model == 'tm39':
1106 equation = 'mf_orig'
1107 params = ['local_tm', 'r', 'csa', 'rex']
1108
1109
1110 else:
1111 raise RelaxError("The model '%s' is invalid." % model)
1112
1113
1114 return equation, params
1115
1116
1117 - def _model_setup(self, model=None, equation=None, params=None, spin_id=None):
1118 """Function for updating various data structures depending on the model selected.
1119
1120 @param model: The name of the model.
1121 @type model: str
1122 @param equation: The equation type to use. The 3 allowed types are: 'mf_orig' for the original model-free equations with parameters {s2, te}; 'mf_ext' for the extended model-free equations with parameters {s2f, tf, s2, ts}; and 'mf_ext2' for the extended model-free equations with parameters {s2f, tf, s2s, ts}.
1123 @type equation: str
1124 @param params: A list of the parameters to include in the model. The allowed parameter names includes those for the equation type as well as chemical exchange 'rex', the bond length 'r', and the chemical shift anisotropy 'csa'.
1125 @type params: list of str
1126 @param spin_id: The spin identification string.
1127 @type spin_id: str
1128 """
1129
1130
1131 if params:
1132 for param in params:
1133 if param == 'local_tm' and hasattr(pipes.get_pipe(), 'diff_tensor'):
1134 raise RelaxTensorError('diffusion')
1135
1136
1137 for spin in spin_loop(spin_id):
1138
1139 self.data_init(spin)
1140
1141
1142 spin.model = model
1143 spin.equation = equation
1144 spin.params = params
1145
1146
1147 - def _remove_tm(self, spin_id=None):
1148 """Remove local tm from the set of model-free parameters for the given spins.
1149
1150 @param spin_id: The spin identification string.
1151 @type spin_id: str or None
1152 """
1153
1154
1155 pipes.test()
1156
1157
1158 function_type = pipes.get_type()
1159 if function_type != 'mf':
1160 raise RelaxFuncSetupError(specific_fns.get_string(function_type))
1161
1162
1163 if not exists_mol_res_spin_data():
1164 raise RelaxNoSequenceError
1165
1166
1167 for spin in spin_loop(spin_id):
1168
1169 if not spin.select:
1170 continue
1171
1172
1173 if not hasattr(spin, 'params') or not 'local_tm' in spin.params:
1174 continue
1175
1176
1177 spin.params.remove('local_tm')
1178
1179
1180 if match('^tm', spin.model):
1181 spin.model = spin.model[1:]
1182
1183
1184 del spin.local_tm
1185
1186
1187 spin.chi2 = None
1188 spin.iter = None
1189 spin.f_count = None
1190 spin.g_count = None
1191 spin.h_count = None
1192 spin.warning = None
1193
1194
1195 cdp.chi2 = None
1196 cdp.iter = None
1197 cdp.f_count = None
1198 cdp.g_count = None
1199 cdp.h_count = None
1200 cdp.warning = None
1201
1202
1203 - def _select_model(self, model=None, spin_id=None):
1204 """Function for the selection of a preset model-free model.
1205
1206 @param model: The name of the model.
1207 @type model: str
1208 @param spin_id: The spin identification string.
1209 @type spin_id: str
1210 """
1211
1212
1213 pipes.test()
1214
1215
1216 function_type = pipes.get_type()
1217 if function_type != 'mf':
1218 raise RelaxFuncSetupError(specific_fns.get_string(function_type))
1219
1220
1221 if not exists_mol_res_spin_data():
1222 raise RelaxNoSequenceError
1223
1224
1225 equation, params = self._model_map(model)
1226
1227
1228 self._model_setup(model, equation, params, spin_id)
1229
1230
1231 - def _units_rex(self):
1232 """Return the units for the Rex parameter.
1233
1234 @return: The field strength dependent Rex units.
1235 @rtype: str
1236 """
1237
1238
1239 if not hasattr(cdp, 'frq_labels') or len(cdp.frq_labels) == 0:
1240 return ''
1241
1242
1243 return cdp.frq_labels[0] + ' MHz'
1244
1245
1246 - def create_mc_data(self, data_id=None):
1247 """Create the Monte Carlo Ri data.
1248
1249 @keyword data_id: The spin identification string, as yielded by the base_data_loop() generator method.
1250 @type data_id: str
1251 @return: The Monte Carlo simulation data.
1252 @rtype: list of floats
1253 """
1254
1255
1256 mc_data = []
1257
1258
1259 spin = return_spin(data_id)
1260 global_index = find_index(data_id)
1261
1262
1263 if not spin.select:
1264 return
1265
1266
1267 if not hasattr(spin, 'model') or not spin.model:
1268 raise RelaxNoModelError
1269
1270
1271 for ri_id in cdp.ri_ids:
1272
1273 value = self.back_calc_ri(spin_index=global_index, ri_id=ri_id, ri_type=cdp.ri_type[ri_id], frq=cdp.frq[ri_id])
1274
1275
1276 mc_data.append(value)
1277
1278
1279 return mc_data
1280
1281
1282 - def data_init(self, data_cont, sim=False):
1283 """Initialise the spin specific data structures.
1284
1285 @param data_cont: The spin data container.
1286 @type data_cont: SpinContainer instance
1287 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure.
1288 @type sim: bool
1289 """
1290
1291
1292 for name in self.PARAMS.loop(scope='spin'):
1293
1294 if name in ['ri_data', 'ri_data_bc', 'ri_data_err']:
1295 continue
1296
1297
1298 list_data = [ 'params' ]
1299 if name in list_data:
1300 init_data = []
1301
1302
1303 init_data = None
1304 if self.PARAMS.get_type(name) == bool:
1305 init_data = False
1306 if name == 'select':
1307 init_data = True
1308
1309
1310 if not hasattr(data_cont, name):
1311 setattr(data_cont, name, init_data)
1312
1313
1314 - def data_type(self, param=None):
1315 """Return the type of data, as a string, that the parameter should be.
1316
1317 @keyword param: The parameter name.
1318 @type param: list of str
1319 @return: The type of the parameter, as a string. I.e. 'int', 'float', 'str', 'bool', 'list of str', 'dict of bool', etc.
1320 @rtype: str
1321 """
1322
1323
1324 types = {
1325 'select': bool,
1326 'fixed': bool,
1327 'nucleus': str,
1328 'model': str,
1329 'equation': str,
1330 'params': [str],
1331 's2': float,
1332 's2f': float,
1333 's2s': float,
1334 'local_tm': float,
1335 'te': float,
1336 'tf': float,
1337 'ts': float,
1338 'rex': float,
1339 'csa': float,
1340 'chi2': float,
1341 'iter': int,
1342 'f_count': int,
1343 'g_count': int,
1344 'h_count': int,
1345 'warning': str
1346 }
1347
1348
1349 if param in types:
1350 return types[param]
1351
1352
1353 - def default_value(self, param):
1354 """The default model-free parameter values.
1355
1356 @param param: The model-free parameter.
1357 @type param: str
1358 @return: The default value.
1359 @rtype: float
1360 """
1361
1362
1363 diff_val = diffusion_tensor.default_value(param)
1364 if diff_val != None:
1365 return diff_val
1366
1367
1368 return self.PARAMS.get_default(param)
1369
1370
1371 - def deselect(self, model_info, sim_index=None):
1372 """Deselect models or simulations.
1373
1374 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1375 @type model_info: int
1376 @keyword sim_index: The optional Monte Carlo simulation index. If None, then models will be deselected, otherwise the given simulation will.
1377 @type sim_index: None or int
1378 """
1379
1380
1381 model_type = self._determine_model_type()
1382
1383
1384 if model_type == 'mf' or model_type == 'local_tm':
1385
1386 spin = return_spin_from_index(model_info)
1387
1388
1389 if sim_index == None:
1390 spin.select = False
1391
1392
1393 else:
1394 spin.select_sim[sim_index] = False
1395
1396
1397 else:
1398
1399 if sim_index == None:
1400 raise RelaxError("Cannot deselect the global model.")
1401
1402
1403 else:
1404
1405 cdp.select_sim[sim_index] = False
1406
1407
1408 - def duplicate_data(self, pipe_from=None, pipe_to=None, model_info=None, global_stats=False, verbose=True):
1409 """Duplicate the data specific to a single model-free model.
1410
1411 @keyword pipe_from: The data pipe to copy the data from.
1412 @type pipe_from: str
1413 @keyword pipe_to: The data pipe to copy the data to.
1414 @type pipe_to: str
1415 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1416 @type model_info: int
1417 @keyword global_stats: The global statistics flag.
1418 @type global_stats: bool
1419 @keyword verbose: A flag which if True will cause info about each spin to be printed out as the sequence is generated.
1420 @type verbose: bool
1421 """
1422
1423
1424 if model_info == None:
1425 raise RelaxError("The model_info argument cannot be None.")
1426
1427
1428 if not pipes.has_pipe(pipe_to):
1429 pipes.create(pipe_to, pipe_type='mf', switch=False)
1430
1431
1432 dp_from = pipes.get_pipe(pipe_from)
1433 dp_to = pipes.get_pipe(pipe_to)
1434
1435
1436 for data_name in dir(dp_from):
1437
1438 if data_name in ['diff_tensor', 'mol', 'interatomic', 'structure', 'exp_info']:
1439 continue
1440
1441
1442 if search('^_', data_name) or data_name in list(dp_from.__class__.__dict__.keys()):
1443 continue
1444
1445
1446 data_from = getattr(dp_from, data_name)
1447
1448
1449 if hasattr(dp_to, data_name):
1450
1451 data_to = getattr(dp_to, data_name)
1452
1453
1454 if data_from != data_to:
1455 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
1456
1457
1458 continue
1459
1460
1461 setattr(dp_to, data_name, deepcopy(data_from))
1462
1463
1464 if hasattr(dp_from, 'diff_tensor'):
1465
1466 if not hasattr(dp_to, 'diff_tensor'):
1467 setattr(dp_to, 'diff_tensor', deepcopy(dp_from.diff_tensor))
1468
1469
1470 else:
1471
1472 for data_name in dp_from.diff_tensor._mod_attr:
1473
1474 data_from = None
1475 if hasattr(dp_from.diff_tensor, data_name):
1476 data_from = getattr(dp_from.diff_tensor, data_name)
1477
1478
1479 if data_from and not hasattr(dp_to.diff_tensor, data_name):
1480 raise RelaxError("The diffusion tensor object " + repr(data_name) + " of the " + repr(pipe_from) + " data pipe is not located in the " + repr(pipe_to) + " data pipe.")
1481 elif data_from:
1482 data_to = getattr(dp_to.diff_tensor, data_name)
1483 else:
1484 continue
1485
1486
1487 if data_from != data_to:
1488 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
1489
1490
1491 if hasattr(dp_from, 'structure'):
1492
1493 if not hasattr(dp_to, 'structure'):
1494 setattr(dp_to, 'structure', deepcopy(dp_from.structure))
1495
1496
1497 else:
1498
1499 self._compare_objects(dp_from.structure, dp_to.structure, pipe_from, pipe_to)
1500
1501
1502 if len(dp_from.structure.structural_data) != len(dp_from.structure.structural_data):
1503 raise RelaxError("The number of structural models is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
1504
1505
1506 for i in range(len(dp_from.structure.structural_data)):
1507
1508 model_from = dp_from.structure.structural_data[i]
1509 model_to = dp_to.structure.structural_data[i]
1510
1511
1512 if model_from.num != model_to.num:
1513 raise RelaxError("The structure models are not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
1514
1515
1516 if len(model_from.mol) != len(model_to.mol):
1517 raise RelaxError("The number of molecules is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
1518
1519
1520 for mol_index in range(len(model_from.mol)):
1521
1522 self._compare_objects(model_from.mol[mol_index], model_to.mol[mol_index], pipe_from, pipe_to)
1523
1524
1525 if dp_from.mol.is_empty():
1526 return
1527
1528
1529 if dp_to.mol.is_empty():
1530 sequence.copy(pipe_from=pipe_from, pipe_to=pipe_to, preserve_select=True, verbose=verbose)
1531
1532
1533 if dp_to.interatomic.is_empty():
1534 interatomic.copy(pipe_from=pipe_from, pipe_to=pipe_to, verbose=verbose)
1535
1536
1537 pipes.switch(pipe_from)
1538 model_type = self._determine_model_type()
1539
1540
1541 spin, spin_id = return_spin_from_index(model_info, pipe=pipe_from, return_spin_id=True)
1542 if model_type == 'mf' or (model_type == 'local_tm' and not global_stats):
1543
1544 for name in dir(spin):
1545
1546 if search('^__', name):
1547 continue
1548
1549
1550 obj = getattr(spin, name)
1551
1552
1553 if isinstance(obj, MethodType):
1554 continue
1555
1556
1557 new_obj = deepcopy(getattr(spin, name))
1558 setattr(dp_to.mol[spin._mol_index].res[spin._res_index].spin[spin._spin_index], name, new_obj)
1559
1560
1561 interatoms = interatomic.return_interatom_list(spin_id)
1562 for interatom in interatoms:
1563
1564 if not interatom.dipole_pair:
1565 continue
1566
1567
1568 if spin_id != interatom.spin_id1:
1569 spin_id2 = interatom.spin_id1
1570 else:
1571 spin_id2 = interatom.spin_id2
1572 spin2 = return_spin(spin_id2)
1573
1574
1575 mol_index, res_index, spin_index = return_spin_indices(spin_id2)
1576 dp_to.mol[mol_index].res[res_index].spin[spin_index] = deepcopy(spin2)
1577
1578
1579 else:
1580
1581 dp_to.mol = deepcopy(dp_from.mol)
1582
1583
1584 eliminate_doc = []
1585 eliminate_doc.append(Desc_container("Local tm model elimination rule"))
1586 eliminate_doc[-1].add_paragraph("The local tm, in some cases, may exceed the value expected for a global correlation time. Generally the tm value will be stuck at the upper limit defined for the parameter. These models are eliminated using the rule:")
1587 eliminate_doc[-1].add_verbatim(" tm >= c")
1588 eliminate_doc[-1].add_paragraph("The default value of c is 50 ns, although this can be overridden by supplying the value (in seconds) as the first element of the args tuple.")
1589 eliminate_doc.append(Desc_container("Internal correlation times {te, tf, ts} model elimination rules"))
1590 eliminate_doc[-1].add_paragraph("These parameters may experience the same problem as the local tm in that the model fails and the parameter value is stuck at the upper limit. These parameters are constrained using the formula (te, tf, ts <= 2tm). These failed models are eliminated using the rule:")
1591 eliminate_doc[-1].add_verbatim(" te, tf, ts >= c . tm.")
1592 eliminate_doc[-1].add_paragraph("The default value of c is 1.5. Because of round-off errors and the constraint algorithm, setting c to 2 will result in no models being eliminated as the minimised parameters will always be less than 2tm. The value can be changed by supplying the value as the second element of the tuple.")
1593 eliminate_doc.append(Desc_container("Arguments"))
1594 eliminate_doc[-1].add_paragraph("The 'args' argument must be a tuple of length 2, the elements of which must be numbers. For example, to eliminate models which have a local tm value greater than 25 ns and models with internal correlation times greater than 1.5 times tm, set 'args' to (25 * 1e-9, 1.5).")
1595
1596 - def eliminate(self, name, value, model_info, args, sim=None):
1597 """Model-free model elimination, parameter by parameter.
1598
1599 @param name: The parameter name.
1600 @type name: str
1601 @param value: The parameter value.
1602 @type value: float
1603 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1604 @type model_info: int
1605 @param args: The c1 and c2 elimination constant overrides.
1606 @type args: None or tuple of float
1607 @keyword sim: The Monte Carlo simulation index.
1608 @type sim: int
1609 @return: True if the model is to be eliminated, False otherwise.
1610 @rtype: bool
1611 """
1612
1613
1614 c1 = 50.0 * 1e-9
1615 c2 = 1.5
1616
1617
1618 if args != None:
1619 c1, c2 = args
1620
1621
1622 model_type = self._determine_model_type()
1623
1624
1625 if model_type != 'mf' and model_type != 'local_tm':
1626 raise RelaxError("Elimination of the global model is not yet supported.")
1627
1628
1629 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True)
1630
1631
1632 if model_type == 'local_tm':
1633 tm = spin.local_tm
1634 else:
1635 tm = cdp.diff_tensor.tm
1636
1637
1638 if tm == None:
1639 return False
1640
1641
1642 if name == 'local_tm' and value >= c1:
1643 if sim == None:
1644 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), value, c1, spin_id))
1645 else:
1646 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), value, c1, sim, spin_id))
1647 return True
1648
1649
1650 if match('t[efs]', name) and value >= c2 * tm:
1651 if sim == None:
1652 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, spin_id))
1653 else:
1654 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, sim, spin_id))
1655 return True
1656
1657
1658 return False
1659
1660
1661 - def get_param_names(self, model_info=None):
1662 """Return a vector of parameter names.
1663
1664 @keyword model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1665 @type model_info: int
1666 @return: The vector of parameter names.
1667 @rtype: list of str
1668 """
1669
1670
1671 model_type = self._determine_model_type()
1672
1673
1674 if model_type == 'mf' or model_type == 'local_tm':
1675
1676 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True)
1677 else:
1678 spin_id = None
1679
1680
1681 return self._assemble_param_names(model_type, spin_id=spin_id)
1682
1683
1684 - def get_param_values(self, model_info=None, sim_index=None):
1685 """Return a vector of parameter values.
1686
1687 @keyword model_info: The model index from model_info(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1688 @type model_info: int
1689 @keyword sim_index: The Monte Carlo simulation index.
1690 @type sim_index: int
1691 @return: The vector of parameter values.
1692 @rtype: list of str
1693 """
1694
1695
1696 for spin in spin_loop():
1697
1698 if not spin.select:
1699 continue
1700
1701
1702 if not spin.model:
1703 raise RelaxNoModelError
1704
1705
1706 model_type = self._determine_model_type()
1707
1708
1709 if model_type == 'mf' or model_type == 'local_tm':
1710 spin = return_spin_from_index(model_info)
1711 else:
1712 spin = None
1713
1714
1715 return self._assemble_param_vector(spin=spin, sim_index=sim_index, model_type=model_type)
1716
1717
1718 - def is_spin_param(self, name):
1719 """Determine whether the given parameter is spin specific.
1720
1721 Unless a diffusion parameter is encountered, this method will return true.
1722
1723 @param name: The name of the parameter.
1724 @type name: str
1725 @return: If the parameter is a diffusion parameter, False I returned. Otherwise True
1726 is returned.
1727 @rtype: bool
1728 """
1729
1730
1731 if diffusion_tensor.return_data_name(name):
1732 return False
1733
1734
1735 else:
1736 return True
1737
1738
1739 - def map_bounds(self, param, spin_id=None):
1740 """Create bounds for the OpenDX mapping function.
1741
1742 @param param: The name of the parameter to return the lower and upper bounds of.
1743 @type param: str
1744 @param spin_id: The spin identification string.
1745 @type spin_id: str
1746 @return: The upper and lower bounds of the parameter.
1747 @rtype: list of float
1748 """
1749
1750
1751 spin = return_spin(spin_id)
1752
1753
1754 if search('^s2', param):
1755 return [0.0, 1.0]
1756
1757
1758 elif search('^t', param) or param == 'local_tm':
1759 return [0.0, 1e-8]
1760
1761
1762 elif param == 'rex':
1763 return [0.0, 30.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2]
1764
1765
1766 elif param == 'r':
1767 return [1.0 * 1e-10, 1.1 * 1e-10]
1768
1769
1770 elif param == 'csa':
1771 return [-100 * 1e-6, -300 * 1e-6]
1772
1773
1774 - def model_desc(self, model_info):
1775 """Return a description of the model.
1776
1777 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1778 @type model_info: int
1779 @return: The model description.
1780 @rtype: str
1781 """
1782
1783
1784 model_type = self._determine_model_type()
1785
1786
1787 if model_type == 'all':
1788 return "Global model - all diffusion tensor parameters and spin specific model-free parameters."
1789 elif model_type == 'diff':
1790 return "Diffusion tensor model."
1791
1792
1793 else:
1794
1795 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True)
1796
1797
1798 return "Model-free model of spin '%s'." % spin_id
1799
1800
1801 - def model_loop(self):
1802 """Generator method for looping over the models (global or local).
1803
1804 If the model type is 'all' or 'diff', then this yields the single value of zero. Otherwise
1805 the global spin index is yielded.
1806
1807
1808 @return: The model index. This is zero for the global models or equal to the global spin
1809 index (which covers the molecule, residue, and spin indices).
1810 @rtype: int
1811 """
1812
1813
1814 model_type = self._determine_model_type()
1815
1816
1817 if model_type == 'all' or model_type == 'diff':
1818 yield 0
1819
1820
1821 else:
1822
1823 global_index = -1
1824 for spin in spin_loop():
1825
1826 global_index = global_index + 1
1827
1828
1829 yield global_index
1830
1831
1832 - def model_statistics(self, model_info=None, spin_id=None, global_stats=None):
1833 """Return the k, n, and chi2 model statistics.
1834
1835 k - number of parameters.
1836 n - number of data points.
1837 chi2 - the chi-squared value.
1838
1839
1840 @keyword model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
1841 @type model_info: int
1842 @keyword spin_id: The spin identification string. Either this or the instance keyword argument must be supplied.
1843 @type spin_id: None or str
1844 @keyword global_stats: A parameter which determines if global or local statistics are returned. If None, then the appropriateness of global or local statistics is automatically determined.
1845 @type global_stats: None or bool
1846 @return: The optimisation statistics, in tuple format, of the number of parameters (k), the number of data points (n), and the chi-squared value (chi2).
1847 @rtype: tuple of (int, int, float)
1848 """
1849
1850
1851 if model_info == None and spin_id == None:
1852 raise RelaxError("Either the model_info or spin_id argument must be supplied.")
1853 elif model_info != None and spin_id != None:
1854 raise RelaxError("The model_info arg " + repr(model_info) + " and spin_id arg " + repr(spin_id) + " clash. Only one should be supplied.")
1855
1856
1857 model_type = self._determine_model_type()
1858
1859
1860 if global_stats == None:
1861 if model_type in ['mf', 'local_tm']:
1862 global_stats = False
1863 else:
1864 global_stats = True
1865
1866
1867 if not global_stats:
1868
1869 if spin_id:
1870 spin = return_spin(spin_id)
1871 else:
1872 spin = return_spin_from_index(model_info)
1873
1874
1875 if not spin.select:
1876 return None, None, None
1877
1878
1879 if not hasattr(spin, 'ri_data'):
1880 return None, None, None
1881
1882
1883 param_vector = self._assemble_param_vector(spin=spin)
1884 k = len(param_vector)
1885
1886
1887 n = len(spin.ri_data)
1888
1889
1890 chi2 = spin.chi2
1891
1892
1893 elif global_stats:
1894
1895 param_vector = self._assemble_param_vector()
1896 k = len(param_vector)
1897
1898
1899 n = 0
1900 chi2 = 0
1901 for spin in spin_loop():
1902
1903 if not spin.select:
1904 continue
1905
1906
1907 if not hasattr(spin, 'ri_data') or not len(spin.ri_data):
1908 continue
1909
1910 n = n + len(spin.ri_data)
1911
1912
1913 if model_type == 'local_tm':
1914 chi2 = chi2 + spin.chi2
1915
1916
1917 if model_type != 'local_tm':
1918 if not hasattr(cdp, 'chi2'):
1919 raise RelaxError("Global statistics are not available, most likely because the global model has not been optimised.")
1920 chi2 = cdp.chi2
1921
1922
1923 return k, n, chi2
1924
1925
1926 - def model_type(self):
1927 """Return the type of the model, either being 'local' or 'global'.
1928
1929 @return: The model type, one of 'local' or 'global'.
1930 @rtype: str
1931 """
1932
1933
1934 model_type = self._determine_model_type()
1935
1936
1937 if model_type in ['all', 'diff']:
1938 return 'global'
1939
1940
1941 else:
1942 return 'local'
1943
1944
1945 - def num_instances(self):
1946 """Function for returning the number of instances.
1947
1948 @return: The number of instances used for optimisation. Either the number of spins if
1949 the local optimisations are setup ('mf' and 'local_tm'), or 1 for the global
1950 models.
1951 @rtype: int
1952 """
1953
1954
1955 if not exists_mol_res_spin_data():
1956 return 0
1957
1958
1959 model_type = self._determine_model_type()
1960
1961
1962 if model_type == 'mf' or model_type == 'local_tm':
1963 return count_spins()
1964
1965
1966 elif model_type == 'diff' or model_type == 'all':
1967 return 1
1968
1969
1970 else:
1971 raise RelaxFault
1972
1973
1974 - def overfit_deselect(self, data_check=True, verbose=True):
1975 """Deselect spins which have insufficient data to support minimisation.
1976
1977 @keyword data_check: A flag to signal if the presence of base data is to be checked for.
1978 @type data_check: bool
1979 @keyword verbose: A flag which if True will allow printouts.
1980 @type verbose: bool
1981 """
1982
1983
1984 if verbose:
1985 print("\nOver-fit spin deselection:")
1986
1987
1988 if not exists_mol_res_spin_data():
1989 raise RelaxNoSequenceError
1990
1991
1992 need_vect = False
1993 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'):
1994 need_vect = True
1995
1996
1997 deselect_flag = False
1998 spin_count = 0
1999 for spin, spin_id in spin_loop(return_id=True):
2000
2001 if not spin.select:
2002 continue
2003
2004
2005 interatoms = interatomic.return_interatom_list(spin_id)
2006
2007
2008 dipole_relax = False
2009 for i in range(len(interatoms)):
2010
2011 if not interatoms[i].dipole_pair:
2012 continue
2013
2014
2015 if spin_id != interatoms[i].spin_id1:
2016 spin_id2 = interatoms[i].spin_id1
2017 else:
2018 spin_id2 = interatoms[i].spin_id2
2019 spin2 = return_spin(spin_id2)
2020
2021
2022 dipole_relax = False
2023
2024
2025 if not dipole_relax and not hasattr(spin, 'csa') or spin.csa == None:
2026 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms'))
2027 spin.select = False
2028 deselect_flag = True
2029 continue
2030
2031
2032 if data_check:
2033
2034 data_points = 0
2035 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'):
2036 for id in cdp.ri_ids:
2037 if id in spin.ri_data and spin.ri_data[id] != None:
2038 data_points += 1
2039
2040
2041 if not hasattr(spin, 'ri_data'):
2042 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data'))
2043 spin.select = False
2044 deselect_flag = True
2045 continue
2046
2047
2048 elif data_points < 3:
2049 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required'))
2050 spin.select = False
2051 deselect_flag = True
2052 continue
2053
2054
2055 elif hasattr(spin, 'params') and spin.params and len(spin.params) > data_points:
2056 warn(RelaxDeselectWarning(spin_id, 'over-fitting - more parameters than data points'))
2057 spin.select = False
2058 deselect_flag = True
2059 continue
2060
2061
2062 for i in range(len(interatoms)):
2063
2064 if not interatoms[i].dipole_pair:
2065 continue
2066
2067
2068 if need_vect:
2069 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector == None:
2070 warn(RelaxDeselectWarning(spin_id, 'missing structural data'))
2071 spin.select = False
2072 deselect_flag = True
2073 continue
2074
2075
2076 spin_count += 1
2077
2078
2079 if spin_count == 0:
2080 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed."))
2081
2082
2083 if verbose and not deselect_flag:
2084 print("No spins have been deselected.")
2085
2086
2087 - def set_error(self, model_info, index, error):
2088 """Set the parameter errors.
2089
2090 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2091 @type model_info: int
2092 @param index: The index of the parameter to set the errors for.
2093 @type index: int
2094 @param error: The error value.
2095 @type error: float
2096 """
2097
2098
2099 inc = 0
2100
2101
2102 model_type = self._determine_model_type()
2103
2104
2105 param_names = self.data_names(set='params', scope='spin')
2106
2107
2108
2109
2110
2111 if model_type == 'diff' or model_type == 'all':
2112
2113 if cdp.diff_tensor.type == 'sphere':
2114
2115 if index == 0:
2116 cdp.diff_tensor.set(param='tm', value=error, category='err')
2117
2118
2119 inc = inc + 1
2120
2121
2122 elif cdp.diff_tensor.type == 'spheroid':
2123
2124 if index == 0:
2125 cdp.diff_tensor.set(param='tm', value=error, category='err')
2126 elif index == 1:
2127 cdp.diff_tensor.set(param='Da', value=error, category='err')
2128 elif index == 2:
2129 cdp.diff_tensor.set(param='theta', value=error, category='err')
2130 elif index == 3:
2131 cdp.diff_tensor.set(param='phi', value=error, category='err')
2132
2133
2134 inc = inc + 4
2135
2136
2137 elif cdp.diff_tensor.type == 'ellipsoid':
2138
2139 if index == 0:
2140 cdp.diff_tensor.set(param='tm', value=error, category='err')
2141 elif index == 1:
2142 cdp.diff_tensor.set(param='Da', value=error, category='err')
2143 elif index == 2:
2144 cdp.diff_tensor.set(param='Dr', value=error, category='err')
2145 elif index == 3:
2146 cdp.diff_tensor.set(param='alpha', value=error, category='err')
2147 elif index == 4:
2148 cdp.diff_tensor.set(param='beta', value=error, category='err')
2149 elif index == 5:
2150 cdp.diff_tensor.set(param='gamma', value=error, category='err')
2151
2152
2153 inc = inc + 6
2154
2155
2156
2157
2158
2159 if model_type == 'all':
2160
2161 for spin in spin_loop():
2162
2163 if not spin.select:
2164 continue
2165
2166
2167 for param in param_names:
2168
2169 if index == inc:
2170 setattr(spin, param + "_err", error)
2171
2172
2173 inc = inc + 1
2174
2175
2176
2177
2178
2179 if model_type == 'mf' or model_type == 'local_tm':
2180
2181 spin = return_spin_from_index(model_info)
2182
2183
2184 if not spin.select:
2185 return
2186
2187
2188 for param in param_names:
2189
2190 if index == inc:
2191 setattr(spin, param + "_err", error)
2192
2193
2194 inc = inc + 1
2195
2196
2197 - def set_param_values(self, param=None, value=None, spin_id=None, force=True):
2198 """Set the model-free parameter values.
2199
2200 @keyword param: The parameter name list.
2201 @type param: list of str
2202 @keyword value: The parameter value list.
2203 @type value: list
2204 @keyword spin_id: The spin identification string, only used for spin specific parameters.
2205 @type spin_id: None or str
2206 @keyword force: A flag which if True will cause current values to be overwritten. If False, a RelaxError will raised if the parameter value is already set.
2207 @type force: bool
2208 """
2209
2210
2211 arg_check.is_str_list(param, 'parameter name')
2212
2213
2214 diff_params = []
2215 diff_vals = []
2216 mf_params = []
2217 mf_vals = []
2218 for i in range(len(param)):
2219
2220 diff_obj = diffusion_tensor.return_data_name(param[i])
2221 if diff_obj:
2222 diff_params.append(param[i])
2223 diff_vals.append(value[i])
2224
2225
2226 else:
2227 mf_params.append(param[i])
2228 mf_vals.append(value[i])
2229
2230
2231 if diff_params:
2232 diffusion_tensor.set(value=diff_vals, param=diff_params)
2233
2234
2235 for i in range(len(mf_params)):
2236
2237 obj_name = self.return_data_name(mf_params[i])
2238
2239
2240 if obj_name not in self.data_names(set='params', scope='spin') and obj_name not in self.data_names(set='generic', scope='spin'):
2241 raise RelaxError("The parameter '%s' is unknown. It should be one of %s or %s" % (mf_params[i], self.data_names(set='params', scope='spin'), self.data_names(set='generic', scope='spin')))
2242
2243
2244 for spin in spin_loop(spin_id):
2245 setattr(spin, obj_name, mf_vals[i])
2246
2247
2248 - def set_selected_sim(self, model_info, select_sim):
2249 """Set all simulation selection flags.
2250
2251 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2252 @type model_info: int
2253 @param select_sim: The selection flags.
2254 @type select_sim: bool
2255 """
2256
2257
2258 model_type = self._determine_model_type()
2259
2260
2261 if model_type == 'all' or model_type == 'diff':
2262 cdp.select_sim = select_sim
2263
2264
2265 else:
2266
2267 spin = return_spin_from_index(model_info)
2268
2269
2270 if not spin.select:
2271 return
2272
2273
2274 spin.select_sim = deepcopy(select_sim)
2275
2276
2277 - def set_update(self, param, spin):
2278 """Function to update the other model-free parameters.
2279
2280 @param param: The name of the parameter which has been changed.
2281 @type param: str
2282 @param spin: The SpinContainer object.
2283 @type spin: SpinContainer
2284 """
2285
2286
2287 if param == 's2f':
2288
2289 if hasattr(spin, 's2s') and spin.s2s != None:
2290 spin.s2 = spin.s2f * spin.s2s
2291
2292
2293
2294 if param == 's2s':
2295
2296 if hasattr(spin, 's2f') and spin.s2f != None:
2297 spin.s2 = spin.s2f * spin.s2s
2298
2299
2300 - def sim_init_values(self):
2301 """Initialise the Monte Carlo parameter values."""
2302
2303
2304 model_type = self._determine_model_type()
2305
2306
2307 param_names = self.data_names(set='params', scope='spin')
2308
2309
2310 min_names = self.data_names(set='min', scope='spin')
2311
2312
2313 if model_type == 'diff' or model_type == 'all':
2314
2315 if cdp.diff_tensor.type == 'sphere':
2316 diff_params = ['tm']
2317
2318
2319 elif cdp.diff_tensor.type == 'spheroid':
2320 diff_params = ['tm', 'Da', 'theta', 'phi']
2321
2322
2323 elif cdp.diff_tensor.type == 'ellipsoid':
2324 diff_params = ['tm', 'Da', 'Dr', 'alpha', 'beta', 'gamma']
2325
2326
2327
2328
2329
2330
2331 if model_type == 'diff' or model_type == 'all':
2332
2333 for object_name in diff_params:
2334
2335 sim_object_name = object_name + '_sim'
2336
2337
2338 if hasattr(cdp.diff_tensor, sim_object_name):
2339 raise RelaxError("Monte Carlo parameter values have already been set.")
2340
2341
2342 for object_name in min_names:
2343
2344 sim_object_name = object_name + '_sim'
2345
2346
2347 if hasattr(cdp, sim_object_name):
2348 raise RelaxError("Monte Carlo parameter values have already been set.")
2349
2350
2351 if model_type != 'diff':
2352 for spin in spin_loop():
2353
2354 if not spin.select:
2355 continue
2356
2357
2358 for object_name in param_names:
2359
2360 sim_object_name = object_name + '_sim'
2361
2362
2363 if hasattr(spin, sim_object_name):
2364 raise RelaxError("Monte Carlo parameter values have already been set.")
2365
2366
2367
2368
2369
2370
2371 for object_name in min_names:
2372
2373 if not hasattr(cdp, object_name):
2374 continue
2375
2376
2377 sim_object_name = object_name + '_sim'
2378
2379
2380 setattr(cdp, sim_object_name, [])
2381
2382
2383 sim_object = getattr(cdp, sim_object_name)
2384
2385
2386 for j in range(cdp.sim_number):
2387
2388 object = getattr(cdp, object_name)
2389
2390
2391 sim_object.append(deepcopy(object))
2392
2393
2394 if model_type == 'diff' or model_type == 'all':
2395
2396 cdp.diff_tensor.set_sim_num(cdp.sim_number)
2397
2398
2399 for object_name in diff_params:
2400 for j in range(cdp.sim_number):
2401 cdp.diff_tensor.set(param=object_name, value=deepcopy(getattr(cdp.diff_tensor, object_name)), category='sim', sim_index=j)
2402
2403
2404 if model_type != 'diff':
2405 for spin in spin_loop():
2406
2407 if not spin.select:
2408 continue
2409
2410
2411 for object_name in param_names:
2412
2413 sim_object_name = object_name + '_sim'
2414
2415
2416 setattr(spin, sim_object_name, [])
2417
2418
2419 sim_object = getattr(spin, sim_object_name)
2420
2421
2422 for j in range(cdp.sim_number):
2423
2424 sim_object.append(deepcopy(getattr(spin, object_name)))
2425
2426
2427 for object_name in min_names:
2428
2429 sim_object_name = object_name + '_sim'
2430
2431
2432 setattr(spin, sim_object_name, [])
2433
2434
2435 sim_object = getattr(spin, sim_object_name)
2436
2437
2438 for j in range(cdp.sim_number):
2439
2440 sim_object.append(deepcopy(getattr(spin, object_name)))
2441
2442
2443 - def sim_return_chi2(self, model_info, index=None):
2444 """Return the simulation chi-squared values.
2445
2446 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2447 @type model_info: int
2448 @keyword index: The optional simulation index.
2449 @type index: int
2450 @return: The list of simulation chi-squared values. If the index is supplied, only a single value will be returned.
2451 @rtype: list of float or float
2452 """
2453
2454
2455 model_type = self._determine_model_type()
2456
2457
2458 if model_type == 'all' or model_type == 'diff':
2459 return cdp.chi2_sim
2460
2461
2462 else:
2463
2464 spin = return_spin_from_index(model_info)
2465
2466
2467 return spin.chi2_sim
2468
2469
2470 - def sim_return_param(self, model_info, index):
2471 """Return the array of simulation parameter values.
2472
2473 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2474 @type model_info: int
2475 @param index: The index of the parameter to return the array of values for.
2476 @type index: int
2477 @return: The array of simulation parameter values.
2478 @rtype: list of float
2479 """
2480
2481
2482 inc = 0
2483
2484
2485 model_type = self._determine_model_type()
2486
2487
2488 param_names = self.data_names(set='params', scope='spin')
2489
2490
2491
2492
2493
2494 if model_type == 'diff' or model_type == 'all':
2495
2496 if cdp.diff_tensor.type == 'sphere':
2497
2498 if index == 0:
2499 return cdp.diff_tensor.tm_sim
2500
2501
2502 inc = inc + 1
2503
2504
2505 elif cdp.diff_tensor.type == 'spheroid':
2506
2507 if index == 0:
2508 return cdp.diff_tensor.tm_sim
2509 elif index == 1:
2510 return cdp.diff_tensor.Da_sim
2511 elif index == 2:
2512 return cdp.diff_tensor.theta_sim
2513 elif index == 3:
2514 return cdp.diff_tensor.phi_sim
2515
2516
2517 inc = inc + 4
2518
2519
2520 elif cdp.diff_tensor.type == 'ellipsoid':
2521
2522 if index == 0:
2523 return cdp.diff_tensor.tm_sim
2524 elif index == 1:
2525 return cdp.diff_tensor.Da_sim
2526 elif index == 2:
2527 return cdp.diff_tensor.Dr_sim
2528 elif index == 3:
2529 return cdp.diff_tensor.alpha_sim
2530 elif index == 4:
2531 return cdp.diff_tensor.beta_sim
2532 elif index == 5:
2533 return cdp.diff_tensor.gamma_sim
2534
2535
2536 inc = inc + 6
2537
2538
2539
2540
2541
2542 if model_type == 'all':
2543
2544 for spin in spin_loop():
2545
2546 if not spin.select:
2547 continue
2548
2549
2550 for param in param_names:
2551
2552 if index == inc:
2553 return getattr(spin, param + "_sim")
2554
2555
2556 inc = inc + 1
2557
2558
2559
2560
2561
2562 if model_type == 'mf' or model_type == 'local_tm':
2563
2564 spin = return_spin_from_index(model_info)
2565
2566
2567 if not spin.select:
2568 return
2569
2570
2571 for param in param_names:
2572
2573 if index == inc:
2574 return getattr(spin, param + "_sim")
2575
2576
2577 inc = inc + 1
2578
2579
2580 - def sim_return_selected(self, model_info):
2581 """Return the array of selected simulation flags for the spin.
2582
2583 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2584 @type model_info: int
2585 @return: The array of selected simulation flags.
2586 @rtype: list of int
2587 """
2588
2589
2590 model_type = self._determine_model_type()
2591
2592
2593 if model_type == 'all' or model_type == 'diff':
2594 return cdp.select_sim
2595
2596
2597 else:
2598
2599 spin = return_spin_from_index(model_info)
2600
2601
2602 if not spin.select:
2603 return
2604
2605
2606 return spin.select_sim
2607
2608
2609 - def skip_function(self, model_info):
2610 """Skip certain data.
2611
2612 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices).
2613 @type model_info: int
2614 @return: True if the data should be skipped, False otherwise.
2615 @rtype: bool
2616 """
2617
2618
2619 model_type = self._determine_model_type()
2620
2621
2622 if (model_type == 'mf' or model_type == 'local_tm') and not return_spin_from_index(model_info).select:
2623 return True
2624
2625
2626 return False
2627