Package gui :: Package components :: Module spectrum
[hide private]
[frames] | no frames]

Source Code for Module gui.components.spectrum

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009-2011 Michael Bieri                                       # 
  4  # Copyright (C) 2010-2012 Edward d'Auvergne                                   # 
  5  #                                                                             # 
  6  # This file is part of the program relax.                                     # 
  7  #                                                                             # 
  8  # relax 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 2 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # relax 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 relax; if not, write to the Free Software                        # 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """Module containing the classes for GUI components involving spectral data.""" 
 26   
 27  # Python module imports. 
 28  import wx 
 29  import wx.lib.buttons 
 30   
 31  # relax module imports. 
 32  from status import Status; status = Status() 
 33  from generic_fns.spectrum import replicated_flags, replicated_ids 
 34   
 35  # relax GUI module imports. 
 36  from gui.components.menu import build_menu_item 
 37  from gui.fonts import font 
 38  from gui.misc import add_border, float_to_gui, gui_to_str, str_to_gui 
 39  from gui import paths 
 40  from gui.user_functions import User_functions; user_functions = User_functions() 
 41   
 42   
43 -class Spectra_list:
44 """The GUI element for listing loaded spectral data.""" 45
46 - def __init__(self, gui=None, parent=None, box=None, id=None, fn_add=None, buttons=True):
47 """Build the spectral list GUI element. 48 49 @keyword gui: The main GUI object. 50 @type gui: wx.Frame instance 51 @keyword parent: The parent GUI element that this is to be attached to (the panel object). 52 @type parent: wx object 53 @keyword data: The data storage container. 54 @type data: class instance 55 @keyword box: The vertical box sizer to pack this GUI component into. 56 @type box: wx.BoxSizer instance 57 @keyword id: A unique identification string. This is used to register the update method with the GUI user function observer object. 58 @type id: str 59 @keyword fn_add: The function to execute when clicking on the 'Add' button. 60 @type fn_add: func 61 @keyword buttons: A flag which if True will display the buttons at the top. 62 @type buttons: bool 63 """ 64 65 # Store the arguments. 66 self.gui = gui 67 self.parent = parent 68 self.fn_add = fn_add 69 70 # GUI variables. 71 self.spacing = 5 72 self.border = 5 73 self.height_buttons = 40 74 75 # First create a panel (to allow for tooltips on the buttons). 76 self.panel = wx.Panel(self.parent) 77 box.Add(self.panel, 0, wx.ALL|wx.EXPAND, 0) 78 79 # Add a sizer to the panel. 80 panel_sizer = wx.BoxSizer(wx.VERTICAL) 81 self.panel.SetSizer(panel_sizer) 82 83 # A static box to hold all the widgets, and its sizer. 84 stat_box = wx.StaticBox(self.panel, -1, "Spectra list") 85 stat_box.SetFont(font.subtitle) 86 sub_sizer = wx.StaticBoxSizer(stat_box, wx.VERTICAL) 87 88 # Add the sizer to the static box and the static box to the main box. 89 panel_sizer.Add(sub_sizer, 0, wx.ALL|wx.EXPAND, 0) 90 91 # Add a border. 92 box_centre = add_border(sub_sizer, border=self.border) 93 94 # Add buttons. 95 if buttons: 96 self.add_buttons(box_centre) 97 98 # Initialise the element. 99 box_centre.AddSpacer(self.spacing) 100 self.init_element(box_centre) 101 102 # Build the element. 103 self.build_element() 104 105 # Initialise observer name. 106 self.name = 'spectra list: %s' % id 107 108 # Register the element for updating when a user function completes. 109 self.observer_register()
110 111
112 - def Enable(self, enable=True):
113 """Enable or disable the element. 114 115 @keyword enable: The flag specifying if the element should be enabled or disabled. 116 @type enable: bool 117 """ 118 119 # Call the button's method. 120 self.button_add.Enable(enable) 121 self.button_delete.Enable(enable)
122 123
124 - def add_buttons(self, sizer):
125 """Add the buttons for peak list manipulation. 126 127 @param sizer: The sizer element to pack the buttons into. 128 @type sizer: wx.BoxSizer instance 129 """ 130 131 # Button Sizer 132 button_sizer = wx.BoxSizer(wx.HORIZONTAL) 133 sizer.Add(button_sizer, 0, wx.ALL|wx.EXPAND, 0) 134 135 # Add button. 136 self.button_add = wx.lib.buttons.ThemedGenBitmapTextButton(self.panel, -1, None, " Add") 137 self.button_add.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.add, wx.BITMAP_TYPE_ANY)) 138 self.button_add.SetFont(font.normal) 139 self.button_add.SetSize((80, self.height_buttons)) 140 button_sizer.Add(self.button_add, 0, 0, 0) 141 self.gui.Bind(wx.EVT_BUTTON, self.fn_add, self.button_add) 142 self.button_add.SetToolTipString("Read a spectral data file.") 143 144 # Delete button. 145 self.button_delete = wx.lib.buttons.ThemedGenBitmapTextButton(self.panel, -1, None, " Delete") 146 self.button_delete.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.list_remove, wx.BITMAP_TYPE_ANY)) 147 self.button_delete.SetFont(font.normal) 148 self.button_delete.SetSize((80, self.height_buttons)) 149 button_sizer.Add(self.button_delete, 0, 0, 0) 150 self.gui.Bind(wx.EVT_BUTTON, self.data_delete, self.button_delete) 151 self.button_delete.SetToolTipString("Delete loaded relaxation data from the relax data store.")
152 153
154 - def build_element(self):
155 """Build the spectra listing GUI element.""" 156 157 # Execution lock, so do nothing. 158 if status.exec_lock.locked(): 159 return 160 161 # Build the GUI element in a thread safe way. 162 wx.CallAfter(self.build_element_safe)
163 164
165 - def build_element_safe(self):
166 """Build the spectra listing GUI element in a thread safe wx.CallAfter call.""" 167 168 # First freeze the element, so that the GUI element doesn't update until the end. 169 self.element.Freeze() 170 171 # Initialise the column index for the data. 172 index = 1 173 174 # Delete the rows and columns. 175 self.element.DeleteAllItems() 176 self.element.DeleteAllColumns() 177 178 # Initialise to a single column. 179 self.element.InsertColumn(0, str_to_gui("Spectrum ID string")) 180 181 # Expand the number of rows to match the number of spectrum IDs, and add the IDs. 182 n = 0 183 if hasattr(cdp, 'spectrum_ids'): 184 # The number of IDs. 185 n = len(cdp.spectrum_ids) 186 187 # Set the IDs. 188 for i in range(n): 189 self.element.InsertStringItem(i, str_to_gui(cdp.spectrum_ids[i])) 190 191 # The NOE spectrum type. 192 if self.noe_spectrum_type(index): 193 index += 1 194 195 # The relaxation times. 196 if self.relax_times(index): 197 index += 1 198 199 # The replicated spectra. 200 if self.replicates(index): 201 index += 1 202 203 # Post a size event to get the scroll panel to update correctly. 204 event = wx.PyCommandEvent(wx.EVT_SIZE.typeId, self.parent.GetId()) 205 wx.PostEvent(self.parent.GetEventHandler(), event) 206 207 # Size the columns. 208 self.size_cols() 209 210 # Set the minimum height. 211 height = self.height_char * (n + 1) + 50 212 self.element.SetMinSize((-1, height)) 213 self.element.Layout() 214 215 # Unfreeze. 216 self.element.Thaw()
217 218
219 - def data_delete(self, event):
220 """Launch the spectrum.delete user function. 221 222 @param event: The wx event. 223 @type event: wx event 224 """ 225 226 # The current selection. 227 item = self.element.GetFirstSelected() 228 229 # No selection. 230 if item == -1: 231 id = None 232 233 # Selected item. 234 else: 235 # The spectrum ID. 236 id = gui_to_str(self.element.GetItemText(item)) 237 238 # Launch the dialog. 239 user_functions.spectrum.delete(spectrum_id=id)
240 241
242 - def delete(self):
243 """Unregister the class.""" 244 245 # Unregister the observer methods. 246 self.observer_register(remove=True)
247 248
249 - def init_element(self, sizer):
250 """Initialise the GUI element for the spectra listing. 251 252 @param sizer: The sizer element to pack the element into. 253 @type sizer: wx.BoxSizer instance 254 """ 255 256 # List of peak list file names and relaxation time. 257 self.element = wx.ListCtrl(self.panel, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT) 258 259 # Properties. 260 self.element.SetFont(font.normal) 261 262 # Store the base heights. 263 self.height_char = self.element.GetCharHeight() 264 265 # Bind some events. 266 self.element.Bind(wx.EVT_SIZE, self.resize) 267 self.element.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.on_right_click) # For wxMSW! 268 self.element.Bind(wx.EVT_RIGHT_UP, self.on_right_click) # For wxGTK! 269 270 # Add list to sizer. 271 sizer.Add(self.element, 0, wx.ALL|wx.EXPAND, 0)
272 273
274 - def observer_register(self, remove=False):
275 """Register and unregister methods with the observer objects. 276 277 @keyword remove: If set to True, then the methods will be unregistered. 278 @type remove: False 279 """ 280 281 # Register. 282 if not remove: 283 status.observers.gui_uf.register(self.name, self.build_element) 284 285 # Unregister. 286 else: 287 status.observers.gui_uf.unregister(self.name)
288 289
290 - def on_right_click(self, event):
291 """Pop up menu for the right click. 292 293 @param event: The wx event. 294 @type event: wx event 295 """ 296 297 # Execution lock, so do nothing. 298 if status.exec_lock.locked(): 299 return 300 301 # New menu entry. 302 if not hasattr(self, 'popup_id_del'): 303 # ID number. 304 self.popup_id_del = wx.NewId() 305 306 # Bind clicks. 307 self.element.Bind(wx.EVT_MENU, self.data_delete, id=self.popup_id_del) 308 309 # Initialise the menu. 310 menu = wx.Menu() 311 312 # Add the delete entry. 313 menu.AppendItem(build_menu_item(menu, id=self.popup_id_del, text="&Delete", icon=paths.icon_16x16.remove)) 314 315 # Pop up the menu. 316 self.element.PopupMenu(menu) 317 menu.Destroy()
318 319
320 - def resize(self, event):
321 """Catch the resize to allow the element to be resized. 322 323 @param event: The wx event. 324 @type event: wx event 325 """ 326 327 # Set the column sizes. 328 self.size_cols() 329 330 # Continue with the normal resizing. 331 event.Skip()
332 333
334 - def noe_spectrum_type(self, index):
335 """Add the NOE spectral type info to the element. 336 337 @param index: The column index for the data. 338 @type index: int 339 @return: True if a spectrum type exists, False otherwise. 340 @rtype: bool 341 """ 342 343 # No type info. 344 if not hasattr(cdp, 'spectrum_type') or not len(cdp.spectrum_type): 345 return False 346 347 # Append a column. 348 self.element.InsertColumn(index, str_to_gui("NOE spectrum type")) 349 350 # Translation table. 351 table = { 352 'sat': 'Saturated', 353 'ref': 'Reference' 354 } 355 356 # Set the values. 357 for i in range(len(cdp.spectrum_ids)): 358 # No value. 359 if cdp.spectrum_ids[i] not in cdp.spectrum_type.keys(): 360 continue 361 362 # Set the value. 363 self.element.SetStringItem(i, index, str_to_gui(table[cdp.spectrum_type[cdp.spectrum_ids[i]]])) 364 365 # Successful. 366 return True
367 368
369 - def relax_times(self, index):
370 """Add the relaxation delay time info to the element. 371 372 @param index: The column index for the data. 373 @type index: int 374 @return: True if relaxation times exist, False otherwise. 375 @rtype: bool 376 """ 377 378 # No type info. 379 if not hasattr(cdp, 'relax_times') or not len(cdp.relax_times): 380 return False 381 382 # Append a column. 383 self.element.InsertColumn(index, str_to_gui("Delay times")) 384 385 # Set the values. 386 for i in range(len(cdp.spectrum_ids)): 387 # No value. 388 if cdp.spectrum_ids[i] not in cdp.relax_times.keys(): 389 continue 390 391 # Set the value. 392 self.element.SetStringItem(i, index, float_to_gui(cdp.relax_times[cdp.spectrum_ids[i]])) 393 394 # Successful. 395 return True
396 397
398 - def replicates(self, index):
399 """Add the replicated spectra info to the element. 400 401 @param index: The column index for the data. 402 @type index: int 403 @return: True if relaxation times exist, False otherwise. 404 @rtype: bool 405 """ 406 407 # No type info. 408 if not hasattr(cdp, 'replicates') or not len(cdp.replicates): 409 return False 410 411 # Replicated spectra. 412 repl = replicated_flags() 413 414 # Append a column. 415 self.element.InsertColumn(index, str_to_gui("Replicate IDs")) 416 417 # Set the values. 418 for i in range(len(cdp.spectrum_ids)): 419 # No replicates. 420 if not repl[cdp.spectrum_ids[i]]: 421 continue 422 423 # The replicated spectra. 424 id_list = replicated_ids(cdp.spectrum_ids[i]) 425 426 # Convert to a string. 427 text = '' 428 for j in range(len(id_list)): 429 # Add the id. 430 text = "%s%s" % (text, id_list[j]) 431 432 # Separator. 433 if j < len(id_list)-1: 434 text = "%s, " % text 435 436 # Set the value. 437 self.element.SetStringItem(i, index, str_to_gui(text)) 438 439 # Successful. 440 return True
441 442
443 - def size_cols(self):
444 """Set the column sizes.""" 445 446 # The element size. 447 x, y = self.element.GetSize() 448 449 # Number of columns. 450 n = self.element.GetColumnCount() 451 452 # Set to equal sizes. 453 if n == 0: 454 width = x 455 else: 456 width = int(x / n) 457 458 # Set the column sizes. 459 for i in range(n): 460 self.element.SetColumnWidth(i, width)
461