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_bundle, 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 protected_exec
49 from gui import paths
50 from gui.string_conv import gui_to_int, gui_to_str, int_to_gui, str_to_gui
51 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
52 from gui.wizard import Wiz_window
53
54
55
57 """The base class for the R1 and R2 frames."""
58
59
60 analysis_type = None
61 bitmap = None
62 label = None
63
64 - 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):
65 """Build the automatic R1 and R2 analysis GUI frame elements.
66
67 @param parent: The parent wx element.
68 @type parent: wx object
69 @keyword id: The unique ID number.
70 @type id: int
71 @keyword pos: The position.
72 @type pos: wx.Size object
73 @keyword size: The size.
74 @type size: wx.Size object
75 @keyword style: The style.
76 @type style: int
77 @keyword name: The name for the panel.
78 @type name: unicode
79 @keyword gui: The main GUI class.
80 @type gui: gui.relax_gui.Main instance
81 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook).
82 @type analysis_name: str
83 @keyword pipe_name: The name of the data pipe associated with this analysis.
84 @type pipe_name: str
85 @keyword pipe_bundle: The name of the data pipe bundle associated with this analysis.
86 @type pipe_bundle: str
87 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists).
88 @type data_index: None or int
89 """
90
91
92 self.gui = gui
93
94
95 self.init_flag = True
96
97
98 if data_index == None:
99
100 if not has_pipe(pipe_name):
101 self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='relax_fit', bundle=pipe_bundle)
102
103
104 if not has_bundle(pipe_bundle):
105 self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name)
106
107
108 data_index = ds.relax_gui.analyses.add(self.label)
109
110
111 ds.relax_gui.analyses[data_index].analysis_name = analysis_name
112 ds.relax_gui.analyses[data_index].pipe_name = pipe_name
113 ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle
114
115
116 ds.relax_gui.analyses[data_index].frq = ''
117 ds.relax_gui.analyses[data_index].grid_inc = None
118 ds.relax_gui.analyses[data_index].mc_sim_num = None
119 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir
120
121
122 self.data = ds.relax_gui.analyses[data_index]
123 self.data_index = data_index
124
125
126 self.observer_register()
127
128
129 super(Auto_rx, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
130
131
133 """Activate or deactivate certain elements of the analysis in response to the execution lock."""
134
135
136 enable = False
137 if not status.exec_lock.locked():
138 enable = True
139
140
141 wx.CallAfter(self.field_nmr_frq.Enable, enable)
142 wx.CallAfter(self.field_results_dir.Enable, enable)
143 wx.CallAfter(self.spin_systems.Enable, enable)
144 wx.CallAfter(self.peak_intensity.Enable, enable)
145 wx.CallAfter(self.grid_inc.Enable, enable)
146 wx.CallAfter(self.mc_sim_num.Enable, enable)
147 wx.CallAfter(self.button_exec_relax.Enable, enable)
148
149
151 """Assemble the data required for the auto-analysis.
152
153 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.
154
155 @return: A container with all the data required for the auto-analysis.
156 @rtype: class instance, list of str
157 """
158
159
160 data = Container()
161 missing = []
162
163
164 data.pipe_name = self.data.pipe_name
165 data.pipe_bundle = self.data.pipe_bundle
166
167
168 frq = gui_to_str(self.field_nmr_frq.GetValue())
169 if frq == None:
170 missing.append('NMR frequency')
171
172
173 data.file_root = '%s.%s' % (self.analysis_type, frq)
174
175
176 if not exists_mol_res_spin_data():
177 missing.append("Sequence data")
178
179
180 if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 3:
181 missing.append("Spectral data")
182
183
184 data.inc = gui_to_int(self.grid_inc.GetValue())
185
186
187 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
188
189
190 data.save_dir = self.data.save_dir
191
192
193 return data, missing
194
195
197 """Construct the right hand box to pack into the main Rx box.
198
199 @return: The right hand box element containing all Rx GUI elements (excluding the bitmap) to pack into the main Rx box.
200 @rtype: wx.BoxSizer instance
201 """
202
203
204 box = wx.BoxSizer(wx.VERTICAL)
205
206
207 self.add_title(box, "Setup for %s relaxation analysis" % self.label)
208
209
210 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)
211
212
213 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)
214
215
216 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)
217
218
219 self.add_spin_systems(box, self)
220
221
222 box.AddSpacer(20)
223 self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard)
224 box.AddSpacer(10)
225
226
227 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)
228 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)
229
230
231 box.AddSpacer(30)
232 box.AddStretchSpacer()
233
234
235 self.button_exec_relax = self.add_execute_relax(box, self.execute)
236
237
238 return box
239
240
242 """Unregister the spin count from the user functions."""
243
244
245 self.observer_register(remove=True)
246
247
248 self.peak_intensity.delete()
249
250
291
292
313
314
316 """Launch the Rx peak loading wizard.
317
318 @param event: The wx event.
319 @type event: wx event
320 """
321
322
323 wx.BeginBusyCursor()
324
325
326 self.wizard = Wiz_window(parent=self.gui, size_x=1000, size_y=750, title="Set up the %s peak intensities" % self.label)
327 self.page_indices = {}
328
329
330 if not are_spins_named():
331
332 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?"
333
334
335 if status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES:
336 page = uf_store['spin.name'].create_page(self.wizard, sync=True)
337 self.page_indices['read'] = self.wizard.add_page(page, proceed_on_error=False)
338
339
340
341 self.page_intensity = uf_store['spectrum.read_intensities'].create_page(self.wizard, sync=True)
342 self.page_indices['read'] = self.wizard.add_page(self.page_intensity, skip_button=True, proceed_on_error=False)
343
344
345 self.page_error_type = Spectral_error_type_page(parent=self.wizard, height_desc=520)
346 self.page_indices['err_type'] = self.wizard.add_page(self.page_error_type, apply_button=False)
347 self.wizard.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type)
348
349
350 page = uf_store['spectrum.replicated'].create_page(self.wizard, sync=True)
351 self.page_indices['repl'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
352 self.wizard.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl)
353 page.on_init = self.wizard_update_repl
354
355
356 page = uf_store['spectrum.baseplane_rmsd'].create_page(self.wizard, sync=True)
357 self.page_indices['rmsd'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
358 self.wizard.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd)
359 page.on_init = self.wizard_update_rmsd
360
361
362 page = uf_store['spectrum.integration_points'].create_page(self.wizard, sync=True)
363 self.page_indices['pts'] = self.wizard.add_page(page, skip_button=True, proceed_on_error=False)
364 page.on_init = self.wizard_update_pts
365
366
367 page = uf_store['relax_fit.relax_time'].create_page(self.wizard, sync=True)
368 self.page_indices['relax_time'] = self.wizard.add_page(page, skip_button=False, proceed_on_error=False)
369 page.on_init = self.wizard_update_relax_time
370
371
372 if wx.IsBusy():
373 wx.EndBusyCursor()
374
375
376 self.wizard.run()
377
378
380 """The results directory selection.
381
382 @param event: The wx event.
383 @type event: wx event
384 """
385
386
387 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue())
388
389
390 if status.show_gui and dialog.ShowModal() != wx.ID_OK:
391
392 return
393
394
395 path = gui_to_str(dialog.get_path())
396 if not path:
397 return
398
399
400 self.data.save_dir = path
401
402
403 self.field_results_dir.SetValue(str_to_gui(path))
404
405
407 """Synchronise the analysis frame and the relax data store, both ways.
408
409 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.
410
411 @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.
412 @type upload: bool
413 """
414
415
416 if upload:
417 self.data.frq = gui_to_str(self.field_nmr_frq.GetValue())
418 else:
419 self.field_nmr_frq.SetValue(str_to_gui(self.data.frq))
420
421
422 if upload:
423 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue())
424 elif hasattr(self.data, 'grid_inc'):
425 self.grid_inc.SetValue(int(self.data.grid_inc))
426
427
428 if upload:
429 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue())
430 elif hasattr(self.data, 'mc_sim_num'):
431 self.mc_sim_num.SetValue(int(self.data.mc_sim_num))
432
433
434 if upload:
435 self.data.save_dir = gui_to_str(self.field_results_dir.GetValue())
436 else:
437 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir))
438
439
441 """Set the page after the error type choice.
442
443 @return: The index of the next page, which is the current page index plus one.
444 @rtype: int
445 """
446
447
448 if self.page_error_type.selection == 'rmsd':
449 return self.page_indices['rmsd']
450
451
452 elif self.page_error_type.selection == 'repl':
453 return self.page_indices['repl']
454
455
457 """Set the page that comes after the spectrum.replicated page.
458
459 @return: The index of the next page.
460 @rtype: int
461 """
462
463
464 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue())
465 if int_method != 'height':
466 return self.page_indices['pts']
467
468
469 else:
470 return self.page_indices['relax_time']
471
472
474 """Set the page that comes after the spectrum.baseplane_rmsd page.
475
476 @return: The index of the next page.
477 @rtype: int
478 """
479
480
481 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue())
482 if int_method != 'height':
483 return self.page_indices['pts']
484
485
486 else:
487 return self.page_indices['relax_time']
488
489
491 """Update the spectrum.replicated page based on previous data."""
492
493
494 page = self.wizard.get_page(self.page_indices['read'])
495
496
497 id = page.uf_args['spectrum_id'].GetValue()
498
499
500 page = self.wizard.get_page(self.page_indices['pts'])
501 page.uf_args['spectrum_id'].SetValue(id)
502
503
505 """Update the spectrum.replicated page based on previous data."""
506
507
508 page = self.wizard.get_page(self.page_indices['read'])
509
510
511 id = page.uf_args['spectrum_id'].GetValue()
512
513
514 page = self.wizard.get_page(self.page_indices['repl'])
515 page.uf_args['spectrum_ids'].SetValue(value=id, index=0)
516
517
519 """Update the spectrum.baseplane_rmsd page based on previous data."""
520
521
522 page = self.wizard.get_page(self.page_indices['read'])
523
524
525 id = page.uf_args['spectrum_id'].GetValue()
526
527
528 page = self.wizard.get_page(self.page_indices['rmsd'])
529 page.uf_args['spectrum_id'].SetValue(id)
530
531
533 """Update the relax_fit.relax_time page based on previous data."""
534
535
536 page = self.wizard.get_page(self.page_indices['read'])
537
538
539 id = page.uf_args['spectrum_id'].GetValue()
540
541
542 page = self.wizard.get_page(self.page_indices['relax_time'])
543 page.uf_args['spectrum_id'].SetValue(id)
544
545
546
548 """The Rx analysis execution object."""
549
558