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