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-2013 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 status import Status; status = Status() 
 41  from user_functions.data import Uf_info; uf_info = Uf_info() 
 42  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 43   
 44   
45 -class Peak_intensity_wizard(Wiz_window):
46 """The wizard for loading peak intensity data.""" 47
48 - def __init__(self, parent=None, size_x=1000, size_y=750, title="Peak intensity loading wizard", noe=False, relax_fit=False):
49 """Set up the peak intensity loading wizard. 50 51 @keyword parent: The parent window. 52 @type parent: wx.Window instance 53 @keyword size_x: The width of the wizard. 54 @type size_x: int 55 @keyword size_y: The height of the wizard. 56 @type size_y: int 57 @keyword title: The title of the wizard dialog. 58 @type title: str 59 @keyword noe: A flag which when True will enable the steady-state NOE portions of the wizard. 60 @type noe: bool 61 @keyword relax_fit: A flag which when True will enable the relaxation curve-fitting portions of the wizard. 62 @type relax_fit: bool 63 """ 64 65 # Store the args. 66 self.noe_flag = noe 67 self.relax_fit_flag = relax_fit 68 69 # Get the app and store the GUI instance. 70 app = wx.GetApp() 71 self.gui = app.gui 72 73 # Execute the base class method. 74 Wiz_window.__init__(self, parent=self.gui, size_x=size_x, size_y=size_y, title=title, style=wx.DEFAULT_DIALOG_STYLE) 75 76 # Change the cursor to busy. 77 wx.BeginBusyCursor() 78 79 # Initialise the page_indices structure. 80 self.page_indices = {} 81 82 # First check that at least a single spin is named! 83 if not are_spins_named(): 84 # The message. 85 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?" 86 87 # Ask about naming spins, and add the spin.name user function page. 88 if (status.show_gui and Question(msg, title="Incomplete setup", size=(450, 250), default=True).ShowModal() == wx.ID_YES) or not status.show_gui: 89 page = uf_store['spin.name'].create_page(self, sync=True) 90 self.page_indices['name'] = self.add_page(page, proceed_on_error=False) 91 92 # The spectrum.read_intensities page. 93 self.page_intensity = uf_store['spectrum.read_intensities'].create_page(self, sync=True) 94 self.page_indices['read'] = self.add_page(self.page_intensity, skip_button=True, proceed_on_error=False) 95 96 # Error type selection page. 97 self.page_error_type = Spectral_error_type_page(parent=self, height_desc=520) 98 self.page_indices['err_type'] = self.add_page(self.page_error_type, apply_button=False) 99 self.set_seq_next_fn(self.page_indices['err_type'], self.wizard_page_after_error_type) 100 101 # The spectrum.replicated page. 102 page = uf_store['spectrum.replicated'].create_page(self, sync=True) 103 self.page_indices['repl'] = self.add_page(page, skip_button=True, proceed_on_error=False) 104 self.set_seq_next_fn(self.page_indices['repl'], self.wizard_page_after_repl) 105 page.on_init = self.wizard_update_repl 106 107 # The spectrum.baseplane_rmsd page. 108 page = uf_store['spectrum.baseplane_rmsd'].create_page(self, sync=True) 109 self.page_indices['rmsd'] = self.add_page(page, skip_button=True, proceed_on_error=False) 110 self.set_seq_next_fn(self.page_indices['rmsd'], self.wizard_page_after_rmsd) 111 page.on_init = self.wizard_update_rmsd 112 113 # The spectrum.integration_points page. 114 page = uf_store['spectrum.integration_points'].create_page(self, sync=True) 115 self.page_indices['pts'] = self.add_page(page, skip_button=True, proceed_on_error=False) 116 page.on_init = self.wizard_update_pts 117 118 # NOE pages. 119 if self.noe_flag: 120 # The noe.spectrum_type page. 121 page = uf_store['noe.spectrum_type'].create_page(self, sync=True) 122 self.page_indices['spectrum_type'] = self.add_page(page, skip_button=False, proceed_on_error=False) 123 page.on_display_post = self.wizard_update_noe_spectrum_type 124 125 # Relaxation curve-fitting pages. 126 if self.relax_fit_flag: 127 # The relax_fit.relax_time page. 128 page = uf_store['relax_fit.relax_time'].create_page(self, sync=True) 129 self.page_indices['relax_time'] = self.add_page(page, skip_button=False, proceed_on_error=False) 130 page.on_init = self.wizard_update_relax_fit_relax_time 131 132 # Reset the cursor. 133 if wx.IsBusy(): 134 wx.EndBusyCursor() 135 136 # Run the wizard. 137 self.run()
138 139
141 """Set the page after the error type choice. 142 143 @return: The index of the next page, which is the current page index plus one. 144 @rtype: int 145 """ 146 147 # Go to the spectrum.baseplane_rmsd page. 148 if self.page_error_type.selection == 'rmsd': 149 return self.page_indices['rmsd'] 150 151 # Go to the spectrum.replicated page. 152 elif self.page_error_type.selection == 'repl': 153 return self.page_indices['repl']
154 155
156 - def wizard_page_after_repl(self):
157 """Set the page that comes after the spectrum.replicated page. 158 159 @return: The index of the next page. 160 @rtype: int 161 """ 162 163 # Go to the spectrum.integration_points page. 164 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 165 if int_method != 'height' and self.page_error_type.selection == 'rmsd': 166 return self.page_indices['pts'] 167 168 # Skip to the noe.spectrum_type page. 169 elif self.noe_flag: 170 return self.page_indices['spectrum_type'] 171 172 # Skip to the relax_fit.relax_time page. 173 elif self.relax_fit_flag: 174 return self.page_indices['relax_time'] 175 176 # Nothing left, so run off the end. 177 else: 178 return self._num_pages + 1
179 180
181 - def wizard_page_after_rmsd(self):
182 """Set the page that comes after the spectrum.baseplane_rmsd page. 183 184 @return: The index of the next page. 185 @rtype: int 186 """ 187 188 # Go to the spectrum.integration_points page. 189 int_method = gui_to_str(self.page_intensity.uf_args['int_method'].GetValue()) 190 if int_method != 'height': 191 return self.page_indices['pts'] 192 193 # Skip to the noe.spectrum_type page. 194 elif self.noe_flag: 195 return self.page_indices['spectrum_type'] 196 197 # Skip to the relax_fit.relax_time page. 198 elif self.relax_fit_flag: 199 return self.page_indices['relax_time'] 200 201 # Nothing left, so run off the end. 202 else: 203 return self._num_pages + 1
204 205
206 - def wizard_update_ids(self, page_key=None, arg_key='spectrum_id', index=None):
207 """Update the spectrum ID on the page specified by the key based on previous data. 208 209 @keyword page_key: The key of the page to update. 210 @type page_key: str 211 @keyword arg_key: The key of the page argument to change to the spectrum ID. 212 @type arg_key: str 213 @keyword index: The index for list type structures. 214 @type index: None or int 215 """ 216 217 # The spectrum.read_intensities page. 218 page = self.get_page(self.page_indices['read']) 219 220 # Set the spectrum ID. 221 id = page.uf_args['spectrum_id'].GetValue() 222 223 # Handle list arguments. 224 if isinstance(id, list): 225 # If an empty list is encountered, exit this method without doing anything. 226 if id == []: 227 return 228 229 # Use only the first element. 230 id = id[0] 231 232 # Set the ID in the page. 233 page = self.get_page(self.page_indices[page_key]) 234 if index == None: 235 page.uf_args[arg_key].SetValue(id) 236 else: 237 page.uf_args[arg_key].SetValue(value=id, index=index)
238 239
241 """Update the noe.spectrum_type page based on previous data.""" 242 243 # Update the spectrum ID. 244 self.wizard_update_ids(page_key='spectrum_type')
245 246
247 - def wizard_update_pts(self):
248 """Update the spectrum.replicated page based on previous data.""" 249 250 # Update the spectrum ID. 251 self.wizard_update_ids(page_key='pts')
252 253
255 """Update the relax_fit.relax_time page based on previous data.""" 256 257 # Update the spectrum ID. 258 self.wizard_update_ids(page_key='relax_time')
259 260
261 - def wizard_update_repl(self):
262 """Update the spectrum.replicated page based on previous data.""" 263 264 # Update the spectrum ID. 265 self.wizard_update_ids(page_key='repl', arg_key='spectrum_ids', index=0)
266 267
268 - def wizard_update_rmsd(self):
269 """Update the spectrum.baseplane_rmsd page based on previous data.""" 270 271 # Update the spectrum ID. 272 self.wizard_update_ids(page_key='rmsd')
273 274 275
276 -class Spectral_error_type_page(Wiz_page):
277 """The peak intensity reading wizard page for specifying the type of error to be used.""" 278 279 # Class variables. 280 image_path = WIZARD_IMAGE_PATH + 'spectrum' + sep + 'spectrum_200.png' 281 title = "Specify the type of error to be used" 282 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." 283 uf_path = ['spectrum', 'error_analysis'] 284
285 - def _on_select(self, event):
286 """Handle the radio button switching. 287 288 @param event: The wx event. 289 @type event: wx event 290 """ 291 292 # The button. 293 button = event.GetEventObject() 294 295 # RMSD. 296 if button == self.radio_rmsd: 297 self.selection = 'rmsd' 298 elif button == self.radio_repl: 299 self.selection = 'repl'
300 301
302 - def add_contents(self, sizer):
303 """Add the specific GUI elements. 304 305 @param sizer: A sizer object. 306 @type sizer: wx.Sizer instance 307 """ 308 309 # A box sizer for placing the box sizer in. 310 sizer2 = wx.BoxSizer(wx.HORIZONTAL) 311 sizer.Add(sizer2, 1, wx.ALL|wx.EXPAND, 0) 312 313 # Bottom spacing. 314 sizer.AddStretchSpacer() 315 316 # A bit of indentation. 317 sizer2.AddStretchSpacer() 318 319 # A vertical sizer for the radio buttons. 320 sizer_radio = wx.BoxSizer(wx.VERTICAL) 321 sizer2.Add(sizer_radio, 1, wx.ALL|wx.EXPAND, 0) 322 323 # The RMSD radio button. 324 self.radio_rmsd = wx.RadioButton(self, -1, "Baseplane RMSD.", style=wx.RB_GROUP) 325 sizer_radio.Add(self.radio_rmsd, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 326 327 # Spacing. 328 sizer_radio.AddSpacer(10) 329 330 # The replicated spectra radio button. 331 self.radio_repl = wx.RadioButton(self, -1, "Replicated spectra.") 332 sizer_radio.Add(self.radio_repl, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 333 334 # Bind the buttons. 335 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_rmsd) 336 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_repl) 337 338 # Right side spacing. 339 sizer2.AddStretchSpacer(3) 340 341 # Bottom spacing. 342 sizer.AddStretchSpacer() 343 344 # Set the default selection. 345 self.selection = 'rmsd'
346 347
348 - def add_desc(self, sizer, max_y=520):
349 """Add the description to the dialog. 350 351 @param sizer: A sizer object. 352 @type sizer: wx.Sizer instance 353 @keyword max_y: The maximum height, in number of pixels, for the description. 354 @type max_y: int 355 """ 356 357 # Initialise. 358 spacing = 15 359 360 # A line with spacing. 361 sizer.AddSpacer(5) 362 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 363 sizer.AddSpacer(5) 364 365 # Create a scrolled panel. 366 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc") 367 368 # A sizer for the panel. 369 panel_sizer = wx.BoxSizer(wx.VERTICAL) 370 371 # Initialise the text elements. 372 tot_y = 0 373 text_elements = [] 374 text_types = [] 375 376 # The wrapped text. 377 text = wx.StaticText(panel, -1, self.main_text, style=wx.TE_MULTILINE) 378 text.SetFont(font.normal) 379 text.Wrap(self._main_size - 20) 380 text_elements.append(text) 381 text_types.append('title') 382 383 # The text size, then spacing. 384 x, y = text.GetSizeTuple() 385 tot_y += y 386 tot_y += spacing 387 388 # Get the spectrum.error_analysis user function data object. 389 uf_data = uf_info.get_uf('spectrum.error_analysis') 390 391 # The description sections. 392 if uf_data.desc != None: 393 # Loop over the sections. 394 for i in range(len(uf_data.desc)): 395 # Alias. 396 desc = uf_data.desc[i] 397 398 # Skip the prompt examples. 399 if desc.get_title() == 'Prompt examples': 400 continue 401 402 # Loop over the text elements. 403 for type, element in desc.element_loop(title=True): 404 # The text version of the elements. 405 text = '' 406 if isinstance(element, str): 407 text = element 408 409 # Format the tables. 410 if type == 'table': 411 text = format_table(uf_tables.get_table(element)) 412 413 # Format the lists. 414 elif type == 'list': 415 # Loop over the list elements. 416 for j in range(len(element)): 417 text += " - %s\n" % element[j] 418 419 # Format the item lists. 420 elif type == 'item list': 421 # Loop over the list elements. 422 for j in range(len(element)): 423 # No item. 424 if element[j][0] in [None, '']: 425 text += " %s\n" % element[j][1] 426 else: 427 text += " %s: %s\n" % (element[j][0], element[j][1]) 428 429 # The text object. 430 text_obj = wx.StaticText(panel, -1, text, style=wx.TE_MULTILINE) 431 432 # Format. 433 if type == 'title': 434 text_obj.SetFont(font.subtitle) 435 elif type == 'paragraph': 436 text_obj.SetFont(font.normal) 437 elif type in ['table', 'verbatim']: 438 text_obj.SetFont(font.modern_small) 439 else: 440 text_obj.SetFont(font.normal) 441 442 # Wrap the paragraphs and lists (with spacing for scrollbars). 443 if type in ['paragraph', 'list', 'item list']: 444 text_obj.Wrap(self._main_size - 20) 445 446 # The text size. 447 x, y = text_obj.GetSizeTuple() 448 tot_y += y 449 450 # The spacing after each element (except the last). 451 tot_y += spacing 452 453 # The spacing before each section (not including the first). 454 if i != 0 and type == 'title': 455 tot_y += spacing 456 457 # Append the text objects. 458 text_elements.append(text_obj) 459 text_types.append(type) 460 461 # Some extra space for who knows what?! 462 tot_y -= spacing 463 tot_y += 20 464 465 # Set the panel size - scrolling needed. 466 if tot_y > max_y: 467 panel.SetInitialSize((self._main_size, max_y)) 468 469 # Set the panel size - no scrolling. 470 else: 471 panel.SetInitialSize((self._main_size, tot_y)) 472 473 # Add the text. 474 n = len(text_elements) 475 for i in range(n): 476 # Spacing before each section (not including the first). 477 if i > 1 and text_types[i] == 'title': 478 panel_sizer.AddSpacer(spacing) 479 480 # The text. 481 panel_sizer.Add(text_elements[i], 0, wx.ALIGN_LEFT, 0) 482 483 # Spacer after all sections (except the end). 484 if i != n - 1: 485 panel_sizer.AddSpacer(spacing) 486 487 # Set up and add the panel to the sizer. 488 panel.SetSizer(panel_sizer) 489 panel.SetAutoLayout(1) 490 panel.SetupScrolling(scroll_x=False, scroll_y=True) 491 sizer.Add(panel, 0, wx.ALL|wx.EXPAND) 492 493 # A line with spacing. 494 sizer.AddSpacer(5) 495 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 496 sizer.AddSpacer(5)
497