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 relaxation dispersion analysis."""
26
27
28 import wx
29
30
31 from auto_analyses.relax_disp import Relax_disp
32 from data_store import Relax_data_store; ds = Relax_data_store()
33 from graphics import ANALYSIS_IMAGE_PATH, fetch_icon
34 from gui.analyses.base import Base_analysis
35 from gui.analyses.elements.bool_element import Boolean_ctrl
36 from gui.analyses.elements.float_element import Float_ctrl
37 from gui.analyses.elements.spin_element import Spin_ctrl
38 from gui.analyses.elements.text_element import Text_ctrl
39 from gui.analyses.elements.model_list import Model_list
40 from gui.analyses.execute import Execute
41 from gui.base_classes import Container
42 from gui.components.spectrum import Spectra_list
43 from gui.filedialog import RelaxDirDialog
44 from gui.fonts import font
45 from gui.message import error_message, Missing_data
46 from gui.string_conv import float_to_gui, gui_to_float, gui_to_int, gui_to_str, str_to_gui
47 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
48 from gui.wizards.peak_intensity import Peak_intensity_wizard
49 from lib.dispersion.variables import MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_CPMG, MODEL_LIST_R1RHO, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_MMQ_CR72, MODEL_MP05, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_MMQ_2SITE, MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_2SITE, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR, MODEL_R2EFF, MODEL_TAP03, MODEL_TP02, MODEL_TSMFK01
50 from lib.text.gui import dw, dw_AB, dw_BC, dwH, dwH_AB, dwH_BC, i0, kex, kAB, kBC, kAC, padw2, phi_ex, phi_exB, phi_exC, r1, r1rho, r1rho_prime, r1, r2, r2a, r2b, r2eff
51 from pipe_control.mol_res_spin import exists_mol_res_spin_data, spin_loop
52 from pipe_control.pipes import has_bundle, has_pipe
53 from specific_analyses.relax_disp.data import has_cpmg_exp_type, has_r1rho_exp_type
54 from status import Status; status = Status()
55
56
57 default_grid_inc = 21
58 default_exp_mc_sim_num = 500
59 default_mc_sim_num = 500
60
61
63 """The relaxation dispersion auto-analysis GUI element."""
64
65
66 analysis_type = None
67 bitmap = ANALYSIS_IMAGE_PATH+"relax_disp_200x200.png"
68 label = 'Relax-disp'
69
70 - 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, uf_exec=[], data_index=None):
71 """Build the automatic R1 and R2 analysis GUI frame elements.
72
73 @param parent: The parent wx element.
74 @type parent: wx object
75 @keyword id: The unique ID number.
76 @type id: int
77 @keyword pos: The position.
78 @type pos: wx.Size object
79 @keyword size: The size.
80 @type size: wx.Size object
81 @keyword style: The style.
82 @type style: int
83 @keyword name: The name for the panel.
84 @type name: unicode
85 @keyword gui: The main GUI class.
86 @type gui: gui.relax_gui.Main instance
87 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook).
88 @type analysis_name: str
89 @keyword pipe_name: The name of the data pipe associated with this analysis.
90 @type pipe_name: str
91 @keyword pipe_bundle: The name of the data pipe bundle associated with this analysis.
92 @type pipe_bundle: str
93 @keyword uf_exec: The list of user function on_execute methods returned from the new analysis wizard.
94 @type uf_exec: list of methods
95 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists).
96 @type data_index: None or int
97 """
98
99
100 self.gui = gui
101
102
103 self.init_flag = True
104
105
106 if data_index == None:
107
108 if not has_pipe(pipe_name):
109 self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='relax_disp', bundle=pipe_bundle)
110
111
112 if not has_bundle(pipe_bundle):
113 self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name)
114
115
116 data_index = ds.relax_gui.analyses.add(self.label)
117
118
119 ds.relax_gui.analyses[data_index].analysis_name = analysis_name
120 ds.relax_gui.analyses[data_index].pipe_name = pipe_name
121 ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle
122
123
124 ds.relax_gui.analyses[data_index].r1_fit = False
125 ds.relax_gui.analyses[data_index].numeric_only = False
126 ds.relax_gui.analyses[data_index].grid_inc = None
127 ds.relax_gui.analyses[data_index].mc_sim_num = None
128 ds.relax_gui.analyses[data_index].exp_mc_sim_num = None
129 ds.relax_gui.analyses[data_index].pre_run_dir = None
130 ds.relax_gui.analyses[data_index].mc_sim_all_models = False
131 ds.relax_gui.analyses[data_index].insignificance = 1.0
132 ds.relax_gui.analyses[data_index].save_dir = self.gui.system_cwd_path
133
134
135 ds.relax_gui.analyses[data_index].disp_models = [
136 MODEL_R2EFF,
137 MODEL_NOREX,
138 MODEL_CR72,
139 MODEL_NS_CPMG_2SITE_EXPANDED,
140 MODEL_MP05,
141 MODEL_NS_R1RHO_2SITE
142 ]
143
144
145 if ds.relax_gui.analyses[data_index].pipe_bundle == None:
146 raise RelaxError("The pipe bundle must be supplied.")
147
148
149 self.data = ds.relax_gui.analyses[data_index]
150 self.data_index = data_index
151
152
153 self.observer_register()
154
155
156 super(Auto_relax_disp, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
157
158
159 self.opt_func_tol = 1e-25
160 self.opt_max_iterations = int(1e7)
161
162
163 self.update_clusters()
164
165
167 """Activate or deactivate certain elements of the analysis in response to the execution lock."""
168
169
170 enable = False
171 if not status.exec_lock.locked():
172 enable = True
173
174
175 wx.CallAfter(self.field_results_dir.Enable, enable)
176 wx.CallAfter(self.field_pre_run_dir.Enable, enable)
177 wx.CallAfter(self.spin_systems.Enable, enable)
178 wx.CallAfter(self.field_cluster.Enable, enable)
179 wx.CallAfter(self.button_isotope.Enable, enable)
180 wx.CallAfter(self.button_r1.Enable, enable)
181 wx.CallAfter(self.button_chemical_shift.Enable, enable)
182 wx.CallAfter(self.button_interatom_define.Enable, enable)
183 wx.CallAfter(self.peak_intensity.Enable, enable)
184 wx.CallAfter(self.model_field.Enable, enable)
185 wx.CallAfter(self.button_exec_relax.Enable, enable)
186
187
246
247
249 """Assemble the data required for the Auto_noe class.
250
251 @return: A container with all the data required for the auto-analysis, the missing list, and a list of models that don't match the experiment types.
252 @rtype: class instance, list of str, list of str
253 """
254
255
256 data = Container()
257 missing = []
258 model_mismatch = []
259
260
261 data.pipe_name = self.data.pipe_name
262 data.pipe_bundle = self.data.pipe_bundle
263
264
265 data.save_dir = self.data.save_dir
266 data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue())
267
268
269 if not exists_mol_res_spin_data():
270 missing.append("Sequence data")
271
272
273 for spin, spin_id in spin_loop(return_id=True, skip_desel=True):
274
275 msg = "Spin '%s' - %s (try the %s user function)." % (spin_id, "%s", "%s")
276
277
278 if not hasattr(spin, 'isotope') or spin.isotope == None:
279 missing.append(msg % ("nuclear isotope data", "spin.isotope"))
280
281
282 if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 2:
283 missing.append("Spectral data")
284
285
286 data.models = self.model_field.GetValue()
287
288
289 for model in data.models:
290
291 if model != MODEL_NOREX and model in MODEL_LIST_CPMG and not has_cpmg_exp_type():
292 model_mismatch.append([model, 'CPMG'])
293
294
295 if model != MODEL_NOREX and model in MODEL_LIST_R1RHO and not has_r1rho_exp_type():
296 model_mismatch.append([model, 'R1rho'])
297
298
299 data.r1_fit = self.r1_fit.GetValue()
300
301
302 data.numeric_only = self.numeric_only.GetValue()
303
304
305 data.inc = gui_to_int(self.grid_inc.GetValue())
306
307
308 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
309 data.exp_mc_sim_num = gui_to_int(self.exp_mc_sim_num.GetValue())
310 data.mc_sim_all_models = self.mc_sim_all_models.GetValue()
311
312
313 data.insignificance = self.insignificance.GetValue()
314 try:
315 data.insignificance = gui_to_float(data.insignificance)
316 except:
317 missing.append("The insignificance level must be a number.")
318
319
320 data.opt_func_tol = self.opt_func_tol
321 data.opt_max_iterations = self.opt_max_iterations
322
323
324 return data, missing, model_mismatch
325
326
328 """Construct the right hand box to pack into the main relax_disp box.
329
330 @return: The right hand box element containing all relaxation dispersion GUI elements (excluding the bitmap) to pack into the main box.
331 @rtype: wx.BoxSizer instance
332 """
333
334
335 box = wx.BoxSizer(wx.VERTICAL)
336
337
338 self.add_title(box, "Relaxation dispersion analysis")
339
340
341 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)
342
343
344 self.field_results_dir = Text_ctrl(box, self, text="Results directory:", icon=fetch_icon('oxygen.actions.document-open-folder', "16x16"), default=self.data.save_dir, tooltip="The directory in which all automatically created files will be saved.", tooltip_button="Select the results directory.", fn=self.results_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
345
346
347 tooltip = "The optional directory containing the dispersion auto-analysis results from a previous run. The optimised parameters from these previous results will be used as the starting point for optimisation rather than performing a grid search. This is essential for when large spin clusters are specified, as a grid search becomes prohibitively expensive with clusters of three or more spins. At some point a RelaxError will occur because the grid search is impossibly large. For the cluster specific parameters, i.e. the populations of the states and the exchange parameters, an average value will be used as the starting point. For all other parameters, the R20 values for each spin and magnetic field, as well as the parameters related to the chemical shift difference dw, the optimised values of the previous run will be directly copied."
348 self.field_pre_run_dir = Text_ctrl(box, self, text="Previous run directory:", icon=fetch_icon('oxygen.actions.document-open-folder', "16x16"), tooltip=tooltip, tooltip_button="Select the results directory of the previous run.", fn=self.pre_run_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
349
350
351 self.add_spin_systems(box, self)
352
353
354 self.field_cluster = Text_ctrl(box, self, text="Spin cluster IDs:", button_text=" Cluster", icon=fetch_icon("relax.cluster", "16x16"), tooltip="The list of currently defined spin clusters. A spin cluster will share the same the dispersion parameters during the optimisation of the dispersion model. The special 'free spins' cluster ID refers to all non-clustered spins.", tooltip_button="Define clusters of spins using the relax_disp.cluster user function.", fn=self.relax_disp_cluster, button=True, editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
355
356
357 box.AddSpacer(20)
358 self.add_buttons(box=box)
359
360
361 box.AddSpacer(20)
362 self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard_launch, relax_disp_flag=True)
363 box.AddSpacer(10)
364
365
366 self.model_field = Disp_model_list(self, box)
367 self.model_field.set_value(self.data.disp_models)
368
369
370 tooltip = "Toggle the optimisation of the off-resonance R1 parameter.\n\nThis allows the optimisation of R1 values to be turned on an off for the relaxation dispersion dispersion models. If turned off, the current values of R1 will be fixed. Otherwise the R1 values will be added to the model parameter set. For models which do not support the R1 parameter for off-resonance effects, this setting will have no effect."
371 self.r1_fit = Boolean_ctrl(box, self, text="R1 parameter optimisation:", default=False, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
372
373
374 tooltip = "The class of models to use in the final model selection.\n\nThe default of False allows all dispersion models to be compared for statistical significance in the analysis (no exchange, the analytic models and the numeric models). The value of True will activate a pure numeric solution - the analytic models will be optimised, as they are very useful for replacing the grid search for the numeric models, but the final model selection will not include them."
375 self.numeric_only = Boolean_ctrl(box, self, text="Pure numeric solutions:", default=False, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
376
377
378 self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=default_grid_inc, 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)
379
380
381 self.exp_mc_sim_num = Spin_ctrl(box, self, text="Exponential curve error analysis:", default=default_exp_mc_sim_num, min=-1, max=100000, tooltip="This is the number of Monte Carlo simulations performed for error propagation and analysis when estimating R2eff errors from exponential curve fitting. Setting to '-1' estimates error from the Covariance matrix.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
382 self.mc_sim_num = Spin_ctrl(box, self, text="Monte Carlo simulation number:", default=default_mc_sim_num, min=1, max=100000, tooltip="This is the number of Monte Carlo simulations performed for error propagation and analysis. For best results, at least 500 is recommended.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
383 self.mc_sim_all_models = Boolean_ctrl(box, self, text="Per model error analysis:", default=False, tooltip="A flag which if True will cause Monte Carlo simulations to be performed for each individual model. Otherwise Monte Carlo simulations will be reserved for the final model.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
384
385
386 tooltip = "Experimental option, be careful. True will set the grid %s values from the minimum %s values. This will speed up the grid search with a factor GRID_INC^(Nr_spec_freq). For a CPMG experiment with two fields and standard GRID_INC=21, the speed-up is a factor 441." % (r2, r2eff)
387 self.set_grid_r20 = Boolean_ctrl(box, self, text="Set R20 to the minimum R2eff:", default=False, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
388
389
390 tooltip = "The %s/%s value in rad/s by which to judge insignificance. If the maximum difference between two points on all dispersion curves for a spin is less than this value, that spin will be deselected. This does not affect the '%s' model. Set this value to 0.0 to use all data." % (r2eff, r1rho, MODEL_NOREX)
391 self.insignificance = Float_ctrl(box, self, text="Insignificance level:", default=1.0, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
392
393
394 box.AddSpacer(30)
395 box.AddStretchSpacer()
396
397
398 self.button_exec_relax = self.add_execute_analysis(box, self.execute)
399
400
401 return box
402
403
405 """Unregister the spin count from the user functions."""
406
407
408 self.observer_register(remove=True)
409
410
411 self.peak_intensity.delete()
412
413
414 if hasattr(self, 'peak_wizard'):
415 self.peak_wizard.Destroy()
416 del self.peak_wizard
417
418
419 self.model_field.model_win.Destroy()
420 del self.model_field
421
422
423 if hasattr(self, 'missing_data'):
424 self.missing_data.Destroy()
425 del self.missing_data
426
427
429 """Set up, execute, and process the automatic Rx analysis.
430
431 @param event: The wx event.
432 @type event: wx event
433 """
434
435
436 self.gui.interpreter.flush()
437
438
439 if status.exec_lock.locked():
440 error_message("relax is currently executing.", "relax execution lock")
441 event.Skip()
442 return
443
444
445 self.gui.close_windows()
446
447
448 self.sync_ds(upload=True)
449
450
451 data, missing, model_mismatch = self.assemble_data()
452
453
454 if len(missing):
455 self.missing_data = Missing_data(missing)
456 return
457
458
459 if len(model_mismatch):
460
461 text = ''
462 for model, exp in model_mismatch:
463 text += "The '%s' %s model cannot be used as no %s experiment types have been set up.\n" % (model, exp, exp)
464
465
466 error_message(text, caption='Model mismatch')
467 return
468
469
470 self.gui.show_controller(None)
471 self.gui.controller.log_panel.on_goto_end(None)
472
473
474 self.thread = Execute_relax_disp(self.gui, data, self.data_index)
475 self.thread.start()
476
477
478 event.Skip()
479
480
482 """Define the interatomic interactions of the spins via the interatom.define user function.
483
484 @keyword event: The wx event.
485 @type event: wx event
486 """
487
488
489 uf_store['interatom.define'](wx_wizard_modal=True, spin_id1='@N', spin_id2='@H')
490
491
493 """Read chemical shift data from a peak list via the chemical_shift.read user function.
494
495 @keyword event: The wx event.
496 @type event: wx event
497 """
498
499
500 uf_store['chemical_shift.read'](wx_wizard_modal=True)
501
502
504 """Load R1 relaxation data via the relax_data.read user function.
505
506 @keyword event: The wx event.
507 @type event: wx event
508 """
509
510
511 uf_store['relax_data.read'](wx_wizard_modal=True, ri_type='R1')
512
513
537
538
540 """Launch the peak loading wizard.
541
542 @param event: The wx event.
543 @type event: wx event
544 """
545
546
547 if hasattr(self, 'peak_wizard'):
548 self.peak_wizard.Destroy()
549
550
551 self.peak_wizard = Peak_intensity_wizard(relax_disp=True)
552
553
555 """The pre-run directory selection.
556
557 @param event: The wx event.
558 @type event: wx event
559 """
560
561
562 dialog = RelaxDirDialog(parent=self, message='Select the directory of the previous run', defaultPath=self.field_pre_run_dir.GetValue())
563
564
565 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
566
567 return
568
569
570 path = gui_to_str(dialog.get_path())
571 if not path:
572 return
573
574
575 self.field_pre_run_dir.SetValue(str_to_gui(path))
576
577
579 """Set up spin clustering via the relax_disp.cluster user function.
580
581 @keyword event: The wx event.
582 @type event: wx event
583 """
584
585
586 uf_store['relax_disp.cluster'](wx_wizard_modal=True)
587
588
590 """The results directory selection.
591
592 @param event: The wx event.
593 @type event: wx event
594 """
595
596
597 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue())
598
599
600 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
601
602 return
603
604
605 path = gui_to_str(dialog.get_path())
606 if not path:
607 return
608
609
610 self.data.save_dir = path
611
612
613 self.field_results_dir.SetValue(str_to_gui(path))
614
615
617 """Set the nuclear isotope types of the spins via the spin.isotope user function.
618
619 @keyword event: The wx event.
620 @type event: wx event
621 """
622
623
624 uf_store['spin.isotope'](wx_wizard_modal=True, isotope='15N', spin_id='@N*')
625
626
628 """Synchronise the analysis frame and the relax data store, both ways.
629
630 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.
631
632 @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.
633 @type upload: bool
634 """
635
636
637 if upload:
638 self.data.r1_fit = self.r1_fit.GetValue()
639 elif hasattr(self.data, 'r1_fit'):
640 self.r1_fit.SetValue(bool(self.data.r1_fit))
641
642
643 if upload:
644 self.data.numeric_only = self.numeric_only.GetValue()
645 elif hasattr(self.data, 'numeric_only'):
646 self.numeric_only.SetValue(bool(self.data.numeric_only))
647
648
649 if upload:
650 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue())
651 elif hasattr(self.data, 'grid_inc'):
652 if self.data.grid_inc == None:
653 self.data.grid_inc = default_grid_inc
654 self.grid_inc.SetValue(int(self.data.grid_inc))
655
656
657 if upload:
658 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
659 elif hasattr(self.data, 'mc_sim_num'):
660 if self.data.mc_sim_num == None:
661 self.data.mc_sim_num = default_mc_sim_num
662 self.mc_sim_num.SetValue(int(self.data.mc_sim_num))
663
664
665 if upload:
666 self.data.exp_mc_sim_num = gui_to_int(self.exp_mc_sim_num.GetValue())
667 elif hasattr(self.data, 'exp_mc_sim_num'):
668 if self.data.exp_mc_sim_num == None:
669 self.data.exp_mc_sim_num = default_exp_mc_sim_num
670 self.exp_mc_sim_num.SetValue(int(self.data.exp_mc_sim_num))
671
672
673 if upload:
674 self.data.mc_sim_all_models = self.mc_sim_all_models.GetValue()
675 elif hasattr(self.data, 'mc_sim_all_models'):
676 self.mc_sim_all_models.SetValue(bool(self.data.mc_sim_all_models))
677
678
679 if upload:
680 self.data.insignificance = self.insignificance.GetValue()
681 try:
682 self.data.insignificance = gui_to_float(self.data.insignificance)
683 except:
684 pass
685 elif hasattr(self.data, 'insignificance'):
686 self.insignificance.SetValue(float_to_gui(self.data.insignificance))
687
688
689 if upload:
690 self.data.save_dir = gui_to_str(self.field_results_dir.GetValue())
691 else:
692 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir))
693
694
695 if upload:
696 self.data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue())
697 elif hasattr(self.data, 'pre_run_dir'):
698 self.field_pre_run_dir.SetValue(str_to_gui(self.data.pre_run_dir))
699
700
701 if upload:
702 self.data.disp_models = self.model_field.GetValue()
703 else:
704 self.model_field.set_value(self.data.disp_models)
705
706
708 """Update the cluster field."""
709
710
711 cluster_keys = []
712 if hasattr(cdp, 'clustering'):
713 cluster_keys = sorted(cdp.clustering.keys())
714
715
716 if not len(cluster_keys):
717 wx.CallAfter(self.field_cluster.SetValue, "free spins")
718
719
720 else:
721
722 text = ""
723 if "free spins" in cluster_keys:
724 text += "free spins"
725 for i in range(len(cluster_keys)):
726 if cluster_keys[i] != "free spins":
727 text += ", %s" % cluster_keys[i]
728
729
730 wx.CallAfter(self.field_cluster.SetValue, text)
731
732
734 """Launch the value.set user function.
735
736 @keyword event: The wx event.
737 @type event: wx event
738 """
739
740
741 uf_store['value.set'](wx_wizard_modal=True)
742
743
744
746 """The relaxation dispersion analysis execution object."""
747
749 """Execute the calculation."""
750
751
752 Relax_disp.opt_func_tol = self.data.opt_func_tol
753 Relax_disp.opt_max_iterations = self.data.opt_max_iterations
754
755
756 Relax_disp(pipe_name=self.data.pipe_name, pipe_bundle=self.data.pipe_bundle, results_dir=self.data.save_dir, models=self.data.models, grid_inc=self.data.inc, mc_sim_num=self.data.mc_sim_num, exp_mc_sim_num=self.data.exp_mc_sim_num, pre_run_dir=self.data.pre_run_dir, mc_sim_all_models=self.data.mc_sim_all_models, insignificance=self.data.insignificance, numeric_only=self.data.numeric_only, r1_fit=self.data.r1_fit)
757
758
759 data = ds.relax_gui.analyses[self.data_index]
760
761
762
764 """The diffusion model list GUI element."""
765
766
767 desc = "Relaxation dispersion models:"
768 models = [
769 MODEL_R2EFF,
770 None,
771 MODEL_NOREX,
772 None,
773 MODEL_LM63,
774 MODEL_LM63_3SITE,
775 MODEL_CR72,
776 MODEL_CR72_FULL,
777 MODEL_IT99,
778 MODEL_TSMFK01,
779 MODEL_B14,
780 MODEL_B14_FULL,
781 MODEL_NS_CPMG_2SITE_EXPANDED,
782 MODEL_NS_CPMG_2SITE_3D,
783 MODEL_NS_CPMG_2SITE_3D_FULL,
784 MODEL_NS_CPMG_2SITE_STAR,
785 MODEL_NS_CPMG_2SITE_STAR_FULL,
786 None,
787 MODEL_M61,
788 MODEL_M61B,
789 MODEL_DPL94,
790 MODEL_TP02,
791 MODEL_TAP03,
792 MODEL_MP05,
793 MODEL_NS_R1RHO_2SITE,
794 MODEL_NS_R1RHO_3SITE_LINEAR,
795 MODEL_NS_R1RHO_3SITE,
796 None,
797 MODEL_MMQ_CR72,
798 MODEL_NS_MMQ_2SITE,
799 MODEL_NS_MMQ_3SITE_LINEAR,
800 MODEL_NS_MMQ_3SITE
801 ]
802 params = [
803 "{%s/%s, %s}" % (r2eff, r1rho, i0),
804 None,
805 "{%s, ...}" % (r2),
806 None,
807 "{%s, ..., %s, %s}" % (r2, phi_ex, kex),
808 "{%s, ..., %s, kB, %s, kC}" % (r2, phi_exB, phi_exC),
809 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
810 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
811 "{%s, ..., %s, %s, %s}" % (r2, phi_ex, padw2, kex),
812 "{%s, ..., %s, k_AB}" % (r2a, dw),
813 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
814 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
815 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
816 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
817 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
818 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
819 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
820 None,
821 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex),
822 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
823 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex),
824 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
825 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
826 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
827 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
828 "{%s, ..., pA, %s, %s, pB, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC),
829 "{%s, ..., pA, %s, %s, pB, %s, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC, kAC),
830 None,
831 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex),
832 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex),
833 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC),
834 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC, kAC)
835 ]
836 model_desc = [
837 "The base model for determining the %s/%s values and errors for all other models." % (r2eff, r1rho),
838 None,
839 "The model for no chemical exchange relaxation.",
840 None,
841 "The original Luz and Meiboom (1963) 2-site fast exchange equation.",
842 "The original Luz and Meiboom (1963) 3-site fast exchange equation.",
843 "The Carver and Richards (1972) 2-site equation for all time scales (with %s = %s)." % (r2a, r2b),
844 "The Carver and Richards (1972) 2-site equation for all time scales.",
845 "The Ishima and Torchia (1999) 2-site model for all time scales with pA >> pB.",
846 "The Tollinger et al. (2001) 2-site very-slow exchange model.",
847 "The Baldwin (2014) 2-site exact solution model for all time scales (with %s = %s)." % (r2a, r2b),
848 "The Baldwin (2014) 2-site exact solution model for all time scales.",
849 "The 2-site numerical solution expanded using Maple by Nikolai Skrynnikov.",
850 "The 2-site numerical solution using 3D magnetisation vectors (with %s = %s)." % (r2a, r2b),
851 "The 2-site numerical solution using 3D magnetisation vectors.",
852 "The 2-site numerical solution using complex conjugate matrices (with %s = %s)." % (r2a, r2b),
853 "The 2-site numerical solution using complex conjugate matrices.",
854 None,
855 "The Meiboom (1961) 2-site fast exchange equation.",
856 "The Meiboom (1961) 2-site equation for all time scales with pA >> pB.",
857 "The Davis, Perlman and London (1994) 2-site fast exchange equation.",
858 "The Trott and Palmer (2002) 2-site equation for all time scales.",
859 "The Trott, Abergel and Palmer (2003) off-resonance 2-site equation for all time scales.",
860 "The Miloushev and Palmer (2005) off-resonance 2-site equation for all time scales.",
861 "The 2-site numerical solution using 3D magnetisation vectors.",
862 "The 3-site linearised numerical solution using 3D magnetisation vectors.",
863 "The 3-site numerical solution using 3D magnetisation vectors.",
864 None,
865 "The CR72 2-site model extended to MMQ CPMG data by Korzhnev et al., 2004.",
866 "The 2-site numerical solution of Korzhnev et al. (2004) from multi-quantum CPMG data.",
867 "The 3-site linearised numerical solution of Korzhnev et al. (2005) for MMQ CPMG data.",
868 "The 3-site numerical solution of Korzhnev et al. (2005) for MMQ CPMG data."
869 ]
870 size = wx.Size(1024, 750)
871 tooltip = "The list of all relaxation dispersion models to be optimised as part of the protocol."
872 tooltip_button = "Open the model list selector window."
873