Package gui :: Package analyses :: Module base
[hide private]
[frames] | no frames]

Source Code for Module gui.analyses.base

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009 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 base class for all frames.""" 
 26   
 27  # Python module imports. 
 28  from os import sep 
 29  import wx 
 30  from wx.lib import buttons 
 31  from wx.lib import scrolledpanel 
 32    
 33  # relax module imports. 
 34  from generic_fns.mol_res_spin import count_spins 
 35  from generic_fns.pipes import cdp_name 
 36  from user_functions.data import Uf_info; uf_info = Uf_info() 
 37  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 38   
 39  # relax GUI module imports. 
 40  from gui import paths 
 41  from gui.analyses.elements import Text_ctrl 
 42  from gui.fonts import font 
 43  from gui.misc import add_border, format_table 
 44  from gui.string_conv import int_to_gui, str_to_gui 
 45  from gui.wizard import Wiz_page 
 46   
 47   
48 -class Base_analysis(wx.lib.scrolledpanel.ScrolledPanel):
49 """The base class for all frames.""" 50 51 # Hard coded variables. 52 border = 10 53 size_graphic_panel = 200 54 spacer_horizontal = 5 55 width_text = 240 56 width_button = 100 57 width_main_separator = 40 58
59 - def __init__(self, parent, id=wx.ID_ANY, pos=None, size=None, style=None, name=None, gui=None):
60 """Initialise the scrolled window. 61 62 @param parent: The parent wx element. 63 @type parent: wx object 64 @keyword id: The unique ID number. 65 @type id: int 66 @keyword pos: The position. 67 @type pos: wx.Size object 68 @keyword size: The size. 69 @type size: wx.Size object 70 @keyword style: The style. 71 @type style: int 72 @keyword name: The name for the panel. 73 @type name: unicode 74 """ 75 76 # Execute the base class method. 77 super(Base_analysis, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name) 78 79 # Determine the size of the scrollers. 80 self.width_vscroll = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X) 81 82 # Pack a sizer into the panel. 83 box_main = wx.BoxSizer(wx.HORIZONTAL) 84 self.SetSizer(box_main) 85 86 # Build the central sizer, with borders. 87 box_centre = add_border(box_main, border=self.border, packing=wx.HORIZONTAL) 88 89 # Build and pack the main sizer box, then add it to the automatic model-free analysis frame. 90 self.build_main_box(box_centre) 91 92 # Set up the scrolled panel. 93 self.SetAutoLayout(True) 94 self.SetupScrolling(scroll_x=False, scroll_y=True) 95 96 # Bind resize events. 97 self.Bind(wx.EVT_SIZE, self.resize)
98 99
100 - def add_button_open(self, box, parent, icon=paths.icon_16x16.open, text=" Change", fn=None, width=-1, height=-1):
101 """Add a button for opening and changing files and directories. 102 103 @param box: The box element to pack the control into. 104 @type box: wx.BoxSizer instance 105 @param parent: The parent GUI element. 106 @type parent: wx object 107 @keyword icon: The path of the icon to use for the button. 108 @type icon: str 109 @keyword text: The text to display on the button. 110 @type text: str 111 @keyword fn: The function or method to execute when clicking on the button. 112 @type fn: func 113 @keyword width: The minimum width of the control. 114 @type width: int 115 @keyword height: The minimum height of the control. 116 @type height: int 117 @return: The button. 118 @rtype: wx.lib.buttons.ThemedGenBitmapTextButton instance 119 """ 120 121 # The button. 122 button = buttons.ThemedGenBitmapTextButton(parent, -1, None, str_to_gui(text)) 123 button.SetBitmapLabel(wx.Bitmap(icon, wx.BITMAP_TYPE_ANY)) 124 125 # The font and button properties. 126 button.SetMinSize((width, height)) 127 button.SetFont(font.normal) 128 129 # Bind the click. 130 self.gui.Bind(wx.EVT_BUTTON, fn, button) 131 132 # Add the button to the box. 133 box.Add(button, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 134 135 # Return the button. 136 return button
137 138
139 - def add_execute_relax(self, box, method):
140 """Create and add the relax execution GUI element to the given box. 141 142 @param box: The box element to pack the relax execution GUI element into. 143 @type box: wx.BoxSizer instance 144 @param method: The method to execute when the button is clicked. 145 @type method: method 146 @return: The button. 147 @rtype: wx.lib.buttons.ThemedGenBitmapTextButton instance 148 """ 149 150 # A horizontal sizer for the contents. 151 sizer = wx.BoxSizer(wx.HORIZONTAL) 152 153 # A unique ID. 154 id = wx.NewId() 155 156 # The button. 157 button = buttons.ThemedGenBitmapTextButton(self, id, None, " Execute relax") 158 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'relax_start.gif', wx.BITMAP_TYPE_ANY)) 159 button.SetFont(font.normal) 160 self.gui.Bind(wx.EVT_BUTTON, method, button) 161 sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0) 162 163 # Add the element to the box. 164 box.Add(sizer, 0, wx.ALIGN_RIGHT, 0) 165 166 # Return the button. 167 return button
168 169
170 - def add_spin_control(self, box, parent, text='', min=None, max=None, control=wx.SpinCtrl, width=-1, height=-1):
171 """Add a text control field to the box. 172 173 @param box: The box element to pack the control into. 174 @type box: wx.BoxSizer instance 175 @param parent: The parent GUI element. 176 @type parent: wx object 177 @keyword text: The default text of the control. 178 @type text: str 179 @keyword min: The minimum value allowed. 180 @type min: int 181 @keyword max: The maximum value allowed. 182 @type max: int 183 @keyword control: The control class to use. 184 @type control: wx.TextCtrl derived class 185 @keyword width: The minimum width of the control. 186 @type width: int 187 @keyword height: The minimum height of the control. 188 @type height: int 189 @return: The text control object. 190 @rtype: control object 191 """ 192 193 # The control. 194 field = control(parent, -1, text, min=min, max=max) 195 196 # The font and control properties. 197 field.SetMinSize((width, height)) 198 field.SetFont(font.normal) 199 200 # Add the control to the box. 201 box.Add(field, 1, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 202 203 # Return the text field. 204 return field
205 206
207 - def add_spin_systems(self, box, parent):
208 """Add a special control for spin systems. 209 210 Only one of these per analysis are allowed. 211 212 @param box: The box element to pack the control into. 213 @type box: wx.BoxSizer instance 214 @param parent: The parent GUI element. 215 @type parent: wx object 216 """ 217 218 # Add the element. 219 self.spin_systems = Text_ctrl(box, self, text="Spin systems", button_text=" Spin editor", default=self.spin_count(), icon=paths.icon_16x16.spin, fn=self.launch_spin_editor, editable=False, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal)
220 221
222 - def add_static_text(self, box, parent, text='', width=-1, height=-1):
223 """Add a text control field to the box. 224 225 @param box: The box element to pack the control into. 226 @type box: wx.BoxSizer instance 227 @param parent: The parent GUI element. 228 @type parent: wx object 229 @keyword text: The default text of the control. 230 @type text: str 231 @keyword width: The minimum width of the control. 232 @type width: int 233 @keyword height: The minimum height of the control. 234 @type height: int 235 @return: The label. 236 @rtype: wx.StaticText instance 237 """ 238 239 # The label. 240 label = wx.StaticText(parent, -1, text) 241 242 # The font and label properties. 243 label.SetMinSize((width, height)) 244 label.SetFont(font.normal) 245 246 # Add the label to the box. 247 box.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 248 249 # Return the label. 250 return label
251 252
253 - def add_subtitle(self, box, text):
254 """Create and add the subtitle. 255 256 @param box: The box element to pack the subtitle into. 257 @type box: wx.BoxSizer instance 258 @param text: The text of the subtitle. 259 @type text: str 260 """ 261 262 # The title. 263 label = wx.StaticText(self, -1, text) 264 265 # The font properties. 266 label.SetFont(font.subtitle) 267 268 # Add the subtitle to the box, with spacing. 269 box.AddSpacer(20) 270 box.Add(label) 271 box.AddSpacer(5)
272 273
274 - def add_subsubtitle(self, box, text):
275 """Create and add the subsubtitle. 276 277 @param box: The box element to pack the text into. 278 @type box: wx.BoxSizer instance 279 @param text: The text of the subsubtitle. 280 @type text: str 281 """ 282 283 # The text. 284 label = wx.StaticText(self, -1, text) 285 286 # The font properties. 287 label.SetFont(font.normal) 288 289 # Add the text to the box, with spacing. 290 box.AddSpacer(10) 291 box.Add(label)
292 293
294 - def add_text_control(self, box, parent, text='', control=wx.TextCtrl, width=-1, height=-1, editable=True):
295 """Add a text control field to the box. 296 297 @param box: The box element to pack the control into. 298 @type box: wx.BoxSizer instance 299 @param parent: The parent GUI element. 300 @type parent: wx object 301 @keyword text: The default text of the control. 302 @type text: str 303 @keyword control: The control class to use. 304 @type control: wx.TextCtrl derived class 305 @keyword width: The minimum width of the control. 306 @type width: int 307 @keyword height: The minimum height of the control. 308 @type height: int 309 @keyword editable: A flag specifying if the control is editable or not. 310 @type editable: bool 311 @return: The text control object. 312 @rtype: control object 313 """ 314 315 # The control. 316 field = control(parent, -1, str_to_gui(text)) 317 318 # The font and control properties. 319 field.SetMinSize((width, height)) 320 field.SetFont(font.normal) 321 322 # Editable (change the colour if not). 323 field.SetEditable(editable) 324 if not editable: 325 colour = self.GetBackgroundColour() 326 field.SetOwnBackgroundColour(colour) 327 328 # Add the control to the box. 329 box.Add(field, 1, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 330 331 # Return the text field. 332 return field
333 334
335 - def add_title(self, box, text):
336 """Create and add the frame title. 337 338 @param box: The box element to pack the frame title into. 339 @type box: wx.BoxSizer instance 340 @param text: The text of the title. 341 @type text: str 342 """ 343 344 # The title. 345 label = wx.StaticText(self, -1, text) 346 347 # The font properties. 348 label.SetFont(font.title) 349 350 # Pack the title, with spacing. 351 box.AddSpacer(10) 352 box.Add(label) 353 box.AddSpacer(5)
354 355
356 - def build_left_box(self):
357 """Construct the left hand box to pack into the automatic Rx analysis frame. 358 359 @return: The left hand box element containing the bitmap. 360 @rtype: wx.BoxSizer instance 361 """ 362 363 # Use a vertical packing of elements. 364 box = wx.BoxSizer(wx.VERTICAL) 365 366 # Convert the bitmap names to a list. 367 if not isinstance(self.bitmap, list): 368 bitmaps = [self.bitmap] 369 else: 370 bitmaps = self.bitmap 371 372 # Add the bitmaps. 373 for i in range(len(bitmaps)): 374 # The bitmap. 375 bitmap = wx.StaticBitmap(self, -1, wx.Bitmap(bitmaps[i], wx.BITMAP_TYPE_ANY)) 376 377 # Add it. 378 box.Add(bitmap, 0, wx.ADJUST_MINSIZE, 10) 379 380 # Return the box. 381 return box
382 383
384 - def build_main_box(self, box):
385 """Construct the highest level box to pack into the automatic analysis frames. 386 387 @param box: The horizontal box element to pack the elements into. 388 @type box: wx.BoxSizer instance 389 """ 390 391 # Build the left hand box and add to the main box. 392 left_box = self.build_left_box() 393 box.Add(left_box, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 0) 394 395 # Central spacer. 396 box.AddSpacer(self.width_main_separator) 397 398 # Build the right hand box and pack it next to the bitmap. 399 right_box = self.build_right_box() 400 box.Add(right_box, 1, wx.ALL|wx.EXPAND, 0)
401 402
403 - def launch_spin_editor(self, event):
404 """The spin editor GUI element. 405 406 @param event: The wx event. 407 @type event: wx event 408 """ 409 410 # Show the molecule, residue, and spin tree window. 411 self.gui.show_tree(None)
412 413
414 - def observer_register(self, remove=False):
415 """Register and unregister methods with the observer objects. 416 417 This is a dummy method. 418 419 420 @keyword remove: If set to True, then the methods will be unregistered. 421 @type remove: False 422 """
423 424
425 - def resize(self, event):
426 """The spin editor GUI element. 427 428 @param event: The wx event. 429 @type event: wx event 430 """ 431 432 # Set the virtual size to have the width of the visible size and the height of the virtual size. 433 x = self.GetSize()[0] - self.width_vscroll 434 y = self.GetVirtualSize()[1] 435 self.SetVirtualSize((x, y))
436 437
438 - def spin_count(self):
439 """Count the number of loaded spins, returning a string formatted as 'xxx spins loaded'. 440 441 @return: The number of loaded spins in the format 'xxx spins loaded'. 442 @rtype: str 443 """ 444 445 # The data pipe. 446 if hasattr(self.data, 'pipe_name'): 447 pipe = self.data.pipe_name 448 else: 449 pipe = cdp_name() 450 451 # The count. 452 num = count_spins(pipe=pipe) 453 454 # Return the formatted string. 455 return "%s spins loaded and selected" % num
456 457
458 - def update_spin_count(self):
459 """Update the spin count.""" 460 461 # Set the new value. 462 wx.CallAfter(self.spin_systems.SetValue, str_to_gui(self.spin_count()))
463 464 465
466 -class Spectral_error_type_page(Wiz_page):
467 """The NOE peak intensity reading wizard page for specifying the type of error to be used.""" 468 469 # Class variables. 470 image_path = paths.WIZARD_IMAGE_PATH + 'spectrum' + sep + 'spectrum_200.png' 471 title = "Specify the type of error to be used" 472 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." 473 uf_path = ['spectrum', 'error_analysis'] 474
475 - def _on_select(self, event):
476 """Handle the radio button switching. 477 478 @param event: The wx event. 479 @type event: wx event 480 """ 481 482 # The button. 483 button = event.GetEventObject() 484 485 # RMSD. 486 if button == self.radio_rmsd: 487 self.selection = 'rmsd' 488 elif button == self.radio_repl: 489 self.selection = 'repl'
490 491
492 - def add_contents(self, sizer):
493 """Add the specific GUI elements. 494 495 @param sizer: A sizer object. 496 @type sizer: wx.Sizer instance 497 """ 498 499 # A box sizer for placing the box sizer in. 500 sizer2 = wx.BoxSizer(wx.HORIZONTAL) 501 sizer.Add(sizer2, 1, wx.ALL|wx.EXPAND, 0) 502 503 # Bottom spacing. 504 sizer.AddStretchSpacer() 505 506 # A bit of indentation. 507 sizer2.AddStretchSpacer() 508 509 # A vertical sizer for the radio buttons. 510 sizer_radio = wx.BoxSizer(wx.VERTICAL) 511 sizer2.Add(sizer_radio, 1, wx.ALL|wx.EXPAND, 0) 512 513 # The RMSD radio button. 514 self.radio_rmsd = wx.RadioButton(self, -1, "Baseplane RMSD.", style=wx.RB_GROUP) 515 sizer_radio.Add(self.radio_rmsd, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 516 517 # Spacing. 518 sizer_radio.AddSpacer(10) 519 520 # The replicated spectra radio button. 521 self.radio_repl = wx.RadioButton(self, -1, "Replicated spectra.") 522 sizer_radio.Add(self.radio_repl, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 523 524 # Bind the buttons. 525 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_rmsd) 526 self.Bind(wx.EVT_RADIOBUTTON, self._on_select, self.radio_repl) 527 528 # Right side spacing. 529 sizer2.AddStretchSpacer(3) 530 531 # Bottom spacing. 532 sizer.AddStretchSpacer() 533 534 # Set the default selection. 535 self.selection = 'rmsd'
536 537
538 - def add_desc(self, sizer, max_y=520):
539 """Add the description to the dialog. 540 541 @param sizer: A sizer object. 542 @type sizer: wx.Sizer instance 543 @keyword max_y: The maximum height, in number of pixels, for the description. 544 @type max_y: int 545 """ 546 547 # Initialise. 548 spacing = 15 549 550 # A line with spacing. 551 sizer.AddSpacer(5) 552 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 553 sizer.AddSpacer(5) 554 555 # Create a scrolled panel. 556 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc") 557 558 # A sizer for the panel. 559 panel_sizer = wx.BoxSizer(wx.VERTICAL) 560 561 # Initialise the text elements. 562 tot_y = 0 563 text_elements = [] 564 text_types = [] 565 566 # The wrapped text. 567 text = wx.StaticText(panel, -1, self.main_text, style=wx.TE_MULTILINE) 568 text.SetFont(font.normal) 569 text.Wrap(self._main_size - 20) 570 text_elements.append(text) 571 text_types.append('title') 572 573 # The text size, then spacing. 574 x, y = text.GetSizeTuple() 575 tot_y += y 576 tot_y += spacing 577 578 # Get the spectrum.error_analysis user function data object. 579 uf_data = uf_info.get_uf('spectrum.error_analysis') 580 581 # The description sections. 582 if uf_data.desc != None: 583 # Loop over the sections. 584 for i in range(len(uf_data.desc)): 585 # Alias. 586 desc = uf_data.desc[i] 587 588 # Skip the prompt examples. 589 if desc.get_title() == 'Prompt examples': 590 continue 591 592 # Loop over the text elements. 593 for type, element in desc.element_loop(title=True): 594 # The text version of the elements. 595 text = '' 596 if isinstance(element, str): 597 text = element 598 599 # Format the tables. 600 if type == 'table': 601 text = format_table(uf_tables.get_table(element)) 602 603 # Format the lists. 604 elif type == 'list': 605 # Loop over the list elements. 606 for j in range(len(element)): 607 text += " - %s\n" % element[j] 608 609 # Format the item lists. 610 elif type == 'item list': 611 # Loop over the list elements. 612 for j in range(len(element)): 613 # No item. 614 if element[j][0] in [None, '']: 615 text += " %s\n" % element[j][1] 616 else: 617 text += " %s: %s\n" % (element[j][0], element[j][1]) 618 619 # The text object. 620 text_obj = wx.StaticText(panel, -1, text, style=wx.TE_MULTILINE) 621 622 # Format. 623 if type == 'title': 624 text_obj.SetFont(font.subtitle) 625 elif type == 'paragraph': 626 text_obj.SetFont(font.normal) 627 elif type in ['table', 'verbatim']: 628 text_obj.SetFont(font.modern_small) 629 else: 630 text_obj.SetFont(font.normal) 631 632 # Wrap the paragraphs and lists (with spacing for scrollbars). 633 if type in ['paragraph', 'list', 'item list']: 634 text_obj.Wrap(self._main_size - 20) 635 636 # The text size. 637 x, y = text_obj.GetSizeTuple() 638 tot_y += y 639 640 # The spacing after each element (except the last). 641 tot_y += spacing 642 643 # The spacing before each section (not including the first). 644 if i != 0 and type == 'title': 645 tot_y += spacing 646 647 # Append the text objects. 648 text_elements.append(text_obj) 649 text_types.append(type) 650 651 # Some extra space for who knows what?! 652 tot_y -= spacing 653 tot_y += 20 654 655 # Set the panel size - scrolling needed. 656 if tot_y > max_y: 657 panel.SetInitialSize((self._main_size, max_y)) 658 659 # Set the panel size - no scrolling. 660 else: 661 panel.SetInitialSize((self._main_size, tot_y)) 662 663 # Add the text. 664 n = len(text_elements) 665 for i in range(n): 666 # Spacing before each section (not including the first). 667 if i > 1 and text_types[i] == 'title': 668 panel_sizer.AddSpacer(spacing) 669 670 # The text. 671 panel_sizer.Add(text_elements[i], 0, wx.ALIGN_LEFT, 0) 672 673 # Spacer after all sections (except the end). 674 if i != n - 1: 675 panel_sizer.AddSpacer(spacing) 676 677 # Set up and add the panel to the sizer. 678 panel.SetSizer(panel_sizer) 679 panel.SetAutoLayout(1) 680 panel.SetupScrolling(scroll_x=False, scroll_y=True) 681 sizer.Add(panel, 0, wx.ALL|wx.EXPAND) 682 683 # A line with spacing. 684 sizer.AddSpacer(5) 685 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0) 686 sizer.AddSpacer(5)
687