Package gui :: Package analyses :: Module wizard
[hide private]
[frames] | no frames]

Source Code for Module gui.analyses.wizard

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2011-2013 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """Module for the analysis selection wizard.""" 
 24   
 25  # Python module imports. 
 26  from os import sep 
 27  from time import asctime, localtime 
 28  import wx 
 29  from wx.lib import buttons 
 30   
 31  # relax module imports. 
 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.wizards.wiz_objects import Wiz_page, Wiz_window 
 37  from lib.text.gui import r1, r2 
 38   
 39   
40 -class Analysis_wizard:
41 """The analysis selection wizard.""" 42
43 - def run(self):
44 """Run through the analysis selection wizard, returning the results. 45 46 @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list. 47 @rtype: tuple of str 48 """ 49 50 # Change the cursor to busy. 51 wx.Yield() 52 wx.BeginBusyCursor() 53 54 # Set up the wizard. 55 self.wizard = Wiz_window(size_x=850, size_y=700, title='Analysis selection wizard') 56 57 # Change the finish button. 58 self.wizard.TEXT_FINISH = " Start" 59 60 # Add the new analysis panel. 61 self.new_page = New_analysis_page(self.wizard) 62 self.wizard.add_page(self.new_page, apply_button=False) 63 64 # Add the data pipe name panel. 65 self.pipe_page = Data_pipe_page(self.wizard, height_desc=400) 66 self.wizard.add_page(self.pipe_page, apply_button=False) 67 68 # Reset the cursor. 69 if wx.IsBusy(): 70 wx.EndBusyCursor() 71 72 # Execute the wizard. 73 setup = self.wizard.run(modal=True) 74 if setup != wx.ID_OK: 75 return 76 77 # Return the analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list. 78 return self.get_data()
79 80
81 - def get_data(self):
82 """Assemble and return the analysis type, analysis name, and pipe name. 83 84 @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and list of user function on_execute methods. 85 @rtype: str, str, str, str, list of methods 86 """ 87 88 # Get the data. 89 analysis_type = gui_to_str(self.wizard.analysis_type) 90 analysis_name = gui_to_str(self.new_page.analysis_name.GetValue()) 91 pipe_name = gui_to_str(self.pipe_page.pipe_name.GetValue()) 92 pipe_bundle = gui_to_str(self.pipe_page.pipe_bundle.GetValue()) 93 94 # The user function on_execute methods. 95 uf_exec = [] 96 97 # Return it. 98 return analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec
99 100 101
102 -class Data_pipe_page(Wiz_page):
103 """The panel for setting the data pipe name.""" 104 105 # Class variables. 106 image_path = WIZARD_IMAGE_PATH + 'pipe.png' 107 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) 108 title = 'Data pipe set up' 109
110 - def add_contents(self, sizer):
111 """Add the specific GUI elements (dummy method). 112 113 @param sizer: A sizer object. 114 @type sizer: wx.Sizer instance 115 """ 116 117 # The pipe name input. 118 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) 119 120 # The pipe bundle input. 121 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) 122 123 # Spacing. 124 sizer.AddStretchSpacer(3)
125 126
127 - def on_display(self):
128 """Update the pipe name.""" 129 130 # Generate a name for the data pipe bundle based on the type and time. 131 name = "%s (%s)" % (self.parent.analysis_type, asctime(localtime())) 132 133 # Update the fields. 134 self.pipe_name.SetValue(str_to_gui("origin - %s" % name)) 135 self.pipe_bundle.SetValue(str_to_gui(name))
136 137 138
139 -class New_analysis_button(buttons.ThemedGenBitmapTextToggleButton):
140 """A special button for the new analysis panel.""" 141
142 - def OnLeftDown(self, event):
143 """Catch left button mouse down events to ignore when the button is toggled. 144 145 @param event: The wx event. 146 @type event: wx event 147 """ 148 149 # Do nothing on a click if already selected. 150 if self.GetValue(): 151 event.Skip() 152 153 # Otherwise, perform the normal operations. 154 else: 155 super(buttons.ThemedGenBitmapTextToggleButton, self).OnLeftDown(event)
156 157
158 - def OnMouse(self, event):
159 """Catch mouse events, specifically entry into the window. 160 161 @param event: The wx event. 162 @type event: wx event 163 """ 164 165 # Do nothing if entering the button when it is selected. 166 if event.GetEventType() == wx.EVT_ENTER_WINDOW.typeId and self.GetValue(): 167 event.Skip() 168 169 # Otherwise, perform the normal operations. 170 else: 171 super(buttons.ThemedGenBitmapTextToggleButton, self).OnMouse(event)
172 173 174
175 -class New_analysis_page(Wiz_page):
176 """The panel for selection of the new analysis.""" 177 178 # Class variables. 179 image_path = IMAGE_PATH + "relax.gif" 180 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) 181 title = "Start a new analysis" 182
183 - def add_artwork(self, sizer):
184 """Add the artwork to the dialog. 185 186 @param sizer: A sizer object. 187 @type sizer: wx.Sizer instance 188 """ 189 190 # Create a vertical box. 191 sizer2 = wx.BoxSizer(wx.VERTICAL) 192 193 # Add a spacer. 194 sizer2.AddSpacer(30) 195 196 # Add the graphics. 197 self.image = wx.StaticBitmap(self, -1, bitmap_setup(self.image_path)) 198 sizer2.Add(self.image, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 0) 199 200 # Nest the sizers. 201 sizer.Add(sizer2) 202 203 # A spacer. 204 sizer.AddSpacer(self.art_spacing)
205 206
207 - def add_buttons(self, box):
208 """The widget of analysis buttons. 209 210 @param box: A sizer object. 211 @type box: wx.BoxSizer instance 212 """ 213 214 # The sizes. 215 size = (170, 170) 216 217 # No button is initially selected. 218 self._select_flag = False 219 220 # The horizontal spacers. 221 sizer1 = wx.BoxSizer(wx.HORIZONTAL) 222 sizer2 = wx.BoxSizer(wx.HORIZONTAL) 223 224 # A set of unique IDs for the buttons. 225 self.button_ids = {'noe': wx.NewId(), 226 'r1': wx.NewId(), 227 'r2': wx.NewId(), 228 'consist_test': wx.NewId(), 229 'mf': wx.NewId(), 230 'custom': wx.NewId()} 231 232 # The NOE button. 233 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) 234 235 # The R1 button. 236 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) 237 238 # The R2 button. 239 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) 240 241 # Consistency testing. 242 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", fn=self.select_consist_test, disabled=True) 243 244 # The model-free button. 245 self.button_mf = self.create_button(id=self.button_ids['mf'], box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"model_free"+sep+"model_free_150x150.png", tooltip="Model-free analysis", fn=self.select_mf) 246 247 # The custom analysis button. 248 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", fn=self.select_custom, disabled=True) 249 250 # Add the sizers. 251 box.Add(sizer1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0) 252 box.Add(sizer2, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
253 254
255 - def add_contents(self, sizer):
256 """Add the specific GUI elements (dummy method). 257 258 @param sizer: A sizer object. 259 @type sizer: wx.Sizer instance 260 """ 261 262 # Add the button widget. 263 self.add_buttons(sizer) 264 265 # Add a spacer. 266 sizer.AddStretchSpacer(2) 267 268 # Add the analysis name field. 269 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)
270 271
272 - def create_button(self, id=-1, box=None, size=None, bmp=None, text='', tooltip='', fn=None, disabled=False):
273 """Create a button for the new analysis selector panel. 274 275 @keyword id: The unique ID number. 276 @type id: int 277 @keyword box: The box sizer to place the button into. 278 @type box: wx.BoxSizer instance 279 @keyword size: The size of the button. 280 @type size: tuple of int 281 @keyword bmp: The full path of the bitmap image to use for the button. 282 @type bmp: str 283 @keyword text: The text for the button. 284 @type text: str 285 @keyword tooltip: The button tooltip text. 286 @type tooltip: str 287 @keyword fn: The function to bind the button click to. 288 @type fn: method 289 @return: The button. 290 @rtype: wx.lib.buttons.ThemedGenBitmapTextToggleButton instance 291 """ 292 293 # Generate the button. 294 if bmp: 295 image = wx.Bitmap(bmp, wx.BITMAP_TYPE_ANY) 296 button = New_analysis_button(self, id, image) 297 else: 298 button = New_analysis_button(self, id) 299 300 # Set the tool tip. 301 button.SetToolTipString(tooltip) 302 303 # Button properties. 304 button.SetMinSize(size) 305 306 # Add to the given sizer. 307 box.Add(button) 308 309 # Bind the click. 310 if fn != None: 311 self.Bind(wx.EVT_BUTTON, fn, button) 312 313 # The button is disabled. 314 if disabled: 315 button.Disable() 316 317 # Return the button. 318 return button
319 320
321 - def on_display(self):
322 """Disable the next button until an analysis is selected.""" 323 324 # Turn off the next button. 325 self.parent.block_next(not self._select_flag)
326 327
328 - def select_consist_test(self, event):
329 """NOE analysis selection. 330 331 @param event: The wx event. 332 @type event: wx event 333 """ 334 335 # Toggle all buttons off. 336 self.toggle(self.button_consist_test) 337 338 # Set the analysis type. 339 self.parent.analysis_type = 'consistency test'
340 341
342 - def select_custom(self, event):
343 """NOE analysis selection. 344 345 @param event: The wx event. 346 @type event: wx event 347 """ 348 349 # Toggle all buttons off. 350 self.toggle(self.button_custom) 351 352 # Set the analysis type. 353 self.parent.analysis_type = 'custom'
354 355
356 - def select_mf(self, event):
357 """NOE analysis selection. 358 359 @param event: The wx event. 360 @type event: wx event 361 """ 362 363 # Toggle all buttons off. 364 self.toggle(self.button_mf) 365 366 # Update the analysis name. 367 self.analysis_name.SetValue(str_to_gui('Model-free')) 368 369 # Set the analysis type. 370 self.parent.analysis_type = 'mf'
371 372
373 - def select_noe(self, event):
374 """NOE analysis selection. 375 376 @param event: The wx event. 377 @type event: wx event 378 """ 379 380 # Toggle all buttons off. 381 self.toggle(self.button_noe) 382 383 # Update the analysis name. 384 self.analysis_name.SetValue(str_to_gui('Steady-state NOE')) 385 386 # Set the analysis type. 387 self.parent.analysis_type = 'noe'
388 389
390 - def select_r1(self, event):
391 """NOE analysis selection. 392 393 @param event: The wx event. 394 @type event: wx event 395 """ 396 397 # Toggle all buttons off. 398 self.toggle(self.button_r1) 399 400 # Update the analysis name. 401 self.analysis_name.SetValue(str_to_gui("R1 relaxation")) 402 403 # Set the analysis type. 404 self.parent.analysis_type = 'r1'
405 406
407 - def select_r2(self, event):
408 """NOE analysis selection. 409 410 @param event: The wx event. 411 @type event: wx event 412 """ 413 414 # Toggle all buttons off. 415 self.toggle(self.button_r2) 416 417 # Update the analysis name. 418 self.analysis_name.SetValue(str_to_gui("R2 relaxation")) 419 420 # Set the analysis type. 421 self.parent.analysis_type = 'r2'
422 423
424 - def toggle(self, button):
425 """Toggle all buttons off except the selected one. 426 427 @param button: The button of the selected analysis. 428 @type button: wx.ToggleButton instance 429 """ 430 431 # First freeze the wizard. 432 self.Freeze() 433 434 # The button is selected. 435 self._select_flag = True 436 437 # Deselect all. 438 self.button_noe.SetValue(False) 439 self.button_r1.SetValue(False) 440 self.button_r2.SetValue(False) 441 self.button_consist_test.SetValue(False) 442 self.button_mf.SetValue(False) 443 self.button_custom.SetValue(False) 444 445 # Turn on the selected button. 446 button.SetValue(True) 447 448 # Refresh the GUI element. 449 self.Refresh() 450 451 # Unfreeze. 452 self.Thaw() 453 454 # Unblock forwards movement. 455 self.parent.block_next(not self._select_flag)
456