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