1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """API methods in common between different analysis types."""
25
26
27 from copy import deepcopy
28
29
30 import arg_check
31 from data.mol_res_spin import SpinContainer
32 from generic_fns.mol_res_spin import count_spins, exists_mol_res_spin_data, return_spin, spin_loop
33 from relax_errors import RelaxError, RelaxLenError, RelaxNoSequenceError
34
35
37 """Base class containing API methods common to multiple analysis types."""
38
40 """Generator method for looping over the base data of the specific analysis type (spin system specific).
41
42 This method simply loops over the spins, returning the spin identification string.
43
44 @return: The spin identification string
45 @rtype: str
46 """
47
48
49 for spin, spin_id in spin_loop(return_id=True):
50
51 if not spin.select:
52 continue
53
54
55 yield spin_id
56
57
59 """Return the Monte Carlo relaxation data list for the corresponding spin.
60
61 @param data_id: The spin identification string, as yielded by the base_data_loop() generator method.
62 @type data_id: str
63 """
64
65
66 spin = return_spin(data_id)
67
68
69 data = []
70
71
72 for ri_id in cdp.ri_ids:
73 data.append(spin.ri_data[ri_id])
74
75
76 return data
77
78
80 """Dummy method for initialising data structures.
81
82 This method does nothing!
83
84
85 @param data_cont: The data container.
86 @type data_cont: instance
87 @keyword sim: The unused Monte Carlo simulation flag.
88 @type sim: bool
89 """
90
91
93 """The default spin parameter values.
94
95 @param param: The spin parameter.
96 @type param: str
97 @return: The default value.
98 @rtype: float
99 """
100
101
102 return self.SPIN_PARAMS.get_default(param)
103
104
106 """Dummy method for model elimination.
107
108 This simply returns False to signal that no model elimination is to be performed.
109
110
111 @param name: The parameter name.
112 @type name: str
113 @param value: The parameter value.
114 @type value: float
115 @param model_info: The model index from model_info().
116 @type model_info: int
117 @param args: The elimination constant overrides.
118 @type args: None or tuple of float
119 @keyword sim: The Monte Carlo simulation index.
120 @type sim: int
121 @return: False to prevent model elimination.
122 @rtype: bool
123 """
124
125
126 return False
127
128
130 """Testing if errors exist for the current data pipe (spin system specific).
131
132 @return: The answer to the question of whether errors exist.
133 @rtype: bool
134 """
135
136
137 if hasattr(cdp, 'diff'):
138 for object_name in dir(cdp.diff):
139
140 object_error = object_name + '_err'
141
142
143 if hasattr(cdp.diff, object_error):
144 return True
145
146
147 for spin in spin_loop():
148
149 for object_name in dir(spin):
150
151 object_error = object_name + '_err'
152
153
154 if hasattr(spin, object_error):
155 return True
156
157
158 return False
159
160
162 """Dummy method stating that the parameter is spin specific.
163
164 This method always returns true, hence all parameters will be considered residents of a SpinContainer object unless this method is overwritten.
165
166 @param name: The name of the parameter.
167 @type name: str
168 @return: True
169 @rtype: bool
170 """
171
172
173 return True
174
175
177 """Default generator method for looping over the models, where each spin has a separate model.
178
179 In this case only a single model per spin system is assumed. Hence the yielded data is the spin container object.
180
181
182 @return: The spin container.
183 @rtype: SpinContainer instance
184 """
185
186
187 for spin in spin_loop():
188
189 if not spin.select:
190 continue
191
192
193 yield spin
194
195
197 """Default generator method for looping over a single global (non-spin specific) model.
198
199 The loop will yield a single index, zero, once to indicate a single model.
200
201
202 @return: The global model index of zero.
203 @rtype: int
204 """
205
206
207 yield 0
208
209
211 """Return the number of instances, equal to the number of selected spins.
212
213 @return: The number of instances (equal to the number of spins).
214 @rtype: int
215 """
216
217
218 if not exists_mol_res_spin_data():
219 raise RelaxNoSequenceError
220
221
222 return count_spins()
223
224
226 """Dummy method, normally for deselecting spins with insufficient data for minimisation."""
227
228
230 """Return the spin specific parameter conversion factor.
231
232 @param param: The parameter name.
233 @type param: str
234 @return: The spin specific parameter conversion factor.
235 @rtype: None or float
236 """
237
238
239 return self.SPIN_PARAMS.get_conv_factor(param)
240
241
243 """Method for returning 1.0.
244
245 @param param: The parameter name.
246 @type param: str
247 @return: A conversion factor of 1.0.
248 @rtype: float
249 """
250
251 return 1.0
252
253
255 """Return a description of the spin parameter.
256
257 @param name: The name of the spin specific object.
258 @type name: str
259 @return: The object description, or None.
260 @rtype: str or None
261 """
262
263
264 return self.SPIN_PARAMS.get_desc(name)
265
266
268 """Return a unique identifying string for the global or spin parameter.
269
270 This first returns a global parameter if it exists, followed by a spin parameter, and None if neither exist.
271
272
273 @param param: The parameter name.
274 @type param: str
275 @return: The unique parameter identifying string.
276 @rtype: str
277 """
278
279
280 if self.GLOBAL_PARAMS.contains(param):
281 return param
282
283
284 if self.SPIN_PARAMS.contains(param):
285 return param
286
287
288 return None
289
290
292 """Return a unique identifying string for the global parameter.
293
294 @param param: The parameter name.
295 @type param: str
296 @return: The unique parameter identifying string.
297 @rtype: str
298 """
299
300
301 if not self.GLOBAL_PARAMS.contains(param):
302 return None
303
304
305 return param
306
307
309 """Return a unique identifying string for the spin parameter.
310
311 @param param: The parameter name.
312 @type param: str
313 @return: The unique parameter identifying string.
314 @rtype: str
315 """
316
317
318 if not self.SPIN_PARAMS.contains(param):
319 return None
320
321
322 return param
323
324
326 """Return the Ri data structure for the given spin.
327
328 @param spin: The SpinContainer object.
329 @type spin: SpinContainer instance
330 @return: The array of relaxation data values.
331 @rtype: list of float
332 """
333
334
335 data = []
336 for ri_id in cdp.ri_ids:
337 data.append(spin.ri_data[ri_id])
338
339
340 return data
341
342
344 """Return the Ri error structure for the corresponding spin.
345
346 @param data_id: The data identification information, as yielded by the base_data_loop() generator method.
347 @type data_id: str
348 @return: The array of relaxation data error values.
349 @rtype: list of float
350 """
351
352
353 spin = return_spin(data_id)
354
355
356 error = []
357 for ri_id in cdp.ri_ids:
358 error.append(spin.ri_data_err[ri_id])
359
360
361 return error
362
363
365 """Return the Grace string representing the given spin parameter.
366
367 @param param: The parameter name.
368 @type param: str
369 @return: The unique parameter identifying string.
370 @rtype: str
371 """
372
373
374 return self.SPIN_PARAMS.get_grace_string(param)
375
376
378 """Return a string representing the spin parameter units.
379
380 @param param: The parameter name.
381 @type param: str
382 @return: The string representation of the units.
383 @rtype: None or str
384 """
385
386
387 if not self.SPIN_PARAMS.contains(param):
388 return None
389
390
391 return self.SPIN_PARAMS.get_units(param)
392
393
395 """Return a string representing the global parameter units.
396
397 @param param: The parameter name.
398 @type param: str
399 @return: The string representation of the units.
400 @rtype: None or str
401 """
402
403
404 if not self.GLOBAL_PARAMS.contains(param):
405 return None
406
407
408 return self.GLOBAL_PARAMS.get_units(param)
409
410
412 """Return the value and error corresponding to the parameter 'param'.
413
414 If sim is set to an integer, return the value of the simulation and None. The values are taken from the given SpinContainer object.
415
416
417 @param spin: The SpinContainer object.
418 @type spin: SpinContainer
419 @param param: The name of the parameter to return values for.
420 @type param: str
421 @param sim: The Monte Carlo simulation index.
422 @type sim: None or int
423 @keyword bc: The back-calculated data flag. If True, then the back-calculated data will be returned rather than the actual data.
424 @type bc: bool
425 @return: The value and error corresponding to
426 @rtype: tuple of length 2 of floats or None
427 """
428
429
430 index = None
431
432
433 object_name = self.return_data_name(param)
434
435
436 if object_name:
437 object_error = object_name + '_err'
438 object_sim = object_name + '_sim'
439 object_bc = object_name + '_bc'
440 key = None
441
442
443 else:
444
445 if hasattr(cdp, 'spectrum_ids') and param in cdp.spectrum_ids:
446 object_name = 'intensities'
447 object_error = 'intensity_err'
448 object_sim = 'intensity_sim'
449 object_bc = 'intensity_bc'
450 key = param
451
452
453 else:
454 raise RelaxError("The parameter " + repr(param) + " does not exist.")
455
456
457 value = None
458 error = None
459
460
461 if bc:
462 object_name = object_bc
463
464
465 if sim != None:
466 object_name = object_sim
467
468
469 if hasattr(spin, object_name):
470 value = getattr(spin, object_name)
471
472
473 if hasattr(spin, object_error):
474 error = getattr(spin, object_error)
475
476
477 elif hasattr(cdp, object_name):
478 value = getattr(cdp, object_name)
479
480
481 if hasattr(cdp, object_error):
482 error = getattr(cdp, object_error)
483
484
485 if index != None:
486 value = value[index]
487 if error:
488 error = error[index]
489
490
491 if key:
492 value = value[key]
493 if error:
494 error = error[key]
495
496
497 if sim == None:
498 return value, error
499 else:
500 return value[sim], error
501
502
504 """Set the parameter errors (spin system specific).
505
506 @param model_info: The spin container originating from model_loop().
507 @type model_info: unknown
508 @param index: The index of the parameter to set the errors for.
509 @type index: int
510 @param error: The error value.
511 @type error: float
512 """
513
514
515 if not isinstance(model_info, SpinContainer):
516 raise RelaxError("The model information argument is not a spin container.")
517 spin = model_info
518
519
520 inc = 0
521
522
523 for param in self.data_names(set='params'):
524
525 if index == inc:
526 setattr(spin, param + "_err", error)
527
528
529 inc = inc + 1
530
531
533 """Set the global parameter values in the top layer of the data pipe.
534
535 @keyword param: The parameter name list.
536 @type param: list of str
537 @keyword value: The parameter value list.
538 @type value: list
539 @keyword spin_id: The spin identification string (unused).
540 @type spin_id: None
541 @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.
542 @type force: bool
543 """
544
545
546 arg_check.is_str_list(param, 'parameter name')
547 arg_check.is_list(value, 'parameter value')
548
549
550 for i in range(len(param)):
551
552 obj_name = self.return_data_name(param[i])
553
554
555 if not obj_name:
556 raise RelaxError("The parameter '%s' is not valid for this data pipe type." % param[i])
557
558
559 if not force and hasattr(cdp, obj_name) and getattr(cdp, obj_name) != None:
560 raise RelaxError("The parameter '%s' already exists, set the force flag to True to overwrite." % param[i])
561
562
563 setattr(cdp, obj_name, value[i])
564
565
567 """Set the spin specific parameter values.
568
569 @keyword param: The parameter name list.
570 @type param: list of str
571 @keyword value: The parameter value list.
572 @type value: list
573 @keyword spin_id: The spin identification string, only used for spin specific parameters.
574 @type spin_id: None or str
575 @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.
576 @type force: bool
577 """
578
579
580 arg_check.is_str_list(param, 'parameter name')
581 arg_check.is_list(value, 'parameter value')
582
583
584 for i in range(len(param)):
585
586 if not self.SPIN_PARAMS.contains(param[i]):
587 raise RelaxError("The parameter '%s' is not valid for this data pipe type." % param[i])
588
589
590 for spin in spin_loop(spin_id):
591
592 if not spin.select:
593 continue
594
595
596 setattr(spin, param[i], value[i])
597
598
600 """Set the simulation selection flag (for a single global model).
601
602 @param model_info: The model information originating from model_loop(). This should be zero for the single global model.
603 @type model_info: int
604 @param select_sim: The selection flag for the simulations.
605 @type select_sim: bool
606 """
607
608
609 cdp.select_sim = deepcopy(select_sim)
610
611
613 """Set the simulation selection flag (spin system specific).
614
615 @param model_info: The model information originating from model_loop().
616 @type model_info: unknown
617 @param select_sim: The selection flag for the simulations.
618 @type select_sim: bool
619 """
620
621
622 if not isinstance(model_info, SpinContainer):
623 raise RelaxError("The model information argument is not a spin container.")
624 spin = model_info
625
626
627 spin.select_sim = deepcopy(select_sim)
628
629
631 """Dummy method to do nothing!
632
633 @param param: The name of the parameter which has been changed.
634 @type param: str
635 @param spin: The SpinContainer object.
636 @type spin: SpinContainer
637 """
638
639
641 """Initialise the Monte Carlo parameter values (spin system specific)."""
642
643
644 param_names = self.data_names(set='params')
645
646
647 min_names = self.data_names(set='min')
648
649
650
651
652
653
654 for spin in spin_loop():
655
656 if not spin.select:
657 continue
658
659
660 for object_name in param_names:
661
662 sim_object_name = object_name + '_sim'
663
664
665 if hasattr(spin, sim_object_name):
666 raise RelaxError("Monte Carlo parameter values have already been set.")
667
668
669
670
671
672
673 for spin in spin_loop():
674
675 if not spin.select:
676 continue
677
678
679 for object_name in param_names:
680
681 sim_object_name = object_name + '_sim'
682
683
684 setattr(spin, sim_object_name, [])
685
686
687 sim_object = getattr(spin, sim_object_name)
688
689
690 for j in xrange(cdp.sim_number):
691
692 sim_object.append(deepcopy(getattr(spin, object_name)))
693
694
695 for object_name in min_names:
696
697 sim_object_name = object_name + '_sim'
698
699
700 setattr(spin, sim_object_name, [])
701
702
703 sim_object = getattr(spin, sim_object_name)
704
705
706 for j in xrange(cdp.sim_number):
707
708 sim_object.append(deepcopy(getattr(spin, object_name)))
709
710
712 """Pack the Monte Carlo simulation relaxation data into the corresponding spin container.
713
714 @param data_id: The spin identification string, as yielded by the base_data_loop() generator method.
715 @type data_id: str
716 @param sim_data: The Monte Carlo simulation data.
717 @type sim_data: list of float
718 """
719
720
721 spin = return_spin(data_id)
722
723
724 spin.ri_data_sim = {}
725
726
727 for i in range(len(cdp.ri_ids)):
728
729 ri_id = cdp.ri_ids[i]
730
731
732 spin.ri_data_sim[ri_id] = []
733
734
735 for j in range(cdp.sim_number):
736 spin.ri_data_sim[ri_id].append(sim_data[j][i])
737
738
740 """Return the simulation chi-squared values (spin system specific).
741
742 @param model_info: The model information originating from model_loop().
743 @type model_info: unknown
744 @keyword index: The optional simulation index.
745 @type index: int
746 @return: The list of simulation chi-squared values. If the index is supplied, only a single value will be returned.
747 @rtype: list of float or float
748 """
749
750
751 if not isinstance(model_info, SpinContainer):
752 raise RelaxError("The model information argument is not a spin container.")
753 spin = model_info
754
755
756 if index != None:
757 return spin.chi2_sim[index]
758
759
760 else:
761 return spin.chi2_sim
762
763
765 """Return the array of simulation parameter values (spin system specific).
766
767 @param model_info: The model information originating from model_loop().
768 @type model_info: unknown
769 @param index: The index of the parameter to return the array of values for.
770 @type index: int
771 @return: The array of simulation parameter values.
772 @rtype: list of float
773 """
774
775
776 if not isinstance(model_info, SpinContainer):
777 raise RelaxError("The model information argument is not a spin container.")
778 spin = model_info
779
780
781 inc = 0
782
783
784 for param in self.data_names(set='params'):
785
786 if index == inc:
787 return getattr(spin, param + "_sim")
788
789
790 inc = inc + 1
791
792
794 """Return the array of selected simulation flags for the global model.
795
796 @param model_info: The model information originating from model_loop(). This should be zero for the single global model.
797 @type model_info: int
798 @return: The array of selected simulation flags.
799 @rtype: list of int
800 """
801
802
803 return cdp.select_sim
804
805
807 """Return the array of selected simulation flags (spin system specific).
808
809 @param model_info: The model information originating from model_loop().
810 @type model_info: unknown
811 @return: The array of selected simulation flags.
812 @rtype: list of int
813 """
814
815
816 if not isinstance(model_info, SpinContainer):
817 raise RelaxError("The model information argument is not a spin container.")
818 spin = model_info
819
820
821 return spin.select_sim
822
823
825 """Test that the grid search options are reasonable.
826
827 @param lower: The lower bounds of the grid search which must be equal to the number of parameters in the model.
828 @type lower: array of numbers
829 @param upper: The upper bounds of the grid search which must be equal to the number of parameters in the model.
830 @type upper: array of numbers
831 @param inc: The increments for each dimension of the space for the grid search. The number of elements in the array must equal to the number of parameters in the model.
832 @type inc: array of int
833 @param n: The number of parameters in the model.
834 @type n: int
835 """
836
837
838 if lower != None:
839 if len(lower) != n:
840 raise RelaxLenError('lower bounds', n)
841
842
843 if upper != None:
844 if len(upper) != n:
845 raise RelaxLenError('upper bounds', n)
846
847
848 if isinstance(inc, list):
849 if len(inc) != n:
850 raise RelaxLenError('increment', n)
851