1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for the automatic relaxation dispersion analysis."""
24
25
26 import wx
27
28
29 from auto_analyses.relax_disp import Relax_disp
30 from data_store import Relax_data_store; ds = Relax_data_store()
31 from graphics import ANALYSIS_IMAGE_PATH, fetch_icon
32 from gui.analyses.base import Base_analysis
33 from gui.analyses.elements.bool_element import Boolean_ctrl
34 from gui.analyses.elements.float_element import Float_ctrl
35 from gui.analyses.elements.spin_element import Spin_ctrl
36 from gui.analyses.elements.text_element import Text_ctrl
37 from gui.analyses.elements.model_list import Model_list
38 from gui.analyses.execute import Execute
39 from gui.base_classes import Container
40 from gui.components.spectrum import Spectra_list
41 from gui.filedialog import RelaxDirDialog
42 from gui.fonts import font
43 from gui.message import error_message, Missing_data
44 from gui.string_conv import float_to_gui, gui_to_bool, gui_to_float, gui_to_int, gui_to_str, str_to_gui
45 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
46 from gui.wizards.peak_intensity import Peak_intensity_wizard
47 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, r2, r2a, r2b, r2eff
48 from pipe_control.mol_res_spin import exists_mol_res_spin_data, spin_loop
49 from pipe_control.pipes import has_bundle, has_pipe
50 from specific_analyses.relax_disp.disp_data import has_cpmg_exp_type, has_r1rho_exp_type
51 from specific_analyses.relax_disp.variables import 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
52 from status import Status; status = Status()
53
54
56 """The relaxation dispersion auto-analysis GUI element."""
57
58
59 analysis_type = None
60 bitmap = ANALYSIS_IMAGE_PATH+"relax_disp_200x200.png"
61 label = 'Relax-disp'
62
63 - 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):
64 """Build the automatic R1 and R2 analysis GUI frame elements.
65
66 @param parent: The parent wx element.
67 @type parent: wx object
68 @keyword id: The unique ID number.
69 @type id: int
70 @keyword pos: The position.
71 @type pos: wx.Size object
72 @keyword size: The size.
73 @type size: wx.Size object
74 @keyword style: The style.
75 @type style: int
76 @keyword name: The name for the panel.
77 @type name: unicode
78 @keyword gui: The main GUI class.
79 @type gui: gui.relax_gui.Main instance
80 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook).
81 @type analysis_name: str
82 @keyword pipe_name: The name of the data pipe associated with this analysis.
83 @type pipe_name: str
84 @keyword pipe_bundle: The name of the data pipe bundle associated with this analysis.
85 @type pipe_bundle: str
86 @keyword uf_exec: The list of user function on_execute methods returned from the new analysis wizard.
87 @type uf_exec: list of methods
88 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists).
89 @type data_index: None or int
90 """
91
92
93 self.gui = gui
94
95
96 self.init_flag = True
97
98
99 if data_index == None:
100
101 if not has_pipe(pipe_name):
102 self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='relax_disp', bundle=pipe_bundle)
103
104
105 if not has_bundle(pipe_bundle):
106 self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name)
107
108
109 data_index = ds.relax_gui.analyses.add(self.label)
110
111
112 ds.relax_gui.analyses[data_index].analysis_name = analysis_name
113 ds.relax_gui.analyses[data_index].pipe_name = pipe_name
114 ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle
115
116
117 ds.relax_gui.analyses[data_index].numeric_only = False
118 ds.relax_gui.analyses[data_index].grid_inc = None
119 ds.relax_gui.analyses[data_index].mc_sim_num = None
120 ds.relax_gui.analyses[data_index].pre_run_dir = None
121 ds.relax_gui.analyses[data_index].mc_sim_all_models = False
122 ds.relax_gui.analyses[data_index].insignificance = 1.0
123 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir
124
125
126 ds.relax_gui.analyses[data_index].disp_models = [
127 MODEL_R2EFF,
128 MODEL_NOREX,
129 MODEL_CR72,
130 MODEL_NS_CPMG_2SITE_EXPANDED,
131 MODEL_MP05,
132 MODEL_NS_R1RHO_2SITE
133 ]
134
135
136 if ds.relax_gui.analyses[data_index].pipe_bundle == None:
137 raise RelaxError("The pipe bundle must be supplied.")
138
139
140 self.data = ds.relax_gui.analyses[data_index]
141 self.data_index = data_index
142
143
144 self.observer_register()
145
146
147 super(Auto_relax_disp, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
148
149
150 self.opt_func_tol = 1e-25
151 self.opt_max_iterations = int(1e7)
152
153
154 self.update_clusters()
155
156
158 """Activate or deactivate certain elements of the analysis in response to the execution lock."""
159
160
161 enable = False
162 if not status.exec_lock.locked():
163 enable = True
164
165
166 wx.CallAfter(self.field_results_dir.Enable, enable)
167 wx.CallAfter(self.field_pre_run_dir.Enable, enable)
168 wx.CallAfter(self.spin_systems.Enable, enable)
169 wx.CallAfter(self.field_cluster.Enable, enable)
170 wx.CallAfter(self.button_isotope.Enable, enable)
171 wx.CallAfter(self.button_r1.Enable, enable)
172 wx.CallAfter(self.button_chemical_shift.Enable, enable)
173 wx.CallAfter(self.button_interatom_define.Enable, enable)
174 wx.CallAfter(self.peak_intensity.Enable, enable)
175 wx.CallAfter(self.model_field.Enable, enable)
176 wx.CallAfter(self.button_exec_relax.Enable, enable)
177
178
237
238
240 """Assemble the data required for the Auto_noe class.
241
242 @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.
243 @rtype: class instance, list of str, list of str
244 """
245
246
247 data = Container()
248 missing = []
249 model_mismatch = []
250
251
252 data.pipe_name = self.data.pipe_name
253 data.pipe_bundle = self.data.pipe_bundle
254
255
256 data.save_dir = self.data.save_dir
257 data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue())
258
259
260 if not exists_mol_res_spin_data():
261 missing.append("Sequence data")
262
263
264 for spin, spin_id in spin_loop(return_id=True, skip_desel=True):
265
266 msg = "Spin '%s' - %s (try the %s user function)." % (spin_id, "%s", "%s")
267
268
269 if not hasattr(spin, 'isotope') or spin.isotope == None:
270 missing.append(msg % ("nuclear isotope data", "spin.isotope"))
271
272
273 if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 2:
274 missing.append("Spectral data")
275
276
277 data.models = self.model_field.GetValue()
278
279
280 for model in data.models:
281
282 if model != MODEL_NOREX and model in MODEL_LIST_CPMG and not has_cpmg_exp_type():
283 model_mismatch.append([model, 'CPMG'])
284
285
286 if model != MODEL_NOREX and model in MODEL_LIST_R1RHO and not has_r1rho_exp_type():
287 model_mismatch.append([model, 'R1rho'])
288
289
290 data.numeric_only = self.numeric_only.GetValue()
291
292
293 data.inc = gui_to_int(self.grid_inc.GetValue())
294
295
296 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
297 data.mc_sim_all_models = self.mc_sim_all_models.GetValue()
298
299
300 data.insignificance = self.insignificance.GetValue()
301 try:
302 data.insignificance = gui_to_float(data.insignificance)
303 except:
304 missing.append("The insignificance level must be a number.")
305
306
307 data.opt_func_tol = self.opt_func_tol
308 data.opt_max_iterations = self.opt_max_iterations
309
310
311 return data, missing, model_mismatch
312
313
315 """Construct the right hand box to pack into the main relax_disp box.
316
317 @return: The right hand box element containing all relaxation dispersion GUI elements (excluding the bitmap) to pack into the main box.
318 @rtype: wx.BoxSizer instance
319 """
320
321
322 box = wx.BoxSizer(wx.VERTICAL)
323
324
325 self.add_title(box, "Relaxation dispersion analysis")
326
327
328 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)
329
330
331 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)
332
333
334 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."
335 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)
336
337
338 self.add_spin_systems(box, self)
339
340
341 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)
342
343
344 box.AddSpacer(20)
345 self.add_buttons(box=box)
346
347
348 box.AddSpacer(20)
349 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)
350 box.AddSpacer(10)
351
352
353 self.model_field = Disp_model_list(self, box)
354 self.model_field.set_value(self.data.disp_models)
355
356
357 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."
358 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)
359
360
361 self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=21, 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)
362
363
364 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. For best results, at least 500 is recommended.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
365 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)
366
367
368 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)
369 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)
370
371
372 box.AddSpacer(30)
373 box.AddStretchSpacer()
374
375
376 self.button_exec_relax = self.add_execute_analysis(box, self.execute)
377
378
379 return box
380
381
390
391
393 """Set up, execute, and process the automatic Rx analysis.
394
395 @param event: The wx event.
396 @type event: wx event
397 """
398
399
400 self.gui.interpreter.flush()
401
402
403 if status.exec_lock.locked():
404 error_message("relax is currently executing.", "relax execution lock")
405 event.Skip()
406 return
407
408
409 self.gui.close_windows()
410
411
412 self.sync_ds(upload=True)
413
414
415 data, missing, model_mismatch = self.assemble_data()
416
417
418 if len(missing):
419 Missing_data(missing)
420 return
421
422
423 if len(model_mismatch):
424
425 text = ''
426 for model, exp in model_mismatch:
427 text += "The '%s' %s model cannot be used as no %s experiment types have been set up.\n" % (model, exp, exp)
428
429
430 error_message(text, caption='Model mismatch')
431 return
432
433
434 self.gui.show_controller(None)
435 self.gui.controller.log_panel.on_goto_end(None)
436
437
438 self.thread = Execute_relax_disp(self.gui, data, self.data_index)
439 self.thread.start()
440
441
442 event.Skip()
443
444
446 """Define the interatomic interactions of the spins via the interatom.define user function.
447
448 @keyword event: The wx event.
449 @type event: wx event
450 """
451
452
453 uf_store['interatom.define'](wx_wizard_modal=True, spin_id1='@N', spin_id2='@H')
454
455
457 """Read chemical shift data from a peak list via the chemical_shift.read user function.
458
459 @keyword event: The wx event.
460 @type event: wx event
461 """
462
463
464 uf_store['chemical_shift.read'](wx_wizard_modal=True)
465
466
468 """Load R1 relaxation data via the relax_data.read user function.
469
470 @keyword event: The wx event.
471 @type event: wx event
472 """
473
474
475 uf_store['relax_data.read'](wx_wizard_modal=True, ri_type='R1')
476
477
501
502
504 """Launch the peak loading wizard.
505
506 @param event: The wx event.
507 @type event: wx event
508 """
509
510
511 self.peak_wizard = Peak_intensity_wizard(relax_disp=True)
512
513
515 """The pre-run directory selection.
516
517 @param event: The wx event.
518 @type event: wx event
519 """
520
521
522 dialog = RelaxDirDialog(parent=self, message='Select the directory of the previous run', defaultPath=self.field_pre_run_dir.GetValue())
523
524
525 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
526
527 return
528
529
530 path = gui_to_str(dialog.get_path())
531 if not path:
532 return
533
534
535 self.field_pre_run_dir.SetValue(str_to_gui(path))
536
537
539 """Set up spin clustering via the relax_disp.cluster user function.
540
541 @keyword event: The wx event.
542 @type event: wx event
543 """
544
545
546 uf_store['relax_disp.cluster'](wx_wizard_modal=True)
547
548
550 """The results directory selection.
551
552 @param event: The wx event.
553 @type event: wx event
554 """
555
556
557 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue())
558
559
560 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
561
562 return
563
564
565 path = gui_to_str(dialog.get_path())
566 if not path:
567 return
568
569
570 self.data.save_dir = path
571
572
573 self.field_results_dir.SetValue(str_to_gui(path))
574
575
577 """Set the nuclear isotope types of the spins via the spin.isotope user function.
578
579 @keyword event: The wx event.
580 @type event: wx event
581 """
582
583
584 uf_store['spin.isotope'](wx_wizard_modal=True, isotope='15N', spin_id='@N*')
585
586
588 """Synchronise the analysis frame and the relax data store, both ways.
589
590 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.
591
592 @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.
593 @type upload: bool
594 """
595
596
597 if upload:
598 self.data.numeric_only = self.numeric_only.GetValue()
599 elif hasattr(self.data, 'numeric_only'):
600 self.numeric_only.SetValue(bool(self.data.numeric_only))
601
602
603 if upload:
604 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue())
605 elif hasattr(self.data, 'grid_inc'):
606 self.grid_inc.SetValue(int(self.data.grid_inc))
607
608
609 if upload:
610 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
611 elif hasattr(self.data, 'mc_sim_num'):
612 self.mc_sim_num.SetValue(int(self.data.mc_sim_num))
613
614
615 if upload:
616 self.data.mc_sim_all_models = self.mc_sim_all_models.GetValue()
617 elif hasattr(self.data, 'mc_sim_all_models'):
618 self.mc_sim_all_models.SetValue(bool(self.data.mc_sim_all_models))
619
620
621 if upload:
622 self.data.insignificance = self.insignificance.GetValue()
623 try:
624 self.data.insignificance = gui_to_float(self.data.insignificance)
625 except:
626 pass
627 elif hasattr(self.data, 'insignificance'):
628 self.insignificance.SetValue(float_to_gui(self.data.insignificance))
629
630
631 if upload:
632 self.data.save_dir = gui_to_str(self.field_results_dir.GetValue())
633 else:
634 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir))
635
636
637 if upload:
638 self.data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue())
639 elif hasattr(self.data, 'pre_run_dir'):
640 self.field_pre_run_dir.SetValue(str_to_gui(self.data.pre_run_dir))
641
642
643 if upload:
644 self.data.disp_models = self.model_field.GetValue()
645 else:
646 self.model_field.set_value(self.data.disp_models)
647
648
650 """Update the cluster field."""
651
652
653 cluster_keys = []
654 if hasattr(cdp, 'clustering'):
655 cluster_keys = sorted(cdp.clustering.keys())
656
657
658 if not len(cluster_keys):
659 wx.CallAfter(self.field_cluster.SetValue, "free spins")
660
661
662 else:
663
664 text = ""
665 if "free spins" in cluster_keys:
666 text += "free spins"
667 for i in range(len(cluster_keys)):
668 if cluster_keys[i] != "free spins":
669 text += ", %s" % cluster_keys[i]
670
671
672 wx.CallAfter(self.field_cluster.SetValue, text)
673
674
676 """Launch the value.set user function.
677
678 @keyword event: The wx event.
679 @type event: wx event
680 """
681
682
683 uf_store['value.set'](wx_wizard_modal=True)
684
685
686
688 """The relaxation dispersion analysis execution object."""
689
702
703
704
706 """The diffusion model list GUI element."""
707
708
709 desc = "Relaxation dispersion models:"
710 models = [
711 MODEL_R2EFF,
712 None,
713 MODEL_NOREX,
714 None,
715 MODEL_LM63,
716 MODEL_LM63_3SITE,
717 MODEL_CR72,
718 MODEL_CR72_FULL,
719 MODEL_IT99,
720 MODEL_TSMFK01,
721 MODEL_NS_CPMG_2SITE_EXPANDED,
722 MODEL_NS_CPMG_2SITE_3D,
723 MODEL_NS_CPMG_2SITE_3D_FULL,
724 MODEL_NS_CPMG_2SITE_STAR,
725 MODEL_NS_CPMG_2SITE_STAR_FULL,
726 None,
727 MODEL_M61,
728 MODEL_M61B,
729 MODEL_DPL94,
730 MODEL_TP02,
731 MODEL_TAP03,
732 MODEL_MP05,
733 MODEL_NS_R1RHO_2SITE,
734 MODEL_NS_R1RHO_3SITE_LINEAR,
735 MODEL_NS_R1RHO_3SITE,
736 None,
737 MODEL_MMQ_CR72,
738 MODEL_NS_MMQ_2SITE,
739 MODEL_NS_MMQ_3SITE_LINEAR,
740 MODEL_NS_MMQ_3SITE
741 ]
742 params = [
743 "{%s/%s, %s}" % (r2eff, r1rho, i0),
744 None,
745 "{%s, ...}" % (r2),
746 None,
747 "{%s, ..., %s, %s}" % (r2, phi_ex, kex),
748 "{%s, ..., %s, kB, %s, kC}" % (r2, phi_exB, phi_exC),
749 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
750 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
751 "{%s, ..., %s, %s, %s}" % (r2, phi_ex, padw2, kex),
752 "{%s, ..., %s, k_AB}" % (r2a, dw),
753 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
754 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
755 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
756 "{%s, ..., pA, %s, %s}" % (r2, dw, kex),
757 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex),
758 None,
759 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex),
760 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
761 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex),
762 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
763 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
764 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
765 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex),
766 "{%s, ..., pA, %s, %s, pB, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC),
767 "{%s, ..., pA, %s, %s, pB, %s, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC, kAC),
768 None,
769 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex),
770 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex),
771 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC),
772 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC, kAC)
773 ]
774 model_desc = [
775 "The base model for determining the %s/%s values and errors for all other models." % (r2eff, r1rho),
776 None,
777 "The model for no chemical exchange relaxation.",
778 None,
779 "The original Luz and Meiboom (1963) 2-site fast exchange equation.",
780 "The original Luz and Meiboom (1963) 3-site fast exchange equation.",
781 "The Carver and Richards (1972) 2-site equation for all time scales (with %s = %s)." % (r2a, r2b),
782 "The Carver and Richards (1972) 2-site equation for all time scales.",
783 "The Ishima and Torchia (1999) 2-site model for all time scales with pA >> pB.",
784 "The Tollinger et al. (2001) 2-site very-slow exchange model.",
785 "The 2-site numerical solution expanded using Maple by Nikolai Skrynnikov.",
786 "The 2-site numerical solution using 3D magnetisation vectors (with %s = %s)." % (r2a, r2b),
787 "The 2-site numerical solution using 3D magnetisation vectors.",
788 "The 2-site numerical solution using complex conjugate matrices (with %s = %s)." % (r2a, r2b),
789 "The 2-site numerical solution using complex conjugate matrices.",
790 None,
791 "The Meiboom (1961) 2-site fast exchange equation.",
792 "The Meiboom (1961) 2-site equation for all time scales with pA >> pB.",
793 "The Davis, Perlman and London (1994) 2-site fast exchange equation.",
794 "The Trott and Palmer (2002) 2-site equation for all time scales.",
795 "The Trott, Abergel and Palmer (2003) off-resonance 2-site equation for all time scales.",
796 "The Miloushev and Palmer (2005) off-resonance 2-site equation for all time scales.",
797 "The 2-site numerical solution using 3D magnetisation vectors.",
798 "The 3-site linearised numerical solution using 3D magnetisation vectors.",
799 "The 3-site numerical solution using 3D magnetisation vectors.",
800 None,
801 "The CR72 2-site model extended to MMQ CPMG data by Korzhnev et al., 2004.",
802 "The 2-site numerical solution of Korzhnev et al. (2004) from multi-quantum CPMG data.",
803 "The 3-site linearised numerical solution of Korzhnev et al. (2005) for MMQ CPMG data.",
804 "The 3-site numerical solution of Korzhnev et al. (2005) for MMQ CPMG data."
805 ]
806 size = wx.Size(1024, 750)
807 tooltip = "The list of all relaxation dispersion models to be optimised as part of the protocol."
808 tooltip_button = "Open the model list selector window."
809