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 classes for GUI components involving spectral data."""
25
26
27 import wx
28 import wx.lib.buttons
29
30
31 from graphics import fetch_icon
32 from gui.components.base_list import Base_list
33 from gui.string_conv import float_to_gui, gui_to_str, str_to_gui
34 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
35 from lib.compat import u
36 from pipe_control.spectrum import replicated_flags, replicated_ids
37 from status import Status; status = Status()
38 from specific_analyses.relax_disp.data import is_cpmg_exp_type, is_r1rho_exp_type
39 from user_functions.data import Uf_info; uf_info = Uf_info()
40
41
42
43 MENU_SPECTRUM_BASEPLANE_RMSD = wx.NewId()
44 MENU_SPECTRUM_DELETE = wx.NewId()
45 MENU_SPECTRUM_INTEGRATION_POINTS = wx.NewId()
46 MENU_SPECTRUM_REPLICATED = wx.NewId()
47 MENU_RELAX_DISP_EXP_TYPE = wx.NewId()
48 MENU_RELAX_FIT_RELAX_TIME = wx.NewId()
49 MENU_RELAX_DISP_RELAX_TIME = wx.NewId()
50 MENU_SPECTROMETER_FRQ = wx.NewId()
51 MENU_RELAX_DISP_SPIN_LOCK_FIELD = wx.NewId()
52 MENU_RELAX_DISP_SPIN_LOCK_OFFSET = wx.NewId()
53 MENU_RELAX_DISP_CPMG_SETUP = wx.NewId()
54
55
57 """The GUI element for listing loaded spectral data."""
58
59 - def __init__(self, gui=None, parent=None, box=None, id=None, fn_add=None, proportion=0, button_placement='default', noe_flag=False, relax_fit_flag=False, relax_disp_flag=False):
60 """Build the spectral list GUI element.
61
62 @keyword gui: The main GUI object.
63 @type gui: wx.Frame instance
64 @keyword parent: The parent GUI element that this is to be attached to (the panel object).
65 @type parent: wx object
66 @keyword data: The data storage container.
67 @type data: class instance
68 @keyword box: The vertical box sizer to pack this GUI component into.
69 @type box: wx.BoxSizer instance
70 @keyword id: A unique identification string. This is used to register the update method with the GUI user function observer object.
71 @type id: str
72 @keyword fn_add: The function to execute when clicking on the 'Add' button.
73 @type fn_add: func
74 @keyword proportion: The window proportion parameter.
75 @type proportion: bool
76 @keyword button_placement: Override the button visibility and placement. The value of 'default' will leave the buttons at the default setting. The value of 'top' will place the buttons at the top, 'bottom' will place them at the bottom, and None will turn off the buttons.
77 @type button_placement: str or None
78 @keyword noe_flag: A flag which when True will enable the steady-state NOE portions of the wizard.
79 @type noe_flag: bool
80 @keyword relax_fit_flag: A flag which when True will enable the relaxation curve-fitting portions of the wizard.
81 @type relax_fit_flag: bool
82 @keyword relax_disp_flag: A flag which when True will enable the relaxation dispersion portions of the wizard.
83 @type relax_disp_flag: bool
84 """
85
86
87 self.fn_add = fn_add
88 self.noe_flag = noe_flag
89 self.relax_fit_flag = relax_fit_flag
90 self.relax_disp_flag = relax_disp_flag
91
92
93 super(Spectra_list, self).__init__(gui=gui, parent=parent, box=box, id=id, proportion=proportion, button_placement=button_placement)
94
95
97 """Launch the relax_disp.cpmg_setup user function.
98
99 @keyword event: The wx event.
100 @type event: wx event
101 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
102 @type item: None or int
103 """
104
105
106 if item == None:
107 item = self.element.GetFirstSelected()
108
109
110 id = gui_to_str(self.element.GetItemText(item))
111
112
113 frq = None
114 frq_flag = False
115 if hasattr(cdp, 'cpmg_frqs') and id in cdp.cpmg_frqs:
116 frq = cdp.cpmg_frqs[id]
117 frq_flag = True
118
119
120 even = True
121 even_flag = False
122 if hasattr(cdp, 'ncyc_even') and id in cdp.ncyc_even:
123 even = cdp.ncyc_even[id]
124 even_flag = True
125
126
127 if frq_flag:
128 uf_store['relax_disp.cpmg_setup'](spectrum_id=id, cpmg_frq=frq, ncyc_even=even)
129 else:
130 uf_store['relax_disp.cpmg_setup'](spectrum_id=id, ncyc_even=even)
131
132
134 """Launch the relax_disp.exp_type user function.
135
136 @keyword event: The wx event.
137 @type event: wx event
138 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
139 @type item: None or int
140 """
141
142
143 if item == None:
144 item = self.element.GetFirstSelected()
145
146
147 id = gui_to_str(self.element.GetItemText(item))
148
149
150 exp_type = None
151 if hasattr(cdp, 'exp_type') and id in cdp.exp_type:
152 exp_type = cdp.exp_type[id]
153
154
155 if exp_type == None:
156 uf_store['relax_disp.exp_type'](spectrum_id=id)
157 else:
158 uf_store['relax_disp.exp_type'](spectrum_id=id, exp_type=exp_type)
159
160
162 """Launch the relax_disp.relax_time user function.
163
164 @keyword event: The wx event.
165 @type event: wx event
166 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
167 @type item: None or int
168 """
169
170
171 if item == None:
172 item = self.element.GetFirstSelected()
173
174
175 id = gui_to_str(self.element.GetItemText(item))
176
177
178 time = None
179 if hasattr(cdp, 'relax_times') and id in cdp.relax_times:
180 time = cdp.relax_times[id]
181
182
183 if time == None:
184 uf_store['relax_disp.relax_time'](spectrum_id=id)
185 else:
186 uf_store['relax_disp.relax_time'](time=time, spectrum_id=id)
187
188
190 """Launch the relax_disp.spin_lock_field user function.
191
192 @keyword event: The wx event.
193 @type event: wx event
194 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
195 @type item: None or int
196 """
197
198
199 if item == None:
200 item = self.element.GetFirstSelected()
201
202
203 id = gui_to_str(self.element.GetItemText(item))
204
205
206 nu1 = None
207 nu1_flag = False
208 if hasattr(cdp, 'spin_lock_nu1') and id in cdp.spin_lock_nu1:
209 nu1 = cdp.spin_lock_nu1[id]
210 nu1_flag = True
211
212
213 if nu1_flag:
214 uf_store['relax_disp.spin_lock_field'](field=nu1, spectrum_id=id)
215 else:
216 uf_store['relax_disp.spin_lock_field'](spectrum_id=id)
217
218
220 """Launch the relax_disp.spin_lock_offset user function.
221
222 @keyword event: The wx event.
223 @type event: wx event
224 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
225 @type item: None or int
226 """
227
228
229 if item == None:
230 item = self.element.GetFirstSelected()
231
232
233 id = gui_to_str(self.element.GetItemText(item))
234
235
236 offset = None
237 offset_flag = False
238 if hasattr(cdp, 'spin_lock_offset') and id in cdp.spin_lock_offset:
239 offset = cdp.spin_lock_offset[id]
240 offset_flag = True
241
242
243 if offset_flag:
244 uf_store['relax_disp.spin_lock_offset'](offset=offset, spectrum_id=id)
245 else:
246 uf_store['relax_disp.spin_lock_offset'](spectrum_id=id)
247
248
250 """Launch the relax_fit.relax_time user function.
251
252 @keyword event: The wx event.
253 @type event: wx event
254 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
255 @type item: None or int
256 """
257
258
259 if item == None:
260 item = self.element.GetFirstSelected()
261
262
263 id = gui_to_str(self.element.GetItemText(item))
264
265
266 time = None
267 if hasattr(cdp, 'relax_times') and id in cdp.relax_times:
268 time = cdp.relax_times[id]
269
270
271 if time == None:
272 uf_store['relax_fit.relax_time'](spectrum_id=id)
273 else:
274 uf_store['relax_fit.relax_time'](time=time, spectrum_id=id)
275
276
278 """Launch the spectrometer.frequency user function.
279
280 @keyword event: The wx event.
281 @type event: wx event
282 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
283 @type item: None or int
284 """
285
286
287 if item == None:
288 item = self.element.GetFirstSelected()
289
290
291 id = gui_to_str(self.element.GetItemText(item))
292
293
294 frq = None
295 if hasattr(cdp, 'spectrometer_frq') and id in cdp.spectrometer_frq:
296 frq = cdp.spectrometer_frq[id]
297
298
299 if frq == None:
300 uf_store['spectrometer.frequency'](id=id)
301 else:
302 uf_store['spectrometer.frequency'](frq=frq, id=id)
303
304
306 """Launch the spectrum.baseplane_rmsd user function.
307
308 @param event: The wx event.
309 @type event: wx event
310 """
311
312
313 item = self.element.GetFirstSelected()
314
315
316 id = gui_to_str(self.element.GetItemText(item))
317
318
319 uf_store['spectrum.baseplane_rmsd'](spectrum_id=id)
320
321
323 """Launch the spectrum.delete user function.
324
325 @param event: The wx event.
326 @type event: wx event
327 """
328
329
330 item = self.element.GetFirstSelected()
331
332
333 if item == -1:
334 id = None
335
336
337 else:
338
339 id = gui_to_str(self.element.GetItemText(item))
340
341
342 uf_store['spectrum.delete'](spectrum_id=id)
343
344
346 """Launch the spectrum.error_analysis user function.
347
348 @param event: The wx event.
349 @type event: wx event
350 """
351
352
353 item = self.element.GetFirstSelected()
354
355
356 ids = []
357 while True:
358
359 if item == -1:
360 break
361
362
363 ids.append(gui_to_str(self.element.GetItemText(item)))
364
365
366 item = self.element.GetNextSelected(item)
367
368
369 if not len(ids):
370 ids = None
371
372
373 uf_store['spectrum.error_analysis'](subset=ids, wx_wizard_modal=True)
374
375
376 self.gui.show_controller(None)
377 self.gui.controller.log_panel.on_goto_end(None)
378
379
381 """Launch the spectrum.integration_points user function.
382
383 @param event: The wx event.
384 @type event: wx event
385 """
386
387
388 item = self.element.GetFirstSelected()
389
390
391 id = gui_to_str(self.element.GetItemText(item))
392
393
394 uf_store['spectrum.integration_points'](spectrum_id=id)
395
396
398 """Launch the spectrum.replicated user function.
399
400 @keyword event: The wx event.
401 @type event: wx event
402 @keyword item: This is for debugging purposes only, to allow the GUI tests to select items without worrying about OS dependent wxPython bugs.
403 @type item: None or int
404 """
405
406
407 if not self.element.GetItemCount():
408 return
409
410
411 if item == None:
412 item = self.element.GetFirstSelected()
413
414
415 id = gui_to_str(self.element.GetItemText(item))
416
417
418 replicates = replicated_ids(id)
419
420
421 if replicates == []:
422 uf_store['spectrum.replicated'](spectrum_ids=id)
423 else:
424 uf_store['spectrum.replicated'](spectrum_ids=replicates)
425
426
428 """Add the dispersion point info to the element.
429
430 This is either the CPMG pulse frequency or the spin-lock field strength. Both share the same column.
431
432 @param index: The column index for the data.
433 @type index: int
434 @return: True if the data exists, False otherwise.
435 @rtype: bool
436 """
437
438
439 self.element.InsertColumn(index, u("\u03BDCPMG (Hz) or Spin-lock \u03BD1 (Hz)"))
440
441
442 if not hasattr(cdp, 'spectrum_ids'):
443 return True
444
445
446 for i in range(len(cdp.spectrum_ids)):
447
448 if hasattr(cdp, 'cpmg_frqs') and cdp.spectrum_ids[i] in cdp.cpmg_frqs:
449 self.element.SetStringItem(i, index, float_to_gui(cdp.cpmg_frqs[cdp.spectrum_ids[i]]))
450
451
452 if hasattr(cdp, 'spin_lock_nu1') and cdp.spectrum_ids[i] in cdp.spin_lock_nu1:
453 self.element.SetStringItem(i, index, float_to_gui(cdp.spin_lock_nu1[cdp.spectrum_ids[i]]))
454
455
456 return True
457
458
460 """Add the experiment type info to the element.
461
462 @param index: The column index for the data.
463 @type index: int
464 @return: True if the data exists, False otherwise.
465 @rtype: bool
466 """
467
468
469 self.element.InsertColumn(index, u("Experiment type"))
470
471
472 if not hasattr(cdp, 'spectrum_ids') or not hasattr(cdp, 'exp_type'):
473 return True
474
475
476 for i in range(len(cdp.spectrum_ids)):
477
478 if cdp.spectrum_ids[i] not in cdp.exp_type:
479 continue
480
481
482 self.element.SetStringItem(i, index, float_to_gui(cdp.exp_type[cdp.spectrum_ids[i]]))
483
484
485 return True
486
487
489 """Add the spectrometer frequency info to the element.
490
491 @param index: The column index for the data.
492 @type index: int
493 @return: True if the frequency data exists, False otherwise.
494 @rtype: bool
495 """
496
497
498 self.element.InsertColumn(index, u("\u03C9H (MHz)"))
499
500
501 if not hasattr(cdp, 'spectrum_ids'):
502 return True
503 if not hasattr(cdp, 'spectrometer_frq') or not len(cdp.spectrometer_frq):
504 return True
505
506
507 for i in range(len(cdp.spectrum_ids)):
508
509 if cdp.spectrum_ids[i] not in cdp.spectrometer_frq:
510 continue
511
512
513 self.element.SetStringItem(i, index, float_to_gui(cdp.spectrometer_frq[cdp.spectrum_ids[i]]/1e6))
514
515
516 return True
517
518
520 """Add the offset info to the element.
521
522 @param index: The column index for the data.
523 @type index: int
524 @return: True if the data exists, False otherwise.
525 @rtype: bool
526 """
527
528
529 self.element.InsertColumn(index, u("Offset \u03C9_rf (ppm)"))
530
531
532 if not hasattr(cdp, 'spectrum_ids'):
533 return True
534
535
536 for i in range(len(cdp.spectrum_ids)):
537 if hasattr(cdp, 'spin_lock_offset') and cdp.spectrum_ids[i] in cdp.spin_lock_offset:
538 self.element.SetStringItem(i, index, float_to_gui(cdp.spin_lock_offset[cdp.spectrum_ids[i]]))
539
540
541 return True
542
543
545 """Create the popup menu.
546
547 @keyword id: The spectrum ID string for the row that was clicked on.
548 @type id: str
549 @return: The popup menu.
550 @rtype: list of dict of wxID, str, str, method
551 """
552
553
554 popup_menus = [
555 {
556 'id': MENU_SPECTRUM_BASEPLANE_RMSD,
557 'text': "Set the &baseplane RMSD",
558 'icon': fetch_icon(uf_info.get_uf('spectrum.baseplane_rmsd').gui_icon),
559 'method': self.action_spectrum_baseplane_rmsd
560 }, {
561 'id': MENU_SPECTRUM_DELETE,
562 'text': "&Delete the peak intensities",
563 'icon': fetch_icon(uf_info.get_uf('spectrum.delete').gui_icon),
564 'method': self.action_spectrum_delete
565 }, {
566 'id': MENU_SPECTRUM_INTEGRATION_POINTS,
567 'text': "Set the number of integration &points",
568 'icon': fetch_icon(uf_info.get_uf('spectrum.integration_points').gui_icon),
569 'method': self.action_spectrum_integration_points
570 }, {
571 'id': MENU_SPECTRUM_REPLICATED,
572 'text': "Specify which spectra are &replicated",
573 'icon': fetch_icon(uf_info.get_uf('spectrum.replicated').gui_icon),
574 'method': self.action_spectrum_replicated
575 }
576 ]
577 if self.relax_disp_flag:
578 popup_menus.append({
579 'id': MENU_RELAX_DISP_EXP_TYPE,
580 'text': "Set the &experiment type",
581 'icon': None,
582 'method': self.action_relax_disp_exp_type
583 })
584 if self.relax_fit_flag:
585 popup_menus.append({
586 'id': MENU_RELAX_FIT_RELAX_TIME,
587 'text': "Set the relaxation &time",
588 'icon': fetch_icon(uf_info.get_uf('relax_fit.relax_time').gui_icon),
589 'method': self.action_relax_fit_relax_time
590 })
591 if self.relax_disp_flag:
592 popup_menus.append({
593 'id': MENU_RELAX_DISP_RELAX_TIME,
594 'text': "Set the relaxation &time",
595 'icon': fetch_icon(uf_info.get_uf('relax_disp.relax_time').gui_icon),
596 'method': self.action_relax_disp_relax_time
597 })
598 popup_menus.append({
599 'id': MENU_SPECTROMETER_FRQ,
600 'text': "Set the spectrometer &frequency",
601 'icon': fetch_icon("relax.spectrometer"),
602 'method': self.action_spectrometer_frq
603 })
604 if self.relax_disp_flag and is_r1rho_exp_type(id):
605 popup_menus.append({
606 'id': MENU_RELAX_DISP_SPIN_LOCK_FIELD,
607 'text': u("Set the spin-&lock field strength \u03BD1"),
608 'icon': fetch_icon("relax.relax_disp"),
609 'method': self.action_relax_disp_spin_lock_field
610 })
611 popup_menus.append({
612 'id': MENU_RELAX_DISP_SPIN_LOCK_OFFSET,
613 'text': u("Set the spin-&lock offset \u03C9_rf"),
614 'icon': fetch_icon("relax.relax_disp"),
615 'method': self.action_relax_disp_spin_lock_offset
616 })
617 if self.relax_disp_flag and is_cpmg_exp_type(id):
618 popup_menus.append({
619 'id': MENU_RELAX_DISP_CPMG_SETUP,
620 'text': u("Set the &CPMG pulse sequence information"),
621 'icon': fetch_icon("relax.relax_disp"),
622 'method': self.action_relax_disp_cpmg_setup
623 })
624
625
626 return popup_menus
627
628
630 """Add the NOE spectral type info to the element.
631
632 @param index: The column index for the data.
633 @type index: int
634 @return: True if a spectrum type exists, False otherwise.
635 @rtype: bool
636 """
637
638
639 if not hasattr(cdp, 'spectrum_type') or not len(cdp.spectrum_type):
640 return False
641
642
643 self.element.InsertColumn(index, str_to_gui("NOE spectrum type"))
644
645
646 table = {
647 'sat': 'Saturated',
648 'ref': 'Reference'
649 }
650
651
652 if not hasattr(cdp, 'spectrum_ids'):
653 return True
654
655
656 for i in range(len(cdp.spectrum_ids)):
657
658 if cdp.spectrum_ids[i] not in cdp.spectrum_type:
659 continue
660
661
662 self.element.SetStringItem(i, index, str_to_gui(table[cdp.spectrum_type[cdp.spectrum_ids[i]]]))
663
664
665 return True
666
667
669 """Add the relaxation delay time info to the element.
670
671 @param index: The column index for the data.
672 @type index: int
673 @return: True if relaxation times exist, False otherwise.
674 @rtype: bool
675 """
676
677
678 if not hasattr(cdp, 'relax_times') or not len(cdp.relax_times):
679 return False
680
681
682 self.element.InsertColumn(index, str_to_gui("Delay times (s)"))
683
684
685 if not hasattr(cdp, 'spectrum_ids'):
686 return True
687
688
689 for i in range(len(cdp.spectrum_ids)):
690
691 if cdp.spectrum_ids[i] not in cdp.relax_times:
692 continue
693
694
695 self.element.SetStringItem(i, index, float_to_gui(cdp.relax_times[cdp.spectrum_ids[i]]))
696
697
698 return True
699
700
702 """Add the replicated spectra info to the element.
703
704 @param index: The column index for the data.
705 @type index: int
706 @return: True if relaxation times exist, False otherwise.
707 @rtype: bool
708 """
709
710
711 if not hasattr(cdp, 'replicates') or not len(cdp.replicates):
712 return False
713
714
715 repl = replicated_flags()
716
717
718 self.element.InsertColumn(index, str_to_gui("Replicate IDs"))
719
720
721 if not hasattr(cdp, 'spectrum_ids'):
722 return True
723
724
725 for i in range(len(cdp.spectrum_ids)):
726
727 if not repl[cdp.spectrum_ids[i]]:
728 continue
729
730
731 id_list = replicated_ids(cdp.spectrum_ids[i])
732
733
734 text = ''
735 for j in range(len(id_list)):
736
737 text = "%s%s" % (text, id_list[j])
738
739
740 if j < len(id_list)-1:
741 text = "%s, " % text
742
743
744 self.element.SetStringItem(i, index, str_to_gui(text))
745
746
747 return True
748
749
751 """Override the base variables."""
752
753
754 self.title = "Spectra list"
755 self.observer_base_name = "spectra list"
756
757
758 self.columns = []
759
760
761 self.button_placement = 'top'
762 self.button_size = (170, 40)
763 self.button_info = [
764 {
765 'object': 'button_add',
766 'label': ' Add',
767 'icon': fetch_icon('oxygen.actions.list-add-relax-blue', "22x22"),
768 'method': self.fn_add,
769 'tooltip': "Read a spectral data file."
770 }, {
771 'object': 'button_delete',
772 'label': ' Delete',
773 'icon': fetch_icon('oxygen.actions.list-remove', "22x22"),
774 'method': self.action_spectrum_delete,
775 'tooltip': "Delete loaded relaxation data from the relax data store."
776 }, {
777 'object': 'button_error_analysis',
778 'label': ' Error analysis',
779 'icon': fetch_icon('oxygen.categories.applications-education', "22x22"),
780 'method': self.action_spectrum_error_analysis,
781 'tooltip': "Perform a peak intensity error analysis on the currently loaded data or data subsets. Select a subset of the spectra below to perform the error analysis only on this subset."
782 }
783 ]
784
785
787 """Method called from self.build_element_safe() to update the list data."""
788
789
790 index = 1
791
792
793 self.element.DeleteAllItems()
794 for i in reversed(range(self.element.GetColumnCount())):
795 self.element.DeleteColumn(i)
796
797
798 self.element.InsertColumn(0, str_to_gui("Spectrum ID"))
799
800
801 n = 0
802 if hasattr(cdp, 'spectrum_ids'):
803
804 n = len(cdp.spectrum_ids)
805
806
807 for i in range(n):
808 self.element.InsertStringItem(i, str_to_gui(cdp.spectrum_ids[i]))
809
810
811 if self.noe_spectrum_type(index):
812 index += 1
813
814
815 if self.relax_disp_flag and self.add_exp_type(index):
816 index += 1
817
818
819 if self.relax_disp_flag and self.add_frqs(index):
820 index += 1
821
822
823 if self.relax_disp_flag and self.add_disp_point(index):
824 index += 1
825
826
827 if self.relax_disp_flag and self.add_offset(index):
828 index += 1
829
830
831 if (self.relax_fit_flag or self.relax_disp_flag) and self.relax_times(index):
832 index += 1
833
834
835 if self.replicates(index):
836 index += 1
837