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