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 NOE analysis frames.""" 
 26   
 27   
 28  from os import sep 
 29  import sys 
 30  import wx 
 31   
 32   
 33  from auto_analyses.noe import NOE_calc 
 34  from data import Relax_data_store; ds = Relax_data_store() 
 35  from generic_fns.mol_res_spin import are_spins_named, exists_mol_res_spin_data 
 36  from generic_fns.pipes import has_pipe 
 37  from status import Status; status = Status() 
 38   
 39   
 40  from gui.analyses.base import Base_analysis, Spectral_error_type_page 
 41  from gui.analyses.elements import Text_ctrl 
 42  from gui.analyses.execute import Execute 
 43  from gui.analyses.results_analysis import color_code_noe 
 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 gui_to_str, protected_exec, str_to_gui 
 49  from gui import paths 
 50  from gui.user_functions.noe import Spectrum_type_page 
 51  from gui.user_functions.spectrum import Baseplane_rmsd_page, Integration_points_page, Read_intensities_page, Replicated_page 
 52  from gui.user_functions.spin import Name_page 
 53  from gui.wizard import Wiz_window 
 54   
 55   
 56   
 58      """The base class for the noe frames.""" 
 59   
 60       
 61      analysis_type = None 
 62      bitmap = [paths.ANALYSIS_IMAGE_PATH+"noe_200x200.png", 
 63                paths.IMAGE_PATH+'noe.png'] 
 64      label = None 
 65   
 66 -    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, data_index=None): 
  67          """Build the automatic NOE analysis GUI frame elements. 
 68   
 69          @param parent:          The parent wx element. 
 70          @type parent:           wx object 
 71          @keyword id:            The unique ID number. 
 72          @type id:               int 
 73          @keyword pos:           The position. 
 74          @type pos:              wx.Size object 
 75          @keyword size:          The size. 
 76          @type size:             wx.Size object 
 77          @keyword style:         The style. 
 78          @type style:            int 
 79          @keyword name:          The name for the panel. 
 80          @type name:             unicode 
 81          @keyword gui:           The main GUI class. 
 82          @type gui:              gui.relax_gui.Main instance 
 83          @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook). 
 84          @type analysis_name:    str 
 85          @keyword pipe_name:     The name of the data pipe associated with this analysis. 
 86          @type pipe_name:        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, 'noe') 
102   
103               
104              data_index = ds.relax_gui.analyses.add('NOE') 
105   
106               
107              ds.relax_gui.analyses[data_index].analysis_name = analysis_name 
108              ds.relax_gui.analyses[data_index].pipe_name = pipe_name 
109   
110               
111              ds.relax_gui.analyses[data_index].frq = '' 
112              ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir 
113   
114           
115          self.data = ds.relax_gui.analyses[data_index] 
116          self.data_index = data_index 
117   
118           
119          self.observer_register() 
120   
121           
122          super(Auto_noe, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name) 
 123   
124   
126          """Activate or deactivate certain elements of the analysis in response to the execution lock.""" 
127   
128           
129          enable = False 
130          if not status.exec_lock.locked(): 
131              enable = True 
132   
133           
134          wx.CallAfter(self.field_nmr_frq.Enable, enable) 
135          wx.CallAfter(self.field_results_dir.Enable, enable) 
136          wx.CallAfter(self.spin_systems.Enable, enable) 
137          wx.CallAfter(self.peak_intensity.Enable, enable) 
138          wx.CallAfter(self.button_exec_relax.Enable, enable) 
 139   
140   
142          """Assemble the data required for the Auto_noe class. 
143   
144          @return:    A container with all the data required for the auto-analysis. 
145          @rtype:     class instance, list of str 
146          """ 
147   
148           
149          data = Container() 
150          missing = [] 
151   
152           
153          data.pipe_name = self.data.pipe_name 
154   
155           
156          frq = gui_to_str(self.field_nmr_frq.GetValue()) 
157          if frq == None: 
158              missing.append('NMR frequency') 
159   
160           
161          data.file_root = 'noe.%s' % frq 
162   
163           
164          data.save_dir = self.data.save_dir 
165   
166           
167          if not exists_mol_res_spin_data(): 
168              missing.append("Sequence data") 
169   
170           
171          if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 2: 
172              missing.append("Spectral data") 
173   
174           
175          return data, missing 
 176   
177   
179          """Construct the right hand box to pack into the main NOE box. 
180   
181          @return:    The right hand box element containing all NOE GUI elements (excluding the bitmap) to pack into the main Rx box. 
182          @rtype:     wx.BoxSizer instance 
183          """ 
184   
185           
186          box = wx.BoxSizer(wx.VERTICAL) 
187   
188           
189          self.add_title(box, "Setup for steady-state NOE analysis") 
190   
191           
192          Text_ctrl(box, self, text="The data pipe:", default=self.data.pipe_name, tooltip="This is the data pipe associated with this analysis.", editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
193   
194           
195          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 NOE values will be located in the file 'noe.600.out'.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 
196   
197           
198          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) 
199   
200           
201          self.add_spin_systems(box, self) 
202   
203           
204          box.AddSpacer(40) 
205          self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard) 
206   
207           
208          box.AddSpacer(30) 
209          box.AddStretchSpacer() 
210   
211           
212          self.button_exec_relax = self.add_execute_relax(box, self.execute) 
213   
214           
215          return box 
 216   
217   
219          """Unregister the spin count from the user functions.""" 
220   
221           
222          self.observer_register(remove=True) 
223   
224           
225          self.peak_intensity.delete() 
 226   
227   
268   
269   
290   
291   
293          """Launch the NOE peak loading wizard. 
294   
295          @param event:   The wx event. 
296          @type event:    wx event 
297          """ 
298   
299           
300          wx.BeginBusyCursor() 
301   
302           
303          self.wizard = Wiz_window(parent=self.gui, size_x=1000, size_y=800, title="Set up the NOE peak intensities") 
304          self.page_indices = {} 
305   
306           
307          if not are_spins_named(): 
308               
309              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?" 
310   
311               
312              if status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES: 
313                  page = Name_page(self.wizard, sync=True) 
314                  self.page_indices['read'] = self.wizard.add_page(page, proceed_on_error=False) 
315   
316   
317           
318          self.page_intensity = Read_intensities_page(self.wizard, sync=True) 
319          self.page_indices['read'] = self.wizard.add_page(self.page_intensity, skip_button=True, proceed_on_error=False) 
320   
321           
322          self.page_error_type = Spectral_error_type_page(self.wizard) 
323          self.page_indices['err_type'] = self.wizard.add_page(self.page_error_type, apply_button=False) 
324          self.wizard.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type) 
325   
326           
327          page = Replicated_page(self.wizard, sync=True) 
328          self.page_indices['repl'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
329          self.wizard.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl) 
330          page.on_display_post = self.wizard_update_repl 
331   
332           
333          page = Baseplane_rmsd_page(self.wizard, sync=True) 
334          self.page_indices['rmsd'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
335          self.wizard.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd) 
336          page.on_display_post = self.wizard_update_rmsd 
337   
338           
339          page = Integration_points_page(self.wizard, sync=True) 
340          self.page_indices['pts'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False) 
341          page.on_display_post = self.wizard_update_pts 
342   
343           
344          page = Spectrum_type_page(self.wizard, sync=True) 
345          self.page_indices['spectrum_type'] = self.wizard.add_page(page, skip_button=False, proceed_on_error=False) 
346          page.on_display_post = self.wizard_update_spectrum_type 
347   
348           
349          if wx.IsBusy(): 
350              wx.EndBusyCursor() 
351   
352           
353          self.wizard.run() 
 354   
355   
357          """The results directory selection. 
358   
359          @param event:   The wx event. 
360          @type event:    wx event 
361          """ 
362   
363           
364          dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue()) 
365   
366           
367          if status.show_gui and dialog.ShowModal() != wx.ID_OK: 
368               
369              return 
370   
371           
372          path = gui_to_str(dialog.get_path()) 
373          if not path: 
374              return 
375   
376           
377          self.data.save_dir = path 
378   
379           
380          self.field_results_dir.SetValue(str_to_gui(path)) 
 381   
382   
384          """Synchronise the noe analysis frame and the relax data store, both ways. 
385   
386          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. 
387   
388          @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. 
389          @type upload:       bool 
390          """ 
391   
392           
393          if upload: 
394              self.data.frq = gui_to_str(self.field_nmr_frq.GetValue()) 
395          else: 
396              self.field_nmr_frq.SetValue(str_to_gui(self.data.frq)) 
397   
398           
399          if upload: 
400              self.data.save_dir = gui_to_str(self.field_results_dir.GetValue()) 
401          else: 
402              self.field_results_dir.SetValue(str_to_gui(self.data.save_dir)) 
 403   
404   
406          """Set the page after the error type choice. 
407   
408          @return:    The index of the next page, which is the current page index plus one. 
409          @rtype:     int 
410          """ 
411   
412           
413          if self.page_error_type.selection == 'rmsd': 
414              return self.page_indices['rmsd'] 
415   
416           
417          elif self.page_error_type.selection == 'repl': 
418              return self.page_indices['repl'] 
 419   
420   
422          """Set the page that comes after the spectrum.replicated page. 
423   
424          @return:    The index of the next page. 
425          @rtype:     int 
426          """ 
427   
428           
429          int_method = gui_to_str(self.page_intensity.int_method.GetValue()) 
430          if int_method != 'height': 
431              return self.page_indices['pts'] 
432   
433           
434          else: 
435              return self.page_indices['spectrum_type'] 
 436   
437   
439          """Set the page that comes after the spectrum.baseplane_rmsd page. 
440   
441          @return:    The index of the next page. 
442          @rtype:     int 
443          """ 
444   
445           
446          int_method = gui_to_str(self.page_intensity.int_method.GetValue()) 
447          if int_method != 'height': 
448              return self.page_indices['pts'] 
449   
450           
451          else: 
452              return self.page_indices['spectrum_type'] 
 453   
454   
456          """Update the spectrum.replicated page based on previous data.""" 
457   
458           
459          page = self.wizard.get_page(self.page_indices['read']) 
460   
461           
462          id = page.spectrum_id.GetValue() 
463   
464           
465          page = self.wizard.get_page(self.page_indices['pts']) 
466          page.spectrum_id.SetStringSelection(str_to_gui(id)) 
 467   
468   
470          """Update the spectrum.replicated page based on previous data.""" 
471   
472           
473          page = self.wizard.get_page(self.page_indices['read']) 
474   
475           
476          id = page.spectrum_id.GetValue() 
477   
478           
479          page = self.wizard.get_page(self.page_indices['repl']) 
480          page.spectrum_id_boxes[0].SetStringSelection(str_to_gui(id)) 
 481   
482   
484          """Update the spectrum.baseplane_rmsd page based on previous data.""" 
485   
486           
487          page = self.wizard.get_page(self.page_indices['read']) 
488   
489           
490          id = page.spectrum_id.GetValue() 
491   
492           
493          page = self.wizard.get_page(self.page_indices['rmsd']) 
494          page.spectrum_id.SetStringSelection(str_to_gui(id)) 
 495   
496   
498          """Update the noe.spectrum_type page based on previous data.""" 
499   
500           
501          page = self.wizard.get_page(self.page_indices['read']) 
502   
503           
504          id = page.spectrum_id.GetValue() 
505   
506           
507          page = self.wizard.get_page(self.page_indices['spectrum_type']) 
508          page.spectrum_id.SetStringSelection(str_to_gui(id)) 
  509   
510   
511   
513      """The NOE analysis execution object.""" 
514   
 533