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