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