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
41
42 BUTTON_ID_NOE = wx.NewId()
43 BUTTON_ID_R1 = wx.NewId()
44 BUTTON_ID_R2 = wx.NewId()
45 BUTTON_ID_MF = wx.NewId()
46 BUTTON_ID_RELAX_DISP = wx.NewId()
47 BUTTON_ID_CONSIST_TEST = wx.NewId()
48 BUTTON_ID_CUSTOM = wx.NewId()
49 BUTTON_ID_RESERVED = wx.NewId()
50
51
52
54 """The analysis selection wizard."""
55
57 """Properly delete the wizard and all its elements."""
58
59 self.wizard.Destroy()
60
61
63 """Run through the analysis selection wizard, returning the results.
64
65 @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list.
66 @rtype: tuple of str
67 """
68
69
70 wx.Yield()
71 wx.BeginBusyCursor()
72
73
74 self.wizard = Wiz_window(size_x=1000, size_y=700, title='Analysis selection wizard')
75
76
77 self.wizard.TEXT_FINISH = " Start"
78
79
80 self.new_page = New_analysis_page(self.wizard)
81 self.wizard.add_page(self.new_page, apply_button=False)
82 self.wizard.set_seq_next_fn(0, self.wizard_page_after_analysis)
83
84
85 self.pipe_page = Data_pipe_page(self.wizard, height_desc=400)
86 self.wizard.add_page(self.pipe_page, apply_button=False)
87
88
89 if wx.IsBusy():
90 wx.EndBusyCursor()
91
92
93 setup = self.wizard.run(modal=True)
94 if setup != wx.ID_OK:
95 return
96
97
98 return self.get_data()
99
100
102 """Assemble and return the analysis type, analysis name, and pipe name.
103
104 @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and list of user function on_execute methods.
105 @rtype: str, str, str, str, list of methods
106 """
107
108
109 analysis_type = gui_to_str(self.wizard.analysis_type)
110 analysis_name = gui_to_str(self.new_page.analysis_name.GetValue())
111 pipe_name = gui_to_str(self.pipe_page.pipe_name.GetValue())
112 pipe_bundle = gui_to_str(self.pipe_page.pipe_bundle.GetValue())
113
114
115 uf_exec = []
116
117
118 return analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec
119
120
122 """Set the page after the data pipe setup.
123
124 @return: The index of the next page, which is the current page index plus one.
125 @rtype: int
126 """
127
128
129 analysis_name = gui_to_str(self.new_page.analysis_name.GetValue())
130
131
132 return 1
133
134
135
136 -class Data_pipe_page(Wiz_page):
137 """The panel for setting the data pipe name."""
138
139
140 image_path = WIZARD_IMAGE_PATH + 'pipe.png'
141 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)
142 title = 'Data pipe set up'
143
144 - def add_contents(self, sizer):
145 """Add the specific GUI elements (dummy method).
146
147 @param sizer: A sizer object.
148 @type sizer: wx.Sizer instance
149 """
150
151
152 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)
153
154
155 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)
156
157
158 sizer.AddStretchSpacer(3)
159
160
161 - def on_display(self):
162 """Update the pipe name."""
163
164
165 name = "%s (%s)" % (self.parent.analysis_type, asctime(localtime()))
166
167
168 self.pipe_name.SetValue(str_to_gui("origin - %s" % name))
169 self.pipe_bundle.SetValue(str_to_gui(name))
170
171
172
206
207
208
209 -class New_analysis_page(Wiz_page):
210 """The panel for selection of the new analysis."""
211
212
213 image_path = IMAGE_PATH + "relax.gif"
214 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)
215 title = "Start a new analysis"
216
217 - def add_artwork(self, sizer):
218 """Add the artwork to the dialog.
219
220 @param sizer: A sizer object.
221 @type sizer: wx.Sizer instance
222 """
223
224
225 sizer2 = wx.BoxSizer(wx.VERTICAL)
226
227
228 sizer2.AddSpacer(30)
229
230
231 self.image = wx.StaticBitmap(self, -1, bitmap_setup(self.image_path))
232 sizer2.Add(self.image, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 0)
233
234
235 sizer.Add(sizer2)
236
237
238 sizer.AddSpacer(self.art_spacing)
239
240
242 """The widget of analysis buttons.
243
244 @param box: A sizer object.
245 @type box: wx.BoxSizer instance
246 """
247
248
249 size = (170, 170)
250
251
252 self._select_flag = False
253
254
255 sizer1 = wx.BoxSizer(wx.HORIZONTAL)
256 sizer2 = wx.BoxSizer(wx.HORIZONTAL)
257
258
259 self.button_noe = self.create_button(id=BUTTON_ID_NOE, box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"noe_150x150.png", tooltip="Steady-state NOE analysis", fn=self.select_noe)
260
261
262 self.button_r1 = self.create_button(id=BUTTON_ID_R1, box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"r1_150x150.png", tooltip="%s relaxation curve-fitting analysis" % r1, fn=self.select_r1)
263
264
265 self.button_r2 = self.create_button(id=BUTTON_ID_R2, box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"r2_150x150.png", tooltip="%s relaxation curve-fitting analysis" % r2, fn=self.select_r2)
266
267
268 self.button_mf = self.create_button(id=BUTTON_ID_MF, box=sizer1, size=size, bmp=ANALYSIS_IMAGE_PATH+"model_free"+sep+"model_free_150x150.png", tooltip="Model-free analysis", fn=self.select_mf)
269
270
271 self.button_disp = self.create_button(id=BUTTON_ID_RELAX_DISP, box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"relax_disp_150x150.png", tooltip="Relaxation dispersion analysis", fn=self.select_disp)
272
273
274 self.button_consist_test = self.create_button(id=BUTTON_ID_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)
275
276
277 self.button_custom = self.create_button(id=BUTTON_ID_CUSTOM, box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"custom_150x150.png", tooltip="Custom analysis (disabled)", fn=self.select_custom, disabled=True)
278
279
280 self.button_reserved = self.create_button(id=BUTTON_ID_RESERVED, box=sizer2, size=size, bmp=ANALYSIS_IMAGE_PATH+"blank_150x150.png", tooltip=None, fn=None, disabled=True)
281
282
283 box.Add(sizer1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
284 box.Add(sizer2, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
285
286
287 - def add_contents(self, sizer):
288 """Add the specific GUI elements (dummy method).
289
290 @param sizer: A sizer object.
291 @type sizer: wx.Sizer instance
292 """
293
294
295 self.add_buttons(sizer)
296
297
298 sizer.AddStretchSpacer(2)
299
300
301 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)
302
303
304 - def create_button(self, id=-1, box=None, size=None, bmp=None, text='', tooltip='', fn=None, disabled=False):
305 """Create a button for the new analysis selector panel.
306
307 @keyword id: The unique ID number.
308 @type id: int
309 @keyword box: The box sizer to place the button into.
310 @type box: wx.BoxSizer instance
311 @keyword size: The size of the button.
312 @type size: tuple of int
313 @keyword bmp: The full path of the bitmap image to use for the button.
314 @type bmp: str
315 @keyword text: The text for the button.
316 @type text: str
317 @keyword tooltip: The button tooltip text.
318 @type tooltip: str or None
319 @keyword fn: The function to bind the button click to.
320 @type fn: method
321 @return: The button.
322 @rtype: wx.lib.buttons.ThemedGenBitmapTextToggleButton instance
323 """
324
325
326 if bmp:
327 image = wx.Bitmap(bmp, wx.BITMAP_TYPE_ANY)
328 button = New_analysis_button(self, id, image)
329 else:
330 button = New_analysis_button(self, id)
331
332
333 if tooltip != None:
334 button.SetToolTip(wx.ToolTip(tooltip))
335
336
337 button.SetMinSize(size)
338
339
340 box.Add(button)
341
342
343 if fn != None:
344 self.Bind(wx.EVT_BUTTON, fn, button)
345
346
347 if disabled:
348 button.Disable()
349
350
351 return button
352
353
354 - def on_display(self):
355 """Disable the next button until an analysis is selected."""
356
357
358 self.parent.block_next(not self._select_flag)
359
360
361 - def select_consist_test(self, event):
362 """NOE analysis selection.
363
364 @param event: The wx event.
365 @type event: wx event
366 """
367
368
369 self.toggle(self.button_consist_test)
370
371
372 self.parent.analysis_type = 'consistency test'
373
374
375 - def select_custom(self, event):
376 """NOE analysis selection.
377
378 @param event: The wx event.
379 @type event: wx event
380 """
381
382
383 self.toggle(self.button_custom)
384
385
386 self.parent.analysis_type = 'custom'
387
388
389 - def select_disp(self, event):
390 """Relaxation dispersion analysis selection.
391
392 @param event: The wx event.
393 @type event: wx event
394 """
395
396
397 self.toggle(self.button_disp)
398
399
400 self.analysis_name.SetValue(str_to_gui('Relaxation dispersion'))
401
402
403 self.parent.analysis_type = 'relax_disp'
404
405
406 - def select_mf(self, event):
407 """NOE analysis selection.
408
409 @param event: The wx event.
410 @type event: wx event
411 """
412
413
414 self.toggle(self.button_mf)
415
416
417 self.analysis_name.SetValue(str_to_gui('Model-free'))
418
419
420 self.parent.analysis_type = 'mf'
421
422
423 - def select_noe(self, event):
424 """NOE analysis selection.
425
426 @param event: The wx event.
427 @type event: wx event
428 """
429
430
431 self.toggle(self.button_noe)
432
433
434 self.analysis_name.SetValue(str_to_gui('Steady-state NOE'))
435
436
437 self.parent.analysis_type = 'noe'
438
439
440 - def select_r1(self, event):
441 """NOE analysis selection.
442
443 @param event: The wx event.
444 @type event: wx event
445 """
446
447
448 self.toggle(self.button_r1)
449
450
451 self.analysis_name.SetValue(str_to_gui("R1 relaxation"))
452
453
454 self.parent.analysis_type = 'r1'
455
456
457 - def select_r2(self, event):
458 """NOE analysis selection.
459
460 @param event: The wx event.
461 @type event: wx event
462 """
463
464
465 self.toggle(self.button_r2)
466
467
468 self.analysis_name.SetValue(str_to_gui("R2 relaxation"))
469
470
471 self.parent.analysis_type = 'r2'
472
473
474 - def toggle(self, button):
475 """Toggle all buttons off except the selected one.
476
477 @param button: The button of the selected analysis.
478 @type button: wx.ToggleButton instance
479 """
480
481
482 self.Freeze()
483
484
485 self._select_flag = True
486
487
488 self.button_noe.SetValue(False)
489 self.button_r1.SetValue(False)
490 self.button_r2.SetValue(False)
491 self.button_mf.SetValue(False)
492 self.button_disp.SetValue(False)
493 self.button_consist_test.SetValue(False)
494 self.button_custom.SetValue(False)
495 self.button_reserved.SetValue(False)
496
497
498 button.SetValue(True)
499
500
501 self.Refresh()
502
503
504 self.Thaw()
505
506
507 self.parent.block_next(not self._select_flag)
508