1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23   
 24   
 25  """Module containing the base class for the automatic R1 and R2 analysis frames.""" 
 26   
 27   
 28  from os import sep 
 29  from string import lower 
 30  import sys 
 31  import wx 
 32   
 33   
 34  from auto_analyses.relax_fit import Relax_fit 
 35  from data import Relax_data_store; ds = Relax_data_store() 
 36  from generic_fns.mol_res_spin import are_spins_named, exists_mol_res_spin_data 
 37  from generic_fns.pipes import has_bundle, has_pipe 
 38  from status import Status; status = Status() 
 39   
 40   
 41  from gui.analyses.base import Base_analysis, Spectral_error_type_page 
 42  from gui.analyses.elements import Spin_ctrl, Text_ctrl 
 43  from gui.analyses.execute import Execute 
 44  from gui.base_classes import Container 
 45  from gui.components.spectrum import Spectra_list 
 46  from gui.filedialog import RelaxDirDialog 
 47  from gui.message import error_message, Missing_data, Question 
 48  from gui.misc import protected_exec 
 49  from gui import paths 
 50  from gui.string_conv import gui_to_int, gui_to_str, int_to_gui, str_to_gui 
 51  from gui.uf_objects import Uf_storage; uf_store = Uf_storage() 
 52  from gui.wizard import Wiz_window 
 53   
 54   
 55   
 57      """The base class for the R1 and R2 frames.""" 
 58   
 59       
 60      analysis_type = None 
 61      bitmap = None 
 62      label = None 
 63   
 64 -    def __init__(self, parent, id=-1, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=524288, name='scrolledpanel', gui=None, analysis_name=None, pipe_name=None, pipe_bundle=None, data_index=None): 
  65          """Build the automatic R1 and R2 analysis GUI frame elements. 
 66   
 67          @param parent:          The parent wx element. 
 68          @type parent:           wx object 
 69          @keyword id:            The unique ID number. 
 70          @type id:               int 
 71          @keyword pos:           The position. 
 72          @type pos:              wx.Size object 
 73          @keyword size:          The size. 
 74          @type size:             wx.Size object 
 75          @keyword style:         The style. 
 76          @type style:            int 
 77          @keyword name:          The name for the panel. 
 78          @type name:             unicode 
 79          @keyword gui:           The main GUI class. 
 80          @type gui:              gui.relax_gui.Main instance 
 81          @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook). 
 82          @type analysis_name:    str 
 83          @keyword pipe_name:     The name of the data pipe associated with this analysis. 
 84          @type pipe_name:        str 
 85          @keyword pipe_bundle:   The name of the data pipe bundle associated with this analysis. 
 86          @type pipe_bundle:      str 
 87          @keyword data_index:    The index of the analysis in the relax data store (set to None if no data currently exists). 
 88          @type data_index:       None or int 
 89          """ 
 90   
 91           
 92          self.gui = gui 
 93   
 94           
 95          self.init_flag = True 
 96   
 97           
 98          if data_index == None: 
 99               
100              if not has_pipe(pipe_name): 
101                  self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='relax_fit', bundle=pipe_bundle) 
102   
103               
104              if not has_bundle(pipe_bundle): 
105                  self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name) 
106   
107               
108              data_index = ds.relax_gui.analyses.add(self.label) 
109   
110               
111              ds.relax_gui.analyses[data_index].analysis_name = analysis_name 
112              ds.relax_gui.analyses[data_index].pipe_name = pipe_name 
113              ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle 
114   
115               
116              ds.relax_gui.analyses[data_index].frq = '' 
117              ds.relax_gui.analyses[data_index].grid_inc = None 
118              ds.relax_gui.analyses[data_index].mc_sim_num = None 
119              ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir 
120   
121           
122          self.data = ds.relax_gui.analyses[data_index] 
123          self.data_index = data_index 
124   
125           
126          self.observer_register() 
127   
128           
129          super(Auto_rx, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name) 
 130   
131   
133          """Activate or deactivate certain elements of the analysis in response to the execution lock.""" 
134   
135           
136          enable = False 
137          if not status.exec_lock.locked(): 
138              enable = True 
139   
140           
141          wx.CallAfter(self.field_nmr_frq.Enable, enable) 
142          wx.CallAfter(self.field_results_dir.Enable, enable) 
143          wx.CallAfter(self.spin_systems.Enable, enable) 
144          wx.CallAfter(self.peak_intensity.Enable, enable) 
145          wx.CallAfter(self.grid_inc.Enable, enable) 
146          wx.CallAfter(self.mc_sim_num.Enable, enable) 
147          wx.CallAfter(self.button_exec_relax.Enable, enable) 
 148   
149   
151          """Assemble the data required for the auto-analysis. 
152   
153          See the docstring for auto_analyses.relax_fit for details.  All data is taken from the relax data store, so data upload from the GUI to there must have been previously performed. 
154   
155          @return:    A container with all the data required for the auto-analysis. 
156          @rtype:     class instance, list of str 
157          """ 
158   
159           
160          data = Container() 
161          missing = [] 
162   
163           
164          data.pipe_name = self.data.pipe_name 
165          data.pipe_bundle = self.data.pipe_bundle 
166   
167           
168          frq = gui_to_str(self.field_nmr_frq.GetValue()) 
169          if frq == None: 
170              missing.append('NMR frequency') 
171   
172           
173          data.file_root = '%s.%s' % (self.analysis_type, frq) 
174   
175           
176          if not exists_mol_res_spin_data(): 
177              missing.append("Sequence data") 
178   
179           
180          if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 3: 
181              missing.append("Spectral data") 
182   
183           
184          data.inc = gui_to_int(self.grid_inc.GetValue()) 
185   
186           
187          data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 
188   
189           
190          data.save_dir = self.data.save_dir 
191   
192           
193          return data, missing 
 194   
195   
197          """Construct the right hand box to pack into the main Rx box. 
198   
199          @return:    The right hand box element containing all Rx GUI elements (excluding the bitmap) to pack into the main Rx box. 
200          @rtype:     wx.BoxSizer instance 
201          """ 
202   
203           
204          box = wx.BoxSizer(wx.VERTICAL) 
205   
206           
207          self.add_title(box, "Setup for %s relaxation analysis" % self.label) 
208   
209           
210          Text_ctrl(box, self, text="The data pipe bundle:", default=self.data.pipe_bundle, tooltip="This is the data pipe bundle associated with this analysis.", editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
211   
212           
213          self.field_nmr_frq = Text_ctrl(box, self, text="NMR frequency label [MHz]", default=self.data.frq, tooltip="This label is added to the output files.  For example if the label is '600', the %s values will be located in the file '%s.600.out'." % (self.label, lower(self.label)), width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
214   
215           
216          self.field_results_dir = Text_ctrl(box, self, text="Results directory", icon=paths.icon_16x16.open_folder, default=self.data.save_dir, fn=self.results_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
217   
218           
219          self.add_spin_systems(box, self) 
220   
221           
222          box.AddSpacer(20) 
223          self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard) 
224          box.AddSpacer(10) 
225   
226           
227          self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=21, min=1, max=100, tooltip="This is the number of increments per dimension of the grid search performed prior to numerical optimisation.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
228          self.mc_sim_num = Spin_ctrl(box, self, text="Monte Carlo simulation number:", default=500, min=1, max=100000, tooltip="This is the number of Monte Carlo simulations performed for error propagation and analysis.  For best results, at least 500 is recommended.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
229   
230           
231          box.AddSpacer(30) 
232          box.AddStretchSpacer() 
233   
234           
235          self.button_exec_relax = self.add_execute_relax(box, self.execute) 
236   
237           
238          return box 
 239   
240   
242          """Unregister the spin count from the user functions.""" 
243   
244           
245          self.observer_register(remove=True) 
246   
247           
248          self.peak_intensity.delete() 
 249   
250   
291   
292   
313   
314   
316          """Launch the Rx peak loading wizard. 
317   
318          @param event:   The wx event. 
319          @type event:    wx event 
320          """ 
321   
322           
323          wx.BeginBusyCursor() 
324   
325           
326          self.wizard = Wiz_window(parent=self.gui, size_x=1000, size_y=750, title="Set up the %s peak intensities" % self.label) 
327          self.page_indices = {} 
328   
329           
330          if not are_spins_named(): 
331               
332              msg = "No spins have been named.  Please use the spin.name user function first, otherwise it is unlikely that any data will be loaded from the peak intensity file.\n\nThis message can be ignored if the generic file format is used and spin names have not been specified.  Would you like to name the spins already loaded into the relax data store?" 
333   
334               
335              if status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES: 
336                  page = uf_store['spin.name'].create_page(self.wizard, sync=True) 
337                  self.page_indices['read'] = self.wizard.add_page(page, proceed_on_error=False) 
338   
339   
340           
341          self.page_intensity = uf_store['spectrum.read_intensities'].create_page(self.wizard, sync=True) 
342          self.page_indices['read'] = self.wizard.add_page(self.page_intensity, skip_button=True, proceed_on_error=False) 
343   
344           
345          self.page_error_type = Spectral_error_type_page(parent=self.wizard, height_desc=520) 
346          self.page_indices['err_type'] = self.wizard.add_page(self.page_error_type, apply_button=False) 
347          self.wizard.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type) 
348   
349           
350          page = uf_store['spectrum.replicated'].create_page(self.wizard, sync=True) 
351          self.page_indices['repl'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
352          self.wizard.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl) 
353          page.on_init = self.wizard_update_repl 
354   
355           
356          page = uf_store['spectrum.baseplane_rmsd'].create_page(self.wizard, sync=True) 
357          self.page_indices['rmsd'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
358          self.wizard.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd) 
359          page.on_init = self.wizard_update_rmsd 
360   
361           
362          page = uf_store['spectrum.integration_points'].create_page(self.wizard, sync=True) 
363          self.page_indices['pts'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
364          page.on_init = self.wizard_update_pts 
365   
366           
367          page = uf_store['relax_fit.relax_time'].create_page(self.wizard, sync=True) 
368          self.page_indices['relax_time'] = self.wizard.add_page(page, skip_button=False, proceed_on_error=False) 
369          page.on_init = self.wizard_update_relax_time 
370   
371           
372          if wx.IsBusy(): 
373              wx.EndBusyCursor() 
374   
375           
376          self.wizard.run() 
 377   
378   
380          """The results directory selection. 
381   
382          @param event:   The wx event. 
383          @type event:    wx event 
384          """ 
385   
386           
387          dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue()) 
388   
389           
390          if status.show_gui and dialog.ShowModal() != wx.ID_OK: 
391               
392              return 
393   
394           
395          path = gui_to_str(dialog.get_path()) 
396          if not path: 
397              return 
398   
399           
400          self.data.save_dir = path 
401   
402           
403          self.field_results_dir.SetValue(str_to_gui(path)) 
 404   
405   
407          """Synchronise the analysis frame and the relax data store, both ways. 
408   
409          This method allows the frame information to be uploaded into the relax data store, or for the information in the relax data store to be downloaded by the frame. 
410   
411          @keyword upload:    A flag which if True will cause the frame to send data to the relax data store.  If False, data will be downloaded from the relax data store to update the frame. 
412          @type upload:       bool 
413          """ 
414   
415           
416          if upload: 
417              self.data.frq = gui_to_str(self.field_nmr_frq.GetValue()) 
418          else: 
419              self.field_nmr_frq.SetValue(str_to_gui(self.data.frq)) 
420   
421           
422          if upload: 
423              self.data.grid_inc = gui_to_int(self.grid_inc.GetValue()) 
424          elif hasattr(self.data, 'grid_inc'): 
425              self.grid_inc.SetValue(int(self.data.grid_inc)) 
426   
427           
428          if upload: 
429              self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 
430          elif hasattr(self.data, 'mc_sim_num'): 
431              self.mc_sim_num.SetValue(int(self.data.mc_sim_num)) 
432   
433           
434          if upload: 
435              self.data.save_dir = gui_to_str(self.field_results_dir.GetValue()) 
436          else: 
437              self.field_results_dir.SetValue(str_to_gui(self.data.save_dir)) 
 438   
439   
441          """Set the page after the error type choice. 
442   
443          @return:    The index of the next page, which is the current page index plus one. 
444          @rtype:     int 
445          """ 
446   
447           
448          if self.page_error_type.selection == 'rmsd': 
449              return self.page_indices['rmsd'] 
450   
451           
452          elif self.page_error_type.selection == 'repl': 
453              return self.page_indices['repl'] 
 454   
455   
457          """Set the page that comes after the spectrum.replicated page. 
458   
459          @return:    The index of the next page. 
460          @rtype:     int 
461          """ 
462   
463           
464          int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 
465          if int_method != 'height': 
466              return self.page_indices['pts'] 
467   
468           
469          else: 
470              return self.page_indices['relax_time'] 
 471   
472   
474          """Set the page that comes after the spectrum.baseplane_rmsd page. 
475   
476          @return:    The index of the next page. 
477          @rtype:     int 
478          """ 
479   
480           
481          int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 
482          if int_method != 'height': 
483              return self.page_indices['pts'] 
484   
485           
486          else: 
487              return self.page_indices['relax_time'] 
 488   
489   
491          """Update the spectrum.replicated page based on previous data.""" 
492   
493           
494          page = self.wizard.get_page(self.page_indices['read']) 
495   
496           
497          id = page.uf_args['spectrum_id'].GetValue() 
498   
499           
500          page = self.wizard.get_page(self.page_indices['pts']) 
501          page.uf_args['spectrum_id'].SetValue(id) 
 502   
503   
505          """Update the spectrum.replicated page based on previous data.""" 
506   
507           
508          page = self.wizard.get_page(self.page_indices['read']) 
509   
510           
511          id = page.uf_args['spectrum_id'].GetValue() 
512   
513           
514          page = self.wizard.get_page(self.page_indices['repl']) 
515          page.uf_args['spectrum_ids'].SetValue(value=id, index=0) 
 516   
517   
519          """Update the spectrum.baseplane_rmsd page based on previous data.""" 
520   
521           
522          page = self.wizard.get_page(self.page_indices['read']) 
523   
524           
525          id = page.uf_args['spectrum_id'].GetValue() 
526   
527           
528          page = self.wizard.get_page(self.page_indices['rmsd']) 
529          page.uf_args['spectrum_id'].SetValue(id) 
 530   
531   
533          """Update the relax_fit.relax_time page based on previous data.""" 
534   
535           
536          page = self.wizard.get_page(self.page_indices['read']) 
537   
538           
539          id = page.uf_args['spectrum_id'].GetValue() 
540   
541           
542          page = self.wizard.get_page(self.page_indices['relax_time']) 
543          page.uf_args['spectrum_id'].SetValue(id) 
  544   
545   
546   
548      """The Rx analysis execution object.""" 
549   
 558