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 for the automatic model-free protocol frame."""
26
27
28 from os import sep
29 import sys
30 import wx
31 import wx.lib.buttons
32 import wx.lib.mixins.listctrl
33
34
35 from auto_analyses import dauvergne_protocol
36 from data import Relax_data_store; ds = Relax_data_store()
37 from generic_fns.pipes import has_bundle, has_pipe
38 from generic_fns.mol_res_spin import exists_mol_res_spin_data, spin_loop
39 from relax_string import LIST, PARAGRAPH, SECTION, SUBSECTION, TITLE
40 from specific_fns.setup import get_specific_fn
41 from status import Status; status = Status()
42
43
44 from gui.about import About_base
45 from gui.analyses.base import Base_analysis
46 from gui.analyses.elements import Spin_ctrl, Text_ctrl
47 from gui.analyses.execute import Execute
48 from gui.base_classes import Container
49 from gui.components.relax_data import Relax_data_list
50 from gui.filedialog import RelaxDirDialog
51 from gui.fonts import font
52 from gui.message import error_message, Question, Missing_data
53 from gui.misc import add_border, protected_exec
54 from gui import paths
55 from gui.string_conv import gui_to_int, gui_to_str, list_to_gui, str_to_gui
56 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
57 from gui.wizard import Wiz_window
58
59
134
135
136
138 """The model-free auto-analysis GUI element."""
139
140 - 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):
141 """Build the automatic model-free protocol GUI element.
142
143 @param parent: The parent wx element.
144 @type parent: wx object
145 @keyword id: The unique ID number.
146 @type id: int
147 @keyword pos: The position.
148 @type pos: wx.Size object
149 @keyword size: The size.
150 @type size: wx.Size object
151 @keyword style: The style.
152 @type style: int
153 @keyword name: The name for the panel.
154 @type name: unicode
155 @keyword gui: The main GUI class.
156 @type gui: gui.relax_gui.Main instance
157 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook).
158 @type analysis_name: str
159 @keyword pipe_name: The name of the original data pipe for this analysis.
160 @type pipe_name: str
161 @keyword pipe_bundle: The name of the data pipe bundle associated with this analysis.
162 @type pipe_bundle: str
163 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists).
164 @type data_index: None or int
165 """
166
167
168 self.gui = gui
169
170
171 self.init_flag = True
172
173
174 if data_index == None:
175
176 if not has_pipe(pipe_name):
177 self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='mf', bundle=pipe_bundle)
178
179
180 if not has_bundle(pipe_bundle):
181 self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name)
182
183
184 data_index = ds.relax_gui.analyses.add('model-free')
185
186
187 ds.relax_gui.analyses[data_index].analysis_name = analysis_name
188 ds.relax_gui.analyses[data_index].pipe_name = pipe_name
189 ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle
190
191
192 ds.relax_gui.analyses[data_index].grid_inc = None
193 ds.relax_gui.analyses[data_index].diff_tensor_grid_inc = {'sphere': 11, 'prolate': 11, 'oblate': 11, 'ellipsoid': 6}
194 ds.relax_gui.analyses[data_index].mc_sim_num = None
195 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir
196 ds.relax_gui.analyses[data_index].local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9']
197 ds.relax_gui.analyses[data_index].mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9']
198 ds.relax_gui.analyses[data_index].max_iter = 30
199
200
201 self.data = ds.relax_gui.analyses[data_index]
202 self.data_index = data_index
203
204
205 if not hasattr(self.data, 'local_tm_models'):
206 self.data.local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9']
207 if not hasattr(self.data, 'mf_models'):
208 self.data.mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9']
209
210
211 self.mode_win = Protocol_mode_sel_window()
212
213
214 self.observer_register()
215
216
217 super(Auto_model_free, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
218
219
220 - def _about(self, event=None):
221 """The about window.
222
223 @keyword event: The wx event.
224 @type event: wx event
225 """
226
227
228 self.about_dialog = About_window(self)
229
230
231 if status.show_gui:
232 self.about_dialog.Show()
233
234
236 """Activate or deactivate certain elements of the analysis in response to the execution lock."""
237
238
239 enable = False
240 if not status.exec_lock.locked():
241 enable = True
242
243
244 wx.CallAfter(self.field_results_dir.Enable, enable)
245 wx.CallAfter(self.spin_systems.Enable, enable)
246 wx.CallAfter(self.relax_data.Enable, enable)
247 wx.CallAfter(self.button_csa.Enable, enable)
248 wx.CallAfter(self.button_r.Enable, enable)
249 wx.CallAfter(self.button_h_type.Enable, enable)
250 wx.CallAfter(self.button_x_type.Enable, enable)
251 wx.CallAfter(self.button_vectors.Enable, enable)
252 wx.CallAfter(self.local_tm_model_field.Enable, enable)
253 wx.CallAfter(self.mf_model_field.Enable, enable)
254 wx.CallAfter(self.grid_inc.Enable, enable)
255 wx.CallAfter(self.mc_sim_num.Enable, enable)
256 wx.CallAfter(self.max_iter.Enable, enable)
257 wx.CallAfter(self.mode.Enable, enable)
258 wx.CallAfter(self.button_exec_relax.Enable, enable)
259
260
262 """Create and add the value.set buttons for the model-free analysis.
263
264 @param box: The box element to pack the GUI element into.
265 @type box: wx.BoxSizer instance
266 """
267
268
269 sizer = wx.BoxSizer(wx.HORIZONTAL)
270
271
272 self.button_csa = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " CSA")
273 self.button_csa.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY))
274 self.button_csa.SetFont(font.normal)
275 self.button_csa.SetSize((-1, 20))
276 self.button_csa.SetToolTipString("Set the Chemical Shift Anisotropy (CSA) values via the value.set user function.")
277 self.gui.Bind(wx.EVT_BUTTON, self.value_set_csa, self.button_csa)
278 sizer.Add(self.button_csa, 1, wx.ALL|wx.EXPAND, 0)
279
280
281 self.button_r = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Bond length")
282 self.button_r.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY))
283 self.button_r.SetFont(font.normal)
284 self.button_r.SetSize((-1, 20))
285 self.button_r.SetToolTipString("Set the bond length (r) values via the value.set user function.")
286 self.gui.Bind(wx.EVT_BUTTON, self.value_set_r, self.button_r)
287 sizer.Add(self.button_r, 1, wx.ALL|wx.EXPAND, 0)
288
289
290 self.button_h_type = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " H type")
291 self.button_h_type.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY))
292 self.button_h_type.SetFont(font.normal)
293 self.button_h_type.SetSize((-1, 20))
294 self.button_h_type.SetToolTipString("Set the type of proton via the value.set user function.")
295 self.gui.Bind(wx.EVT_BUTTON, self.value_set_proton_type, self.button_h_type)
296 sizer.Add(self.button_h_type, 1, wx.ALL|wx.EXPAND, 0)
297
298
299 self.button_x_type = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " X type")
300 self.button_x_type.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY))
301 self.button_x_type.SetFont(font.normal)
302 self.button_x_type.SetSize((-1, 20))
303 self.button_x_type.SetToolTipString("Set the type of heteronucleus via the value.set user function.")
304 self.gui.Bind(wx.EVT_BUTTON, self.value_set_heteronuc_type, self.button_x_type)
305 sizer.Add(self.button_x_type, 1, wx.ALL|wx.EXPAND, 0)
306
307
308 self.button_vectors = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Unit vectors")
309 self.button_vectors.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.structure, wx.BITMAP_TYPE_ANY))
310 self.button_vectors.SetFont(font.normal)
311 self.button_vectors.SetSize((-1, 20))
312 self.button_vectors.SetToolTipString("Load unit vectors from PDB files.")
313 self.gui.Bind(wx.EVT_BUTTON, self.load_unit_vectors, self.button_vectors)
314 sizer.Add(self.button_vectors, 1, wx.ALL|wx.EXPAND, 0)
315
316
317 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
318
319
321 """Assemble the data required for the auto-analysis.
322
323 See the docstring for auto_analyses.dauvernge_protocol for details. All data is taken from the relax data store, so data upload from the GUI to there must have been previously performed.
324
325 @return: A container with all the data required for the auto-analysis.
326 @rtype: class instance, list of str
327 """
328
329
330 data = Container()
331 missing = []
332
333
334 data.pipe_name = self.data.pipe_name
335 data.pipe_bundle = self.data.pipe_bundle
336
337
338 data.local_tm_models = self.local_tm_model_field.GetValue()
339 data.mf_models = self.mf_model_field.GetValue()
340
341
342 data.conv_loop = True
343
344
345 data.inc = gui_to_int(self.grid_inc.GetValue())
346 if hasattr(self.data, 'diff_tensor_grid_inc'):
347 data.diff_tensor_grid_inc = self.data.diff_tensor_grid_inc
348 else:
349 data.diff_tensor_grid_inc = {'sphere': 11, 'prolate': 11, 'oblate': 11, 'ellipsoid': 6}
350
351
352 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
353
354
355 data.max_iter = self.data.max_iter
356
357
358 data.save_dir = self.data.save_dir
359
360
361 if not exists_mol_res_spin_data():
362 missing.append("Sequence data")
363
364
365 if not hasattr(cdp, 'ri_ids') or len(cdp.ri_ids) == 0:
366 missing.append("Relaxation data")
367
368
369 if hasattr(cdp, 'ri_ids') and len(cdp.ri_ids) <= 3:
370 missing.append("Insufficient relaxation data, 4 or more data sets are essential for the execution of the dauvergne_protocol auto-analysis.")
371
372
373 mode = gui_to_str(self.mode.GetValue())
374
375
376 if mode == 'Fully automated':
377
378 data.global_models = ['local_tm', 'sphere', 'prolate', 'oblate', 'ellipsoid', 'final']
379
380
381 else:
382 data.global_models = [mode]
383
384
385 vector_check = False
386 if 'prolate' in data.global_models or 'oblate' in data.global_models or 'ellipsoid' in data.global_models:
387 vector_check = True
388
389
390 for spin, spin_id in spin_loop(return_id=True):
391
392 if not spin.select:
393 continue
394
395
396 msg = "Spin '%s' - %s (try the %s user function)." % (spin_id, "%s", "%s")
397
398
399 if not hasattr(spin, 'r') or spin.r == None:
400 missing.append(msg % ("bond length data", "value.set"))
401
402
403 if not hasattr(spin, 'csa') or spin.csa == None:
404 missing.append(msg % ("CSA data", "value.set"))
405
406
407 if not hasattr(spin, 'heteronuc_type') or spin.heteronuc_type == None:
408 missing.append(msg % ("heteronucleus type data", "value.set"))
409
410
411 if not hasattr(spin, 'proton_type') or spin.proton_type == None:
412 missing.append(msg % ("proton type data", "value.set"))
413
414
415 if vector_check and (not hasattr(spin, 'xh_vect') or spin.xh_vect == None):
416 missing.append(msg % ("unit vectors", "structure.vectors"))
417
418
419 return data, missing
420
421
423 """Construct the left hand box to pack into the main model-free box.
424
425 @return: The left hand box element containing the bitmap and about button to pack into the main model-free box.
426 @rtype: wx.BoxSizer instance
427 """
428
429
430 left_box = wx.BoxSizer(wx.VERTICAL)
431
432
433 bitmaps = [paths.ANALYSIS_IMAGE_PATH+"model_free"+sep+"model_free_200x200.png",
434 paths.IMAGE_PATH+'modelfree.png']
435
436
437 for i in range(len(bitmaps)):
438
439 bitmap = wx.StaticBitmap(self, -1, wx.Bitmap(bitmaps[i], wx.BITMAP_TYPE_ANY))
440
441
442 left_box.Add(bitmap, 0, wx.ALL, 0)
443
444
445 left_box.AddStretchSpacer()
446
447
448 button_sizer = wx.BoxSizer(wx.HORIZONTAL)
449
450
451 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "About")
452 button.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.about, wx.BITMAP_TYPE_ANY))
453 button.SetFont(font.normal)
454 button.SetToolTipString("Information about this automatic analysis")
455
456
457 self.Bind(wx.EVT_BUTTON, self._about, button)
458
459
460 cursor = wx.StockCursor(wx.CURSOR_QUESTION_ARROW)
461 button.SetCursor(cursor)
462
463
464 button_sizer.Add(button, 0, 0, 0)
465 left_box.Add(button_sizer, 0, wx.ALL, 0)
466
467
468 return left_box
469
470
472 """Construct the right hand box to pack into the main model-free box.
473
474 @return: The right hand box element containing all model-free GUI elements (excluding the bitmap) to pack into the main model-free box.
475 @rtype: wx.BoxSizer instance
476 """
477
478
479 box = wx.BoxSizer(wx.VERTICAL)
480
481
482 self.add_title(box, "Setup for model-free analysis")
483
484
485 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)
486
487
488 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)
489
490
491 self.add_spin_systems(box, self)
492
493
494 box.AddSpacer(10)
495 self.relax_data = Relax_data_list(gui=self.gui, parent=self, box=box, id=str(self.data_index))
496 box.AddSpacer(10)
497
498
499 self.add_values(box)
500 box.AddSpacer(10)
501
502
503 self.local_tm_model_field = Local_tm_list(self, box)
504 self.local_tm_model_field.set_value(self.data.local_tm_models)
505
506
507 self.mf_model_field = Mf_list(self, box)
508 self.mf_model_field.set_value(self.data.mf_models)
509
510
511 self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=11, 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)
512 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.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
513
514
515 self.max_iter = Spin_ctrl(box, self, text="Maximum interations", default=self.data.max_iter, min=25, max=100, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
516
517
518 self.mode = Text_ctrl(box, self, text="Protocol mode:", default='Fully automated', tooltip="Select if the dauvergne_protocol analysis will be fully automated or whether the individual global models will be optimised one by one.", icon=paths.icon_16x16.system_run, fn=self.mode_dialog, editable=False, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
519
520
521 box.AddSpacer(30)
522 box.AddStretchSpacer()
523
524
525 self.button_exec_relax = self.add_execute_relax(box, self.execute)
526
527
528 return box
529
530
539
540
581
582
584 """Create the wizard for structure.read_pdb and structure.vectors.
585
586 @keyword event: The wx event.
587 @type event: wx event
588 """
589
590
591 wx.BeginBusyCursor()
592
593
594 self.vect_wizard = Wiz_window(parent=self.gui, size_x=1000, size_y=750, title="Load unit vectors from file")
595
596
597 page = uf_store['structure.read_pdb'].create_page(self.vect_wizard)
598 self.vect_wizard.add_page(page, skip_button=True)
599
600
601 page = uf_store['structure.vectors'].create_page(self.vect_wizard)
602 self.vect_wizard.add_page(page)
603
604
605 if wx.IsBusy():
606 wx.EndBusyCursor()
607
608
609 self.vect_wizard.run()
610
611
613 """The calculation mode selection.
614
615 @keyword event: The wx event.
616 @type event: wx event
617 """
618
619
620 if status.show_gui:
621 self.mode_win.ShowModal()
622
623
624 self.mode.SetValue(str_to_gui(self.mode_win.select))
625
626
647
648
650 """The results directory selection.
651
652 @keyword event: The wx event.
653 @type event: wx event
654 """
655
656
657 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue())
658
659
660 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
661
662 return
663
664
665 path = gui_to_str(dialog.get_path())
666 if not path:
667 return
668
669
670 self.data.save_dir = path
671
672
673 self.field_results_dir.SetValue(str_to_gui(path))
674
675
677 """Synchronise the analysis frame and the relax data store, both ways.
678
679 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.
680
681 @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.
682 @type upload: bool
683 """
684
685
686 if upload:
687 self.data.local_tm_models = self.local_tm_model_field.GetValue()
688 else:
689 self.local_tm_model_field.set_value(self.data.local_tm_models)
690
691
692 if upload:
693 self.data.mf_models = self.mf_model_field.GetValue()
694 else:
695 self.mf_model_field.set_value(self.data.mf_models)
696
697
698 if upload:
699 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue())
700 elif hasattr(self.data, 'grid_inc'):
701 self.grid_inc.SetValue(int(self.data.grid_inc))
702
703
704 if upload:
705 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
706 elif hasattr(self.data, 'mc_sim_num'):
707 self.mc_sim_num.SetValue(int(self.data.mc_sim_num))
708
709
710 if upload:
711 self.data.save_dir = str(self.field_results_dir.GetValue())
712 else:
713 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir))
714
715
716 if upload:
717 self.data.max_iter = gui_to_int(self.max_iter.GetValue())
718 else:
719 self.max_iter.SetValue(int(self.data.max_iter))
720
721
723 """Set the CSA via the value.set uf.
724
725 @keyword event: The wx event.
726 @type event: wx event
727 """
728
729
730 val = get_specific_fn('default_value')('csa')
731
732
733 uf_store['value.set'](val=val, param='csa')
734
735
737 """Set the type of heteronucleus via the value.set uf.
738
739 @keyword event: The wx event.
740 @type event: wx event
741 """
742
743
744 val = get_specific_fn('default_value')('heteronuc_type')
745
746
747 uf_store['value.set'](val=val, param='heteronuc_type')
748
749
751 """Set the type of proton via the value.set uf.
752
753 @keyword event: The wx event.
754 @type event: wx event
755 """
756
757
758 val = get_specific_fn('default_value')('proton_type')
759
760
761 uf_store['value.set'](val=val, param='proton_type')
762
763
765 """Set the bond length via the value.set uf.
766
767 @keyword event: The wx event.
768 @type event: wx event
769 """
770
771
772 val = get_specific_fn('default_value')('r')
773
774
775 uf_store['value.set'](val=val, param='r')
776
777
778
780 """The model-free analysis execution object."""
781
783 """Execute the calculation."""
784
785
786 dauvergne_protocol.dAuvergne_protocol(pipe_name=self.data.pipe_name, pipe_bundle=self.data.pipe_bundle, results_dir=self.data.save_dir, diff_model=self.data.global_models, mf_models=self.data.mf_models, local_tm_models=self.data.local_tm_models, grid_inc=self.data.inc, diff_tensor_grid_inc=self.data.diff_tensor_grid_inc, mc_sim_num=self.data.mc_sim_num, max_iter=self.data.max_iter, conv_loop=self.data.conv_loop)
787
788
789 ds.relax_gui.analyses[self.data_index].pipe_name = 'final'
790
791
792
794 """The model-free model list GUI element."""
795
796
797 desc = u'Local \u03C4m models:'
798 models = [
799 "tm0",
800 "tm1",
801 "tm2",
802 "tm3",
803 "tm4",
804 "tm5",
805 "tm6",
806 "tm7",
807 "tm8",
808 "tm9"
809 ]
810 params = [
811 "{local_tm}",
812 "{local_tm, S2}",
813 "{local_tm, S2, te}",
814 "{local_tm, S2, Rex}",
815 "{local_tm, S2, te, Rex}",
816 "{local_tm, S2, S2f, ts}",
817 "{local_tm, S2, tf, S2f, ts}",
818 "{local_tm, S2, S2f, ts, Rex}",
819 "{local_tm, S2, tf, S2f, ts, Rex}",
820 "{local_tm, Rex}"
821 ]
822
824 """Build the combo box list widget for a list of list selections.
825
826 @param parent: The parent GUI element.
827 @type parent: wx object instance
828 @param box: The sizer to put the combo box widget into.
829 @type box: wx.Sizer instance
830 """
831
832
833 self.parent = parent
834
835
836 self.select = []
837 for i in range(len(self.models)):
838 self.select.append(True)
839
840
841 self.model_win = Model_sel_window(self.models, self.params)
842
843
844 sizer = wx.BoxSizer(wx.HORIZONTAL)
845
846
847 label = self.parent.add_static_text(sizer, self.parent, text=self.desc, width=self.parent.width_text)
848
849
850 sizer.AddSpacer((self.parent.spacer_horizontal, -1))
851
852
853 self.field = self.parent.add_text_control(sizer, self.parent, text=list_to_gui(self.GetValue()), editable=False)
854
855
856 sizer.AddSpacer((self.parent.spacer_horizontal, -1))
857
858
859 self.button = self.parent.add_button_open(sizer, self.parent, icon=paths.icon_16x16.flag_blue, text="Modify", fn=self.modify, width=self.parent.width_button, height=label.GetSize()[1]+8)
860
861
862 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
863
864
865 - def Enable(self, enable=True):
866 """Enable or disable the element.
867
868 @keyword enable: The flag specifying if the element should be enabled or disabled.
869 @type enable: bool
870 """
871
872
873 self.field.Enable(enable)
874 self.button.Enable(enable)
875
876
878 """Return the list of model-free models.
879
880 @return: The list of model-free models.
881 @rtype: list of str
882 """
883
884
885 model_list = []
886
887
888 for i in range(len(self.models)):
889 if self.select[i]:
890 model_list.append(self.models[i])
891
892
893 return model_list
894
895
897 """Store the list of model-free models.
898
899 @param value: The list of model-free models.
900 @type value: list of str
901 """
902
903
904 for i in range(len(self.models)):
905 self.select[i] = False
906
907
908 for model in value:
909
910 index = self.models.index(model)
911
912
913 self.select[index] = True
914
915
916 self.update_button()
917
918
919 self.field.SetValue(list_to_gui(self.GetValue()))
920
921
922 - def modify(self, event=None):
923 """Modify the model-free model selection.
924
925 @keyword event: The wx event.
926 @type event: wx event
927 """
928
929
930 msg = "The model-free models used in dauvergne_protocol auto-analysis should almost never be changed! The consequences will be unpredictable. Please proceed only if you are sure of what you are doing. Would you like to modify the model-free model list?"
931 if status.show_gui and not Question(msg, title="Warning - do not change!", size=(420, 210), default=False).ShowModal() == wx.ID_YES:
932 return
933
934
935 self.model_win.set_selection(self.select)
936
937
938 if status.show_gui:
939 self.model_win.ShowModal()
940 self.model_win.Close()
941
942
943 self.select = self.model_win.get_selection()
944
945
946 self.update_button()
947
948
949 self.field.SetValue(list_to_gui(self.GetValue()))
950
951
962
963
964
966 """The model-free model list GUI element."""
967
968
969 desc = "Model-free models:"
970 models = [
971 "m0",
972 "m1",
973 "m2",
974 "m3",
975 "m4",
976 "m5",
977 "m6",
978 "m7",
979 "m8",
980 "m9"
981 ]
982 params = [
983 "{}",
984 "{S2}",
985 "{S2, te}",
986 "{S2, Rex}",
987 "{S2, te, Rex}",
988 "{S2, S2f, ts}",
989 "{S2, tf, S2f, ts}",
990 "{S2, S2f, ts, Rex}",
991 "{S2, tf, S2f, ts, Rex}",
992 "{Rex}"
993 ]
994
995
996
998 """The model-free model selector window object."""
999
1001 """Set up the model-free model selector window.
1002
1003 @param models: The list of model-free models.
1004 @type models: list of str
1005 @param params: The list of parameters corresponding to the models.
1006 @type params: list of str
1007 """
1008
1009
1010 wx.Dialog.__init__(self, None, id=-1, title="Model-free model selector")
1011
1012
1013 size_x = 500
1014 size_y = 300
1015 border = 10
1016 width = size_x - 2*border
1017
1018
1019 self.SetSize((size_x, size_y))
1020 self.Centre()
1021 self.SetFont(font.normal)
1022
1023
1024 main_sizer = wx.BoxSizer(wx.VERTICAL)
1025
1026
1027 self.SetSizer(main_sizer)
1028
1029
1030 sizer = add_border(main_sizer, border=border, packing=wx.VERTICAL)
1031
1032
1033 self.model_list = ModelSelListCtrl(self)
1034
1035
1036 self.model_list.InsertColumn(0, "Model-free model")
1037 self.model_list.InsertColumn(1, "Parameters")
1038
1039
1040 self.model_list.SetColumnWidth(0, int(0.4*width))
1041 self.model_list.SetColumnWidth(1, int(0.5*width))
1042
1043
1044 for i in range(len(models)):
1045
1046 self.model_list.Append((str_to_gui(models[i]), str_to_gui(params[i])))
1047
1048
1049 self.model_list.CheckItem(i)
1050
1051
1052 sizer.Add(self.model_list, 1, wx.ALL|wx.EXPAND, 0)
1053
1054
1056 """Return the selection as a list of booleans.
1057
1058 @return: The list of models selected.
1059 @rtype: list of bool
1060 """
1061
1062
1063 select = []
1064
1065
1066 for i in range(self.model_list.GetItemCount()):
1067 select.append(self.model_list.IsChecked(i))
1068
1069
1070 return select
1071
1072
1074 """Set the selection.
1075
1076 @param select: The list of selections.
1077 @type select: list of bool
1078 """
1079
1080
1081 for i in range(self.model_list.GetItemCount()):
1082 self.model_list.CheckItem(i, check=select[i])
1083
1084
1085
1086 -class ModelSelListCtrl(wx.ListCtrl, wx.lib.mixins.listctrl.CheckListCtrlMixin):
1087 """A special list control with checkboxes."""
1088
1090 """Initialise the control.
1091
1092 @param parent: The parent window.
1093 @type parent: wx.Frame instance
1094 """
1095
1096
1097 wx.ListCtrl.__init__(self, parent, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT)
1098
1099
1100 wx.lib.mixins.listctrl.CheckListCtrlMixin.__init__(self)
1101
1102
1103
1105 """The protocol mode selector window object."""
1106
1108 """Set up the window."""
1109
1110
1111 wx.Dialog.__init__(self, None, id=-1, title="Protocol mode selection")
1112
1113
1114 size_x = 600
1115 size_y = 600
1116 border = 10
1117 self.select = 'Fully automated'
1118
1119
1120 self.SetSize((size_x, size_y))
1121 self.Centre()
1122 self.SetFont(font.normal)
1123
1124
1125 main_sizer = wx.BoxSizer(wx.VERTICAL)
1126
1127
1128 self.SetSizer(main_sizer)
1129
1130
1131 sizer = add_border(main_sizer, border=border, packing=wx.HORIZONTAL)
1132
1133
1134 self.build_auto(sizer)
1135
1136
1137 sizer.Add(wx.StaticLine(self, -1, style=wx.LI_VERTICAL), 0, wx.EXPAND|wx.ALL, border)
1138
1139
1140 self.build_manual(sizer)
1141
1142
1144 """Build the fully automated part of the window.
1145
1146 @param sizer: The sizer to pack the elements into.
1147 @type sizer: wx.BoxSizer instance
1148 """
1149
1150
1151 sub_sizer = wx.BoxSizer(wx.VERTICAL)
1152
1153
1154 title = wx.StaticText(self, -1, "Fully automated")
1155 title.SetFont(font.subtitle)
1156 sub_sizer.Add(title, 0, wx.ALIGN_CENTRE_HORIZONTAL, 0)
1157
1158
1159 sub_sizer.AddStretchSpacer()
1160
1161
1162 button = wx.BitmapButton(self, -1, wx.Bitmap(paths.icon_48x48.go_bottom, wx.BITMAP_TYPE_ANY))
1163 button.SetMinSize((80, 80))
1164 button.SetToolTipString("Perform a fully automated analysis, looping over global models I to V and terminating with the final run. Please click on the 'About' button for more information.")
1165 sub_sizer.Add(button, 3, wx.EXPAND, 0)
1166 self.Bind(wx.EVT_BUTTON, self.select_full_analysis, button)
1167
1168
1169 sub_sizer.AddStretchSpacer()
1170
1171
1172 sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0)
1173
1174
1176 """Build the manual part of the window.
1177
1178 @param sizer: The sizer to pack the elements into.
1179 @type sizer: wx.BoxSizer instance
1180 """
1181
1182
1183 sub_sizer = wx.BoxSizer(wx.VERTICAL)
1184
1185
1186 title = wx.StaticText(self, -1, "Manual modes")
1187 title.SetFont(font.subtitle)
1188 sub_sizer.Add(title, 0, wx.ALIGN_CENTRE_HORIZONTAL, 0)
1189
1190
1191 sub_sizer.AddSpacer(10)
1192
1193
1194 button = wx.Button(self, -1, u"Local \u03C4m")
1195 button.SetToolTipString("Optimise global model I, the local tm models. Please click on the 'About' button for more information.")
1196 button.SetFont(font.normal)
1197 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1198 self.Bind(wx.EVT_BUTTON, self.select_local_tm, button)
1199
1200
1201 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Sphere"))
1202 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'sphere.png', wx.BITMAP_TYPE_ANY))
1203 button.SetFont(font.normal)
1204 button.SetToolTipString("Optimise global model II, the spherical diffusion model. Please click on the 'About' button for more information.")
1205 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1206 self.Bind(wx.EVT_BUTTON, self.select_sphere, button)
1207
1208
1209 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Prolate spheroid"))
1210 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'prolate.png', wx.BITMAP_TYPE_ANY))
1211 button.SetFont(font.normal)
1212 button.SetToolTipString("Optimise global model III, the prolate spheroid diffusion model. Please click on the 'About' button for more information.")
1213 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1214 self.Bind(wx.EVT_BUTTON, self.select_prolate, button)
1215
1216
1217 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Oblate spheroid"))
1218 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'oblate.png', wx.BITMAP_TYPE_ANY))
1219 button.SetFont(font.normal)
1220 button.SetToolTipString("Optimise global model IV, the oblate spheroid diffusion model. Please click on the 'About' button for more information.")
1221 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1222 self.Bind(wx.EVT_BUTTON, self.select_oblate, button)
1223
1224
1225 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Ellipsoid"))
1226 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'ellipsoid.png', wx.BITMAP_TYPE_ANY))
1227 button.SetFont(font.normal)
1228 button.SetToolTipString("Optimise global model V, the ellipsoid diffusion model. Please click on the 'About' button for more information.")
1229 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1230 self.Bind(wx.EVT_BUTTON, self.select_ellipsoid, button)
1231
1232
1233 button = wx.Button(self, -1, str_to_gui("Final"))
1234 button.SetToolTipString("The final run of the protocol. Please click on the 'About' button for more information.")
1235 button.SetFont(font.normal)
1236 sub_sizer.Add(button, 1, wx.EXPAND, 0)
1237 self.Bind(wx.EVT_BUTTON, self.select_final, button)
1238
1239
1240 sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0)
1241
1242
1244 """The ellipsoid global model has been selected.
1245
1246 @keyword event: The wx event.
1247 @type event: wx event
1248 """
1249
1250
1251 self.select = 'ellipsoid'
1252
1253
1254 self.Close()
1255
1256
1258 """The final stage of the protocol has been selected.
1259
1260 @keyword event: The wx event.
1261 @type event: wx event
1262 """
1263
1264
1265 self.select = 'final'
1266
1267
1268 self.Close()
1269
1270
1272 """The full analysis has been selected.
1273
1274 @keyword event: The wx event.
1275 @type event: wx event
1276 """
1277
1278
1279 self.select = 'Fully automated'
1280
1281
1282 self.Close()
1283
1284
1286 """The local_tm global model has been selected.
1287
1288 @keyword event: The wx event.
1289 @type event: wx event
1290 """
1291
1292
1293 self.select = 'local_tm'
1294
1295
1296 self.Close()
1297
1298
1300 """The prolate global model has been selected.
1301
1302 @keyword event: The wx event.
1303 @type event: wx event
1304 """
1305
1306
1307 self.select = 'prolate'
1308
1309
1310 self.Close()
1311
1312
1314 """The oblate global model has been selected.
1315
1316 @keyword event: The wx event.
1317 @type event: wx event
1318 """
1319
1320
1321 self.select = 'oblate'
1322
1323
1324 self.Close()
1325
1326
1328 """The sphere global model has been selected.
1329
1330 @keyword event: The wx event.
1331 @type event: wx event
1332 """
1333
1334
1335 self.select = 'sphere'
1336
1337
1338 self.Close()
1339