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