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