Package gui :: Package wizards :: Module peak_intensity
[hide private]
[frames] | no frames]

Source Code for Module gui.wizards.peak_intensity

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009-2011 Michael Bieri                                       # 
  4  # Copyright (C) 2010-2014 Edward d'Auvergne                                   # 
  5  # Copyright (C) 2013 Troels E. Linnet                                         # 
  6  #                                                                             # 
  7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  8  #                                                                             # 
  9  # This program is free software: you can redistribute it and/or modify        # 
 10  # it under the terms of the GNU General Public License as published by        # 
 11  # the Free Software Foundation, either version 3 of the License, or           # 
 12  # (at your option) any later version.                                         # 
 13  #                                                                             # 
 14  # This program is distributed in the hope that it will be useful,             # 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 17  # GNU General Public License for more details.                                # 
 18  #                                                                             # 
 19  # You should have received a copy of the GNU General Public License           # 
 20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """Module containing the base class for the automatic R1 and R2 analysis frames.""" 
 26   
 27  # Python module imports. 
 28  from os import sep 
 29  import wx 
 30  from wx.lib import scrolledpanel 
 31   
 32  # relax module imports. 
 33  from graphics import WIZARD_IMAGE_PATH 
 34  from gui.fonts import font 
 35  from gui.message import Question 
 36  from gui.misc import format_table 
 37  from gui.string_conv import gui_to_str 
 38  from gui.uf_objects import Uf_storage; uf_store = Uf_storage() 
 39  from gui.wizards.wiz_objects import Wiz_page, Wiz_window 
 40  from pipe_control.mol_res_spin import are_spins_named 
 41  from specific_analyses.relax_disp.data import has_cpmg_exp_type, has_r1rho_exp_type 
 42  from status import Status; status = Status() 
 43  from user_functions.data import Uf_info; uf_info = Uf_info() 
 44  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 45   
 46   
47 -class Peak_intensity_wizard(Wiz_window):
48 """The wizard for loading peak intensity data.""" 49
50 - def __init__(self, parent=None, size_x=1000, size_y=750, title="Peak intensity loading wizard", noe=False, relax_fit=False, relax_disp=False):
51 """Set up the peak intensity loading wizard. 52 53 @keyword parent: The parent window. 54 @type parent: wx.Window instance 55 @keyword size_x: The width of the wizard. 56 @type size_x: int 57 @keyword size_y: The height of the wizard. 58 @type size_y: int 59 @keyword title: The title of the wizard dialog. 60 @type title: str 61 @keyword noe: A flag which when True will enable the steady-state NOE portions of the wizard. 62 @type noe: bool 63 @keyword relax_fit: A flag which when True will enable the relaxation curve-fitting portions of the wizard. 64 @type relax_fit: bool 65 @keyword relax_disp: A flag which when True will enable the relaxation dispersion portions of the wizard. 66 @type relax_disp: bool 67 """ 68 69 # Store the args. 70 self.noe_flag = noe 71 self.relax_fit_flag = relax_fit 72 self.relax_disp_flag = relax_disp 73 74 # Get the app and store the GUI instance. 75 app = wx.GetApp() 76 self.gui = app.gui 77 78 # Execute the base class method. 79 Wiz_window.__init__(self, parent=self.gui, size_x=size_x, size_y=size_y, title=title, style=wx.DEFAULT_DIALOG_STYLE) 80 81 # Change the cursor to busy. 82 wx.BeginBusyCursor() 83 84 # Initialise the page_indices structure. 85 self.page_indices = {} 86 87 # First check that at least a single spin is named! 88 if not are_spins_named(): 89 # The message. 90 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?" 91 92 # Ask about naming spins, and add the spin.name user function page. 93 if (status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES) or not status.show_gui: 94 page = uf_store['spin.name'].create_page(self, sync=True) 95 self.page_indices['name'] = self.add_page(page, proceed_on_error=False) 96 97 # The spectrum.read_intensities page. 98 self.page_intensity = uf_store['spectrum.read_intensities'].create_page(self, sync=True) 99 self.page_indices['read'] = self.add_page(self.page_intensity, skip_button=True, proceed_on_error=False) 100 101 # Error type selection page. 102 self.page_error_type = Spectral_error_type_page(parent=self, height_desc=520) 103 self.page_indices['err_type'] = self.add_page(self.page_error_type, apply_button=False) 104 self.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type) 105 106 # The spectrum.replicated page. 107 page = uf_store['spectrum.replicated'].create_page(self, sync=True) 108 self.page_indices['repl'] = self.add_page(page, skip_button=True, proceed_on_error=False) 109 self.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl) 110 page.on_init = self.wizard_update_repl 111 112 # The spectrum.baseplane_rmsd page. 113 page = uf_store['spectrum.baseplane_rmsd'].create_page(self, sync=True) 114 self.page_indices['rmsd'] = self.add_page(page, skip_button=True, proceed_on_error=False) 115 self.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd) 116 page.on_init = self.wizard_update_rmsd 117 118 # The spectrum.integration_points page. 119 page = uf_store['spectrum.integration_points'].create_page(self, sync=True) 120 self.page_indices['pts'] = self.add_page(page, skip_button=True, proceed_on_error=False) 121 page.on_init = self.wizard_update_pts 122 123 # NOE pages. 124 if self.noe_flag: 125 # The noe.spectrum_type page. 126 page = uf_store['noe.spectrum_type'].create_page(self, sync=True) 127 self.page_indices['spectrum_type'] = self.add_page(page, skip_button=False, proceed_on_error=False) 128 page.on_display_post = self.wizard_update_noe_spectrum_type 129 130 # Relaxation curve-fitting pages. 131 if self.relax_fit_flag: 132 # The relax_fit.relax_time page. 133 page = uf_store['relax_fit.relax_time'].create_page(self, sync=True) 134 self.page_indices['relax_time'] = self.add_page(page, skip_button=False, proceed_on_error=False) 135 page.on_init = self.wizard_update_relax_fit_relax_time 136 137 # Relaxation dispersion pages. 138 if self.relax_disp_flag: 139 # The relax_disp.exp_type page. 140 page = uf_store['relax_disp.exp_type'].create_page(self, sync=True) 141 self.page_indices['exp_type'] = self.add_page(page, skip_button=True, proceed_on_error=False) 142 page.on_init = self.wizard_update_relax_disp_exp_type 143 144 # The spectrometer.frequency page. 145 page = uf_store['spectrometer.frequency'].create_page(self, sync=True) 146 self.page_indices['spectrometer_frequency'] = self.add_page(page, skip_button=True, proceed_on_error=False) 147 page.on_init = self.wizard_update_spectrometer_frequency 148 149 # The relax_disp.relax_time page. 150 page = uf_store['relax_disp.relax_time'].create_page(self, sync=True) 151 self.page_indices['relax_time'] = self.add_page(page, skip_button=True, proceed_on_error=False) 152 page.on_init = self.wizard_update_relax_disp_relax_time 153 self.set_seq_next_fn(self.page_indices['relax_time'], self.wizard_page_after_relax_time) 154 155 # The relax_disp.cpmg_setup page. 156 page = uf_store['relax_disp.cpmg_setup'].create_page(self, sync=True) 157 self.page_indices['cpmg_setup'] = self.add_page(page, skip_button=True, proceed_on_error=False) 158 page.on_init = self.wizard_update_relax_disp_cpmg_setup 159 self.set_seq_next_fn(self.page_indices['cpmg_setup'], self.wizard_page_after_cpmg_setup) 160 161 # The relax_disp.spin_lock_field page. 162 page = uf_store['relax_disp.spin_lock_field'].create_page(self, sync=True) 163 self.page_indices['spin_lock_field'] = self.add_page(page, skip_button=True, proceed_on_error=False) 164 page.on_init = self.wizard_update_relax_disp_spin_lock_field 165 166 # The relax_disp.spin_lock_offset page. 167 page = uf_store['relax_disp.spin_lock_offset'].create_page(self, sync=True) 168 self.page_indices['spin_lock_offset'] = self.add_page(page, skip_button=True, proceed_on_error=False) 169 page.on_init = self.wizard_update_relax_disp_spin_lock_offset 170 171 # Reset the cursor. 172 if wx.IsBusy(): 173 wx.EndBusyCursor() 174 175 # Run the wizard. 176 self.run()
177 178
180 """Set the page after the CPMG setup page. 181 182 This should either be the R1rho page if R1rho experiment types exist, or terminate the wizard. 183 184 185 @return: The index of the next page, which is the current page index plus one. 186 @rtype: int 187 """ 188 189 # R1rho experiments exists. 190 if has_r1rho_exp_type(): 191 return self.page_indices['spin_lock_field'] 192 193 # Nothing left, so run off the end. 194 else: 195 return self._num_pages + 1
196 197
199 """Set the page after the error type choice. 200 201 @return: The index of the next page, which is the current page index plus one. 202 @rtype: int 203 """ 204 205 # Go to the spectrum.baseplane_rmsd page. 206 if self.page_error_type.selection == 'rmsd': 207 return self.page_indices['rmsd'] 208 209 # Go to the spectrum.replicated page. 210 elif self.page_error_type.selection == 'repl': 211 return self.page_indices['repl']
212 213
215 """Set the page after the relaxation time period page. 216 217 This should either be the CPMG page if CPMG experiment types exist, the R1rho page if R1rho experiment types exist, or terminate the wizard. 218 219 220 @return: The index of the next page, which is the current page index plus one. 221 @rtype: int 222 """ 223 224 # CPMG experiments exists. 225 if has_cpmg_exp_type(): 226 return self.page_indices['cpmg_setup'] 227 228 # R1rho experiments exists. 229 elif has_r1rho_exp_type(): 230 return self.page_indices['spin_lock_field'] 231 232 # Nothing left, so run off the end. 233 else: 234 return self._num_pages + 1
235 236
237 - def wizard_page_after_repl(self):
238 """Set the page that comes after the spectrum.replicated page. 239 240 @return: The index of the next page. 241 @rtype: int 242 """ 243 244 # Go to the spectrum.integration_points page. 245 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 246 if int_method != 'height' and self.page_error_type.selection == 'rmsd': 247 return self.page_indices['pts'] 248 249 # Skip to the noe.spectrum_type page. 250 elif self.noe_flag: 251 return self.page_indices['spectrum_type'] 252 253 # Skip to the relax_fit.relax_time page. 254 elif self.relax_fit_flag: 255 return self.page_indices['relax_time'] 256 257 # Skip to the first dispersion page. 258 elif self.relax_disp_flag: 259 return self.page_indices['exp_type'] 260 261 # Nothing left, so run off the end. 262 else: 263 return self._num_pages + 1
264 265
266 - def wizard_page_after_rmsd(self):
267 """Set the page that comes after the spectrum.baseplane_rmsd page. 268 269 @return: The index of the next page. 270 @rtype: int 271 """ 272 273 # Go to the spectrum.integration_points page. 274 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 275 if int_method != 'height': 276 return self.page_indices['pts'] 277 278 # Skip to the noe.spectrum_type page. 279 elif self.noe_flag: 280 return self.page_indices['spectrum_type'] 281 282 # Skip to the relax_fit.relax_time page. 283 elif self.relax_fit_flag: 284 return self.page_indices['relax_time'] 285 286 # Skip to the first dispersion page. 287 elif self.relax_disp_flag: 288 return self.page_indices['exp_type'] 289 290 # Nothing left, so run off the end. 291 else: 292 return self._num_pages + 1
293 294
295 - def wizard_update_ids(self, page_key=None, arg_key='spectrum_id', index=None):
296 """Update the spectrum ID on the page specified by the key based on previous data. 297 298 @keyword page_key: The key of the page to update. 299 @type page_key: str 300 @keyword arg_key: The key of the page argument to change to the spectrum ID. 301 @type arg_key: str 302 @keyword index: The index for list type structures. 303 @type index: None or int 304 """ 305 306 # The spectrum.read_intensities page. 307 page = self.get_page(self.page_indices['read']) 308 309 # Set the spectrum ID. 310 id = page.uf_args['spectrum_id'].GetValue() 311 312 # Handle list arguments. 313 if isinstance(id, list): 314 # If an empty list is encountered, exit this method without doing anything. 315 if id == []: 316 return 317 318 # Use only the first element. 319 id = id[0] 320 321 # Handle keyword 'auto'. 322 if id == 'auto': 323 # Return the first ID. 324 id = 'Z_A0' 325 326 # Set the ID in the page. 327 page = self.get_page(self.page_indices[page_key]) 328 if index == None: 329 page.uf_args[arg_key].SetValue(id) 330 else: 331 page.uf_args[arg_key].SetValue(value=id, index=index)
332 333
335 """Update the noe.spectrum_type page based on previous data.""" 336 337 # Update the spectrum ID. 338 self.wizard_update_ids(page_key='spectrum_type')
339 340
341 - def wizard_update_pts(self):
342 """Update the spectrum.replicated page based on previous data.""" 343 344 # Update the spectrum ID. 345 self.wizard_update_ids(page_key='pts')
346 347
349 """Update the relax_disp.cpmg_setup page based on previous data.""" 350 351 # Update the spectrum ID. 352 self.wizard_update_ids(page_key='cpmg_setup')
353 354
356 """Update the relax_disp.exp_type page based on previous data.""" 357 358 # Update the spectrum ID. 359 self.wizard_update_ids(page_key='exp_type')
360 361
363 """Update the relax_disp.relax_time page based on previous data.""" 364 365 # Update the spectrum ID. 366 self.wizard_update_ids(page_key='relax_time')
367 368
370 """Update the relax_disp.spin_lock_field page based on previous data.""" 371 372 # Update the spectrum ID. 373 self.wizard_update_ids(page_key='spin_lock_field')
374 375
377 """Update the relax_disp.spin_lock_offset page based on previous data.""" 378 379 # Update the spectrum ID. 380 self.wizard_update_ids(page_key='spin_lock_offset')
381 382
384 """Update the relax_fit.relax_time page based on previous data.""" 385 386 # Update the spectrum ID. 387 self.wizard_update_ids(page_key='relax_time')
388 389
390 - def wizard_update_repl(self):
391 """Update the spectrum.replicated page based on previous data.""" 392 393 # Update the spectrum ID. 394 self.wizard_update_ids(page_key='repl', arg_key='spectrum_ids', index=0)
395 396
397 - def wizard_update_rmsd(self):
398 """Update the spectrum.baseplane_rmsd page based on previous data.""" 399 400 # Update the spectrum ID. 401 self.wizard_update_ids(page_key='rmsd')
402 403
405 """Update the spectrometer.frequency page based on previous data.""" 406 407 # Update the spectrum ID. 408 self.wizard_update_ids(page_key='spectrometer_frequency', arg_key='id')
409 410 411
412 -class Spectral_error_type_page(Wiz_page):
413 """The peak intensity reading wizard page for specifying the type of error to be used.""" 414 415 # Class variables. 416 image_path = WIZARD_IMAGE_PATH + 'spectrum' + sep + 'spectrum_200.png' 417 title = "Specify the type of error to be used" 418 main_text = "Please specify from where the peak intensity errors will be obtained. The is required for the execution of the spectrum.error_analysis user function which will be postponed until after clicking on the 'Execute relax' button at the end of the automatic analysis page. To understand how the errors will be propagated and analysed, the main parts of the spectrum.error_analysis user function description are given below." 419 uf_path = ['spectrum', 'error_analysis'] 420
421 - def _on_select(self, event):
422 """Handle the radio button switching. 423 424 @param event: The wx event. 425 @type event: wx event 426 """ 427 428 # The button. 429 button = event.GetEventObject() 430 431 # RMSD. 432 if button == self.radio_rmsd: 433 self.selection = 'rmsd' 434 elif button == self.radio_repl: 435 self.selection = 'repl'
436 437
438 - def add_contents(self, sizer):
439 """Add the specific GUI elements. 440 441 @param sizer: A sizer object. 442 @type sizer: wx.Sizer instance 443 """ 444 445 # A box sizer for placing the box sizer in. 446 sizer2 = wx.BoxSizer(wx.HORIZONTAL) 447 sizer.Add(sizer2, 1, wx.ALL|wx.EXPAND, 0) 448 449 # Bottom spacing. 450 sizer.AddStretchSpacer() 451 452 # A bit of indentation. 453 sizer2.AddStretchSpacer() 454 455 # A vertical sizer for the radio buttons. 456 sizer_radio = wx.BoxSizer(wx.VERTICAL) 457 sizer2.Add(sizer_radio, 1, wx.ALL|wx.EXPAND, 0) 458 459 # The RMSD radio button. 460 self.radio_rmsd = wx.RadioButton(self, -1, "Baseplane RMSD.", style=wx.RB_GROUP) 461 sizer_radio.Add(self.radio_rmsd, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 462 463 # Spacing. 464 sizer_radio.AddSpacer(10) 465 466 # The replicated spectra radio button. 467 self.radio_repl = wx.RadioButton(self, -1, "Replicated spectra.") 468 sizer_radio.Add(self.radio_repl, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 469 470 # Bind the buttons. 471 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_rmsd) 472 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_repl) 473 474 # Right side spacing. 475 sizer2.AddStretchSpacer(3) 476 477 # Bottom spacing. 478 sizer.AddStretchSpacer() 479 480 # Set the default selection. 481 self.selection = 'rmsd'
482 483
484 - def add_desc(self, sizer, max_y=520):
485 """Add the description to the dialog. 486 487 @param sizer: A sizer object. 488 @type sizer: wx.Sizer instance 489 @keyword max_y: The maximum height, in number of pixels, for the description. 490 @type max_y: int 491 """ 492 493 # Initialise. 494 spacing = 15 495 496 # A line with spacing. 497 sizer.AddSpacer(5) 498 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 499 sizer.AddSpacer(5) 500 501 # Create a scrolled panel. 502 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc") 503 504 # A sizer for the panel. 505 panel_sizer = wx.BoxSizer(wx.VERTICAL) 506 507 # Initialise the text elements. 508 tot_y = 0 509 text_elements = [] 510 text_types = [] 511 512 # The wrapped text. 513 text = wx.StaticText(panel, -1, self.main_text, style=wx.TE_MULTILINE) 514 text.SetFont(font.normal) 515 text.Wrap(self._main_size - 20) 516 text_elements.append(text) 517 text_types.append('title') 518 519 # The text size, then spacing. 520 x, y = text.GetSizeTuple() 521 tot_y += y 522 tot_y += spacing 523 524 # Get the spectrum.error_analysis user function data object. 525 uf_data = uf_info.get_uf('spectrum.error_analysis') 526 527 # The description sections. 528 if uf_data.desc != None: 529 # Loop over the sections. 530 for i in range(len(uf_data.desc)): 531 # Alias. 532 desc = uf_data.desc[i] 533 534 # Skip the prompt examples. 535 if desc.get_title() == 'Prompt examples': 536 continue 537 538 # Loop over the text elements. 539 for type, element in desc.element_loop(title=True): 540 # The text version of the elements. 541 text = '' 542 if isinstance(element, str): 543 text = element 544 545 # Format the tables. 546 if type == 'table': 547 text = format_table(uf_tables.get_table(element)) 548 549 # Format the lists. 550 elif type == 'list': 551 # Loop over the list elements. 552 for j in range(len(element)): 553 text += " - %s\n" % element[j] 554 555 # Format the item lists. 556 elif type == 'item list': 557 # Loop over the list elements. 558 for j in range(len(element)): 559 # No item. 560 if element[j][0] in [None, '']: 561 text += " %s\n" % element[j][1] 562 else: 563 text += " %s: %s\n" % (element[j][0], element[j][1]) 564 565 # The text object. 566 text_obj = wx.StaticText(panel, -1, text, style=wx.TE_MULTILINE) 567 568 # Format. 569 if type == 'title': 570 text_obj.SetFont(font.subtitle) 571 elif type == 'paragraph': 572 text_obj.SetFont(font.normal) 573 elif type in ['table', 'verbatim']: 574 text_obj.SetFont(font.modern_small) 575 else: 576 text_obj.SetFont(font.normal) 577 578 # Wrap the paragraphs and lists (with spacing for scrollbars). 579 if type in ['paragraph', 'list', 'item list']: 580 text_obj.Wrap(self._main_size - 20) 581 582 # The text size. 583 x, y = text_obj.GetSizeTuple() 584 tot_y += y 585 586 # The spacing after each element (except the last). 587 tot_y += spacing 588 589 # The spacing before each section (not including the first). 590 if i != 0 and type == 'title': 591 tot_y += spacing 592 593 # Append the text objects. 594 text_elements.append(text_obj) 595 text_types.append(type) 596 597 # Some extra space for who knows what?! 598 tot_y -= spacing 599 tot_y += 20 600 601 # Set the panel size - scrolling needed. 602 if tot_y > max_y: 603 panel.SetInitialSize((self._main_size, max_y)) 604 605 # Set the panel size - no scrolling. 606 else: 607 panel.SetInitialSize((self._main_size, tot_y)) 608 609 # Add the text. 610 n = len(text_elements) 611 for i in range(n): 612 # Spacing before each section (not including the first). 613 if i > 1 and text_types[i] == 'title': 614 panel_sizer.AddSpacer(spacing) 615 616 # The text. 617 panel_sizer.Add(text_elements[i], 0, wx.ALIGN_LEFT, 0) 618 619 # Spacer after all sections (except the end). 620 if i != n - 1: 621 panel_sizer.AddSpacer(spacing) 622 623 # Set up and add the panel to the sizer. 624 panel.SetSizer(panel_sizer) 625 panel.SetAutoLayout(1) 626 panel.SetupScrolling(scroll_x=False, scroll_y=True) 627 sizer.Add(panel, 0, wx.ALL|wx.EXPAND) 628 629 # A line with spacing. 630 sizer.AddSpacer(5) 631 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 632 sizer.AddSpacer(5)
633