1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23  """Module for the analysis selection wizard.""" 
 24   
 25   
 26  from os import sep 
 27  from time import asctime, localtime 
 28  import wx 
 29  from wx.lib import buttons 
 30   
 31   
 32  from graphics import ANALYSIS_IMAGE_PATH, IMAGE_PATH, WIZARD_IMAGE_PATH 
 33  from gui.input_elements.value import Value 
 34  from gui.misc import bitmap_setup 
 35  from gui.string_conv import gui_to_str, str_to_gui 
 36  from gui.uf_objects import Uf_storage; uf_store = Uf_storage() 
 37  from gui.wizards.wiz_objects import Wiz_page, Wiz_window 
 38  from lib.text.gui import r1, r2 
 39   
 40   
 42      """The analysis selection wizard.""" 
 43   
 45          """Run through the analysis selection wizard, returning the results. 
 46   
 47          @return:    The analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list. 
 48          @rtype:     tuple of str 
 49          """ 
 50   
 51           
 52          wx.Yield() 
 53          wx.BeginBusyCursor() 
 54   
 55           
 56          self.wizard = Wiz_window(size_x=1000, size_y=700, title='Analysis selection wizard') 
 57   
 58           
 59          self.wizard.TEXT_FINISH = " Start" 
 60   
 61           
 62          self.new_page = New_analysis_page(self.wizard) 
 63          self.wizard.add_page(self.new_page, apply_button=False) 
 64          self.wizard.set_seq_next_fn(0, self.wizard_page_after_analysis) 
 65   
 66           
 67          self.pipe_page = Data_pipe_page(self.wizard, height_desc=400) 
 68          self.wizard.add_page(self.pipe_page, apply_button=False) 
 69   
 70           
 71          if wx.IsBusy(): 
 72              wx.EndBusyCursor() 
 73   
 74           
 75          setup = self.wizard.run(modal=True) 
 76          if setup != wx.ID_OK: 
 77              return 
 78   
 79           
 80          return self.get_data() 
  81   
 82   
 84          """Assemble and return the analysis type, analysis name, and pipe name. 
 85   
 86          @return:    The analysis type, analysis name, data pipe name, data pipe bundle name, and list of user function on_execute methods. 
 87          @rtype:     str, str, str, str, list of methods 
 88          """ 
 89   
 90           
 91          analysis_type = gui_to_str(self.wizard.analysis_type) 
 92          analysis_name = gui_to_str(self.new_page.analysis_name.GetValue()) 
 93          pipe_name = gui_to_str(self.pipe_page.pipe_name.GetValue()) 
 94          pipe_bundle = gui_to_str(self.pipe_page.pipe_bundle.GetValue()) 
 95   
 96           
 97          uf_exec = [] 
 98   
 99           
100          return analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec 
 101   
102   
104          """Set the page after the data pipe setup. 
105   
106          @return:    The index of the next page, which is the current page index plus one. 
107          @rtype:     int 
108          """ 
109   
110           
111          analysis_name = gui_to_str(self.new_page.analysis_name.GetValue()) 
112   
113           
114          return 1 
  115   
116   
117   
118 -class Data_pipe_page(Wiz_page): 
 119      """The panel for setting the data pipe name.""" 
120   
121       
122      image_path = WIZARD_IMAGE_PATH + 'pipe.png' 
123      main_text = "Select the name of the data pipe used at the start of the analysis and the name of the data pipe bundle to be associated with this analysis.  All data in relax is kept within a special structure known as the relax data store.  This store is composed of multiple data pipes, each being associated with a specific analysis type.  Data pipe bundles are simple groupings of the pipes within the data store and each analysis tab is coupled to a specific bundle.\n\nSimple analyses such as the steady-state NOE and the %s and %s curve-fitting will be located within a single data pipe.  More complex analyses such as the automated model-free analysis will be spread across multiple data pipes, internally created by forking the original data pipe which holds the input data, all grouped together within a single bundle.\n\nThe initialisation of a new analysis will call the pipe.create user function with the pipe name and pipe bundle as given below." % (r1, r2) 
124      title = 'Data pipe set up' 
125   
126 -    def add_contents(self, sizer): 
 127          """Add the specific GUI elements (dummy method). 
128   
129          @param sizer:   A sizer object. 
130          @type sizer:    wx.Sizer instance 
131          """ 
132   
133           
134          self.pipe_name = Value(name='pipe_name', parent=self, value_type='str', sizer=sizer, desc="The starting data pipe for the analysis:", divider=self._div_left, height_element=self.height_element) 
135   
136           
137          self.pipe_bundle = Value(name='pipe_bundle', parent=self, value_type='str', sizer=sizer, desc="The data pipe bundle:", divider=self._div_left, height_element=self.height_element) 
138   
139           
140          sizer.AddStretchSpacer(3) 
 141   
142   
143 -    def on_display(self): 
 144          """Update the pipe name.""" 
145   
146           
147          name = "%s (%s)" % (self.parent.analysis_type, asctime(localtime())) 
148   
149           
150          self.pipe_name.SetValue(str_to_gui("origin - %s" % name)) 
151          self.pipe_bundle.SetValue(str_to_gui(name)) 
  152   
153   
154   
188   
189   
190   
191 -class New_analysis_page(Wiz_page): 
 192      """The panel for selection of the new analysis.""" 
193   
194       
195      image_path = IMAGE_PATH + "relax.gif" 
196      main_text = "A number of automatic analyses to be preformed using relax in GUI mode.  Although not as flexible or powerful as the prompt/scripting modes, this provides a quick and easy setup and execution for a number of analysis types.   These currently include the calculation of the steady-state NOE, the exponential curve-fitting for the %s and %s relaxation rates, and for a full and automatic model-free analysis using the d'Auvergne and Gooley, 2008b protocol.  All analyses perform error propagation using the gold standard Monte Calro simulations.  Please select from one of the following analysis types:" % (r1, r2) 
197      title = "Start a new analysis" 
198   
199 -    def add_artwork(self, sizer): 
 200          """Add the artwork to the dialog. 
201   
202          @param sizer:   A sizer object. 
203          @type sizer:    wx.Sizer instance 
204          """ 
205   
206           
207          sizer2 = wx.BoxSizer(wx.VERTICAL) 
208   
209           
210          sizer2.AddSpacer(30) 
211   
212           
213          self.image = wx.StaticBitmap(self, -1, bitmap_setup(self.image_path)) 
214          sizer2.Add(self.image, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 0) 
215   
216           
217          sizer.Add(sizer2) 
218   
219           
220          sizer.AddSpacer(self.art_spacing) 
 221   
222   
224          """The widget of analysis buttons. 
225   
226          @param box:     A sizer object. 
227          @type box:      wx.BoxSizer instance 
228          """ 
229   
230           
231          size = (170, 170) 
232   
233           
234          self._select_flag = False 
235   
236           
237          sizer1 = wx.BoxSizer(wx.HORIZONTAL) 
238          sizer2 = wx.BoxSizer(wx.HORIZONTAL) 
239   
240           
241          self.button_ids = {'noe': wx.NewId(), 
242                             'r1': wx.NewId(), 
243                             'r2': wx.NewId(), 
244                             'mf': wx.NewId(), 
245                             'relax_disp': wx.NewId(), 
246                             'consist_test': wx.NewId(), 
247                             'custom': wx.NewId(), 
248                             'reserved': wx.NewId()} 
249   
250           
251          self.button_noe = self.create_button(id=self.button_ids['noe'], box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"noe_150x150.png", tooltip="Steady-state NOE analysis", fn=self.select_noe) 
252   
253           
254          self.button_r1 = self.create_button(id=self.button_ids['r1'], box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"r1_150x150.png", tooltip="%s relaxation curve-fitting analysis" % r1, fn=self.select_r1) 
255   
256           
257          self.button_r2 = self.create_button(id=self.button_ids['r2'], box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"r2_150x150.png", tooltip="%s relaxation curve-fitting analysis" % r2, fn=self.select_r2) 
258   
259           
260          self.button_mf = self.create_button(id=self.button_ids['mf'], box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"model_free"+sep+"model_free_150x150.png", tooltip="Model-free analysis", fn=self.select_mf) 
261   
262           
263          self.button_disp = self.create_button(id=self.button_ids['relax_disp'], box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"relax_disp_150x150.png", tooltip="Relaxation dispersion analysis", fn=self.select_disp) 
264   
265           
266          self.button_consist_test = self.create_button(id=self.button_ids['consist_test'], box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"consistency_testing_150x70.png", tooltip="Relaxation data consistency testing (disabled)", fn=self.select_consist_test, disabled=True) 
267   
268           
269          self.button_custom = self.create_button(id=self.button_ids['custom'], box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"custom_150x150.png", tooltip="Custom analysis (disabled)", fn=self.select_custom, disabled=True) 
270   
271           
272          self.button_reserved = self.create_button(id=self.button_ids['reserved'], box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"blank_150x150.png", tooltip=None, fn=None, disabled=True) 
273   
274           
275          box.Add(sizer1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0) 
276          box.Add(sizer2, 0, wx.ALIGN_CENTER_HORIZONTAL, 0) 
 277   
278   
279 -    def add_contents(self, sizer): 
 280          """Add the specific GUI elements (dummy method). 
281   
282          @param sizer:   A sizer object. 
283          @type sizer:    wx.Sizer instance 
284          """ 
285   
286           
287          self.add_buttons(sizer) 
288   
289           
290          sizer.AddStretchSpacer(2) 
291   
292           
293          self.analysis_name = Value(name='analysis_name', parent=self, value_type='str', sizer=sizer, desc="The name of the new analysis:", tooltip='The name of the analysis can be changed to any text.', divider=self._div_left, height_element=self.height_element) 
 294   
295   
296 -    def create_button(self, id=-1, box=None, size=None, bmp=None, text='', tooltip='', fn=None, disabled=False): 
 297          """Create a button for the new analysis selector panel. 
298   
299          @keyword id:        The unique ID number. 
300          @type id:           int 
301          @keyword box:       The box sizer to place the button into. 
302          @type box:          wx.BoxSizer instance 
303          @keyword size:      The size of the button. 
304          @type size:         tuple of int 
305          @keyword bmp:       The full path of the bitmap image to use for the button. 
306          @type bmp:          str 
307          @keyword text:      The text for the button. 
308          @type text:         str 
309          @keyword tooltip:   The button tooltip text. 
310          @type tooltip:      str or None 
311          @keyword fn:        The function to bind the button click to. 
312          @type fn:           method 
313          @return:            The button. 
314          @rtype:             wx.lib.buttons.ThemedGenBitmapTextToggleButton instance 
315          """ 
316   
317           
318          if bmp: 
319              image = wx.Bitmap(bmp, wx.BITMAP_TYPE_ANY) 
320              button = New_analysis_button(self, id, image) 
321          else: 
322              button = New_analysis_button(self, id) 
323   
324           
325          if tooltip != None: 
326              button.SetToolTipString(tooltip) 
327   
328           
329          button.SetMinSize(size) 
330   
331           
332          box.Add(button) 
333   
334           
335          if fn != None: 
336              self.Bind(wx.EVT_BUTTON, fn, button) 
337   
338           
339          if disabled: 
340              button.Disable() 
341   
342           
343          return button 
 344   
345   
346 -    def on_display(self): 
 347          """Disable the next button until an analysis is selected.""" 
348   
349           
350          self.parent.block_next(not self._select_flag) 
 351   
352   
353 -    def select_consist_test(self, event): 
 354          """NOE analysis selection. 
355   
356          @param event:   The wx event. 
357          @type event:    wx event 
358          """ 
359   
360           
361          self.toggle(self.button_consist_test) 
362   
363           
364          self.parent.analysis_type = 'consistency test' 
 365   
366   
367 -    def select_custom(self, event): 
 368          """NOE analysis selection. 
369   
370          @param event:   The wx event. 
371          @type event:    wx event 
372          """ 
373   
374           
375          self.toggle(self.button_custom) 
376   
377           
378          self.parent.analysis_type = 'custom' 
 379   
380   
381 -    def select_disp(self, event): 
 382          """Relaxation dispersion analysis selection. 
383   
384          @param event:   The wx event. 
385          @type event:    wx event 
386          """ 
387   
388           
389          self.toggle(self.button_disp) 
390   
391           
392          self.analysis_name.SetValue(str_to_gui('Relaxation dispersion')) 
393   
394           
395          self.parent.analysis_type = 'relax_disp' 
 396   
397   
398 -    def select_mf(self, event): 
 399          """NOE analysis selection. 
400   
401          @param event:   The wx event. 
402          @type event:    wx event 
403          """ 
404   
405           
406          self.toggle(self.button_mf) 
407   
408           
409          self.analysis_name.SetValue(str_to_gui('Model-free')) 
410   
411           
412          self.parent.analysis_type = 'mf' 
 413   
414   
415 -    def select_noe(self, event): 
 416          """NOE analysis selection. 
417   
418          @param event:   The wx event. 
419          @type event:    wx event 
420          """ 
421   
422           
423          self.toggle(self.button_noe) 
424   
425           
426          self.analysis_name.SetValue(str_to_gui('Steady-state NOE')) 
427   
428           
429          self.parent.analysis_type = 'noe' 
 430   
431   
432 -    def select_r1(self, event): 
 433          """NOE analysis selection. 
434   
435          @param event:   The wx event. 
436          @type event:    wx event 
437          """ 
438   
439           
440          self.toggle(self.button_r1) 
441   
442           
443          self.analysis_name.SetValue(str_to_gui("R1 relaxation")) 
444   
445           
446          self.parent.analysis_type = 'r1' 
 447   
448   
449 -    def select_r2(self, event): 
 450          """NOE analysis selection. 
451   
452          @param event:   The wx event. 
453          @type event:    wx event 
454          """ 
455   
456           
457          self.toggle(self.button_r2) 
458   
459           
460          self.analysis_name.SetValue(str_to_gui("R2 relaxation")) 
461   
462           
463          self.parent.analysis_type = 'r2' 
 464   
465   
466 -    def toggle(self, button): 
 467          """Toggle all buttons off except the selected one. 
468   
469          @param button:  The button of the selected analysis. 
470          @type button:   wx.ToggleButton instance 
471          """ 
472   
473           
474          self.Freeze() 
475   
476           
477          self._select_flag = True 
478   
479           
480          self.button_noe.SetValue(False) 
481          self.button_r1.SetValue(False) 
482          self.button_r2.SetValue(False) 
483          self.button_mf.SetValue(False) 
484          self.button_disp.SetValue(False) 
485          self.button_consist_test.SetValue(False) 
486          self.button_custom.SetValue(False) 
487          self.button_reserved.SetValue(False) 
488   
489           
490          button.SetValue(True) 
491   
492           
493          self.Refresh() 
494   
495           
496          self.Thaw() 
497   
498           
499          self.parent.block_next(not self._select_flag) 
  500