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 containing the base class for the automatic R1 and R2 analysis frames."""
26
27
28 from os import sep
29 from string import lower
30 import sys
31 import wx
32
33
34 from auto_analyses.relax_fit import Relax_fit
35 from data import Relax_data_store; ds = Relax_data_store()
36 from generic_fns.mol_res_spin import are_spins_named, exists_mol_res_spin_data
37 from generic_fns.pipes import has_pipe
38 from status import Status; status = Status()
39
40
41 from gui.analyses.base import Base_analysis, Spectral_error_type_page
42 from gui.analyses.elements import Spin_ctrl, Text_ctrl
43 from gui.analyses.execute import Execute
44 from gui.base_classes import Container
45 from gui.components.spectrum import Spectra_list
46 from gui.filedialog import RelaxDirDialog
47 from gui.message import error_message, Missing_data, Question
48 from gui.misc import gui_to_int, gui_to_str, int_to_gui, protected_exec, str_to_gui
49 from gui import paths
50 from gui.user_functions.relax_fit import Relax_time_page
51 from gui.user_functions.spectrum import Baseplane_rmsd_page, Integration_points_page, Read_intensities_page, Replicated_page
52 from gui.user_functions.spin import Name_page
53 from gui.wizard import Wiz_window
54
55
56
58 """The base class for the R1 and R2 frames."""
59
60
61 analysis_type = None
62 bitmap = None
63 label = None
64
65 - 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):
66 """Build the automatic R1 and R2 analysis GUI frame elements.
67
68 @param parent: The parent wx element.
69 @type parent: wx object
70 @keyword id: The unique ID number.
71 @type id: int
72 @keyword pos: The position.
73 @type pos: wx.Size object
74 @keyword size: The size.
75 @type size: wx.Size object
76 @keyword style: The style.
77 @type style: int
78 @keyword name: The name for the panel.
79 @type name: unicode
80 @keyword gui: The main GUI class.
81 @type gui: gui.relax_gui.Main instance
82 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook).
83 @type analysis_name: str
84 @keyword pipe_name: The name of the data pipe associated with this analysis.
85 @type pipe_name: str
86 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists).
87 @type data_index: None or int
88 """
89
90
91 self.gui = gui
92
93
94 self.init_flag = True
95
96
97 if data_index == None:
98
99 if not has_pipe(pipe_name):
100 self.gui.interpreter.apply('pipe.create', pipe_name, 'relax_fit')
101
102
103 data_index = ds.relax_gui.analyses.add(self.label)
104
105
106 ds.relax_gui.analyses[data_index].analysis_name = analysis_name
107 ds.relax_gui.analyses[data_index].pipe_name = pipe_name
108
109
110 ds.relax_gui.analyses[data_index].frq = ''
111 ds.relax_gui.analyses[data_index].grid_inc = None
112 ds.relax_gui.analyses[data_index].mc_sim_num = None
113 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir
114
115
116 self.data = ds.relax_gui.analyses[data_index]
117 self.data_index = data_index
118
119
120 self.observer_register()
121
122
123 super(Auto_rx, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
124
125
127 """Activate or deactivate certain elements of the analysis in response to the execution lock."""
128
129
130 enable = False
131 if not status.exec_lock.locked():
132 enable = True
133
134
135 wx.CallAfter(self.field_nmr_frq.Enable, enable)
136 wx.CallAfter(self.field_results_dir.Enable, enable)
137 wx.CallAfter(self.spin_systems.Enable, enable)
138 wx.CallAfter(self.peak_intensity.Enable, enable)
139 wx.CallAfter(self.grid_inc.Enable, enable)
140 wx.CallAfter(self.mc_sim_num.Enable, enable)
141 wx.CallAfter(self.button_exec_relax.Enable, enable)
142
143
145 """Assemble the data required for the auto-analysis.
146
147 See the docstring for auto_analyses.relax_fit for details. All data is taken from the relax data store, so data upload from the GUI to there must have been previously performed.
148
149 @return: A container with all the data required for the auto-analysis.
150 @rtype: class instance, list of str
151 """
152
153
154 data = Container()
155 missing = []
156
157
158 data.pipe_name = self.data.pipe_name
159
160
161 frq = gui_to_str(self.field_nmr_frq.GetValue())
162 if frq == None:
163 missing.append('NMR frequency')
164
165
166 data.file_root = '%s.%s' % (self.analysis_type, frq)
167
168
169 if not exists_mol_res_spin_data():
170 missing.append("Sequence data")
171
172
173 if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 3:
174 missing.append("Spectral data")
175
176
177 data.inc = gui_to_int(self.grid_inc.GetValue())
178
179
180 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
181
182
183 data.save_dir = self.data.save_dir
184
185
186 return data, missing
187
188
190 """Construct the right hand box to pack into the main Rx box.
191
192 @return: The right hand box element containing all Rx GUI elements (excluding the bitmap) to pack into the main Rx box.
193 @rtype: wx.BoxSizer instance
194 """
195
196
197 box = wx.BoxSizer(wx.VERTICAL)
198
199
200 self.add_title(box, "Setup for %s relaxation analysis" % self.label)
201
202
203 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)
204
205
206 self.field_nmr_frq = Text_ctrl(box, self, text="NMR frequency label [MHz]", default=self.data.frq, tooltip="This label is added to the output files. For example if the label is '600', the %s values will be located in the file '%s.600.out'." % (self.label, lower(self.label)), width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
207
208
209 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)
210
211
212 self.add_spin_systems(box, self)
213
214
215 box.AddSpacer(20)
216 self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard)
217 box.AddSpacer(10)
218
219
220 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)
221 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)
222
223
224 box.AddSpacer(30)
225 box.AddStretchSpacer()
226
227
228 self.button_exec_relax = self.add_execute_relax(box, self.execute)
229
230
231 return box
232
233
235 """Unregister the spin count from the user functions."""
236
237
238 self.observer_register(remove=True)
239
240
241 self.peak_intensity.delete()
242
243
284
285
306
307
309 """Launch the NOE peak loading wizard.
310
311 @param event: The wx event.
312 @type event: wx event
313 """
314
315
316 wx.BeginBusyCursor()
317
318
319 self.wizard = Wiz_window(parent=self.gui, size_x=1000, size_y=800, title="Set up the %s peak intensities" % self.label)
320 self.page_indices = {}
321
322
323 if not are_spins_named():
324
325 msg = "No spins have been named. Please use the spin.name user function first, otherwise it is unlikely that any data will be loaded from the peak intensity file.\n\nThis message can be ignored if the generic file format is used and spin names have not been specified. Would you like to name the spins already loaded into the relax data store?"
326
327
328 if status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES:
329 page = Name_page(self.wizard, sync=True)
330 self.page_indices['read'] = self.wizard.add_page(page, proceed_on_error=False)
331
332
333
334 self.page_intensity = Read_intensities_page(self.wizard, sync=True)
335 self.page_indices['read'] = self.wizard.add_page(self.page_intensity, skip_button=True, proceed_on_error=False)
336
337
338 self.page_error_type = Spectral_error_type_page(self.wizard)
339 self.page_indices['err_type'] = self.wizard.add_page(self.page_error_type, apply_button=False)
340 self.wizard.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type)
341
342
343 page = Replicated_page(self.wizard, sync=True)
344 self.page_indices['repl'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
345 self.wizard.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl)
346 page.on_init = self.wizard_update_repl
347
348
349 page = Baseplane_rmsd_page(self.wizard, sync=True)
350 self.page_indices['rmsd'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
351 self.wizard.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd)
352 page.on_init = self.wizard_update_rmsd
353
354
355 page = Integration_points_page(self.wizard, sync=True)
356 self.page_indices['pts'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
357 page.on_init = self.wizard_update_pts
358
359
360 page = Relax_time_page(self.wizard, sync=True)
361 self.page_indices['relax_time'] = self.wizard.add_page(page, skip_button=False, proceed_on_error=False)
362 page.on_init = self.wizard_update_relax_time
363
364
365 if wx.IsBusy():
366 wx.EndBusyCursor()
367
368
369 self.wizard.run()
370
371
373 """The results directory selection.
374
375 @param event: The wx event.
376 @type event: wx event
377 """
378
379
380 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue())
381
382
383 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
384
385 return
386
387
388 path = gui_to_str(dialog.get_path())
389 if not path:
390 return
391
392
393 self.data.save_dir = path
394
395
396 self.field_results_dir.SetValue(str_to_gui(path))
397
398
400 """Synchronise the analysis frame and the relax data store, both ways.
401
402 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.
403
404 @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.
405 @type upload: bool
406 """
407
408
409 if upload:
410 self.data.frq = gui_to_str(self.field_nmr_frq.GetValue())
411 else:
412 self.field_nmr_frq.SetValue(str_to_gui(self.data.frq))
413
414
415 if upload:
416 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue())
417 elif hasattr(self.data, 'grid_inc'):
418 self.grid_inc.SetValue(int(self.data.grid_inc))
419
420
421 if upload:
422 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
423 elif hasattr(self.data, 'mc_sim_num'):
424 self.mc_sim_num.SetValue(int(self.data.mc_sim_num))
425
426
427 if upload:
428 self.data.save_dir = gui_to_str(self.field_results_dir.GetValue())
429 else:
430 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir))
431
432
434 """Set the page after the error type choice.
435
436 @return: The index of the next page, which is the current page index plus one.
437 @rtype: int
438 """
439
440
441 if self.page_error_type.selection == 'rmsd':
442 return self.page_indices['rmsd']
443
444
445 elif self.page_error_type.selection == 'repl':
446 return self.page_indices['repl']
447
448
450 """Set the page that comes after the spectrum.replicated page.
451
452 @return: The index of the next page.
453 @rtype: int
454 """
455
456
457 int_method = gui_to_str(self.page_intensity.int_method.GetValue())
458 if int_method != 'height':
459 return self.page_indices['pts']
460
461
462 else:
463 return self.page_indices['relax_time']
464
465
467 """Set the page that comes after the spectrum.baseplane_rmsd page.
468
469 @return: The index of the next page.
470 @rtype: int
471 """
472
473
474 int_method = gui_to_str(self.page_intensity.int_method.GetValue())
475 if int_method != 'height':
476 return self.page_indices['pts']
477
478
479 else:
480 return self.page_indices['relax_time']
481
482
484 """Update the spectrum.replicated page based on previous data."""
485
486
487 page = self.wizard.get_page(self.page_indices['read'])
488
489
490 id = page.spectrum_id.GetValue()
491
492
493 page = self.wizard.get_page(self.page_indices['pts'])
494 page.spectrum_id.SetStringSelection(str_to_gui(id))
495
496
498 """Update the spectrum.replicated page based on previous data."""
499
500
501 page = self.wizard.get_page(self.page_indices['read'])
502
503
504 id = page.spectrum_id.GetValue()
505
506
507 page = self.wizard.get_page(self.page_indices['repl'])
508 page.spectrum_id_boxes[0].SetStringSelection(str_to_gui(id))
509
510
512 """Update the spectrum.baseplane_rmsd page based on previous data."""
513
514
515 page = self.wizard.get_page(self.page_indices['read'])
516
517
518 id = page.spectrum_id.GetValue()
519
520
521 page = self.wizard.get_page(self.page_indices['rmsd'])
522 page.spectrum_id.SetStringSelection(str_to_gui(id))
523
524
526 """Update the relax_fit.relax_time page based on previous data."""
527
528
529 page = self.wizard.get_page(self.page_indices['read'])
530
531
532 id = page.spectrum_id.GetValue()
533
534
535 page = self.wizard.get_page(self.page_indices['relax_time'])
536 page.spectrum_id.SetStringSelection(str_to_gui(id))
537
538
539
541 """The Rx analysis execution object."""
542
551