Package gui :: Package spin_viewer :: Module containers
[hide private]
[frames] | no frames]

Source Code for Module gui.spin_viewer.containers

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2010-2013 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """The molecule, residue, and spin containers for the spin viewer.""" 
 24   
 25   
 26  # Python module imports. 
 27  from re import search 
 28  import wx 
 29   
 30  # relax module imports. 
 31  from graphics import WIZARD_IMAGE_PATH 
 32  from gui.misc import bitmap_setup 
 33  from gui.string_conv import str_to_gui 
 34  from lib.compat import unicode 
 35  from pipe_control.mol_res_spin import return_spin 
 36   
 37   
 38   
39 -class Container(wx.Window):
40 """The molecule, residue, and spin container window.""" 41
42 - def __init__(self, gui, parent=None, id=None):
43 """Set up the container GUI element. 44 45 @param gui: The gui object. 46 @type gui: wx object 47 @keyword parent: The parent GUI element that this is to be attached to. 48 @type parent: wx object 49 @keyword id: The ID number. 50 @type id: int 51 """ 52 53 # Store the args. 54 self.gui = gui 55 56 # Execute the base class method. 57 wx.Window.__init__(self, parent, id, style=wx.BORDER_SUNKEN) 58 59 # Set a minimum size for the window. 60 self.SetMinSize((500, 500)) 61 62 # Add a sizer. 63 self.main_sizer = wx.BoxSizer(wx.VERTICAL) 64 self.SetSizer(self.main_sizer) 65 66 # Display the root panel. 67 self.container = Root(self.main_sizer, self) 68 69 # Resizing. 70 self.Bind(wx.EVT_SIZE, self._resize)
71 72
73 - def _resize(self, event):
74 """Resize the tree element. 75 76 @param event: The wx event. 77 @type event: wx event 78 """ 79 80 # Re-perform the window layout. 81 self.Layout() 82 self.Refresh()
83 84
85 - def display(self, info):
86 """Display the info for the selected container. 87 88 @param info: The information list consisting of the container type ('root', 'mol', 'res', or 'spin'), the molecule name, the residue number, the residue name, the spin number, and the spin name. The name and number information is dropped when not needed. 89 @type info: list of str and int 90 """ 91 92 # Destroy all the original contents. 93 self.main_sizer.Clear(deleteWindows=True) 94 95 # The root window display. 96 if info == 'root' or info == None: 97 self.container = Root(self.main_sizer, self) 98 99 # The molecule container display. 100 elif info['type'] == 'mol': 101 self.container = Molecule(self.main_sizer, self, mol_name=info['mol_name'], mol_id=info['id'], select=info['select']) 102 103 # The residue container display. 104 elif info['type'] == 'res': 105 self.container = Residue(self.main_sizer, self, mol_name=info['mol_name'], res_num=info['res_num'], res_name=info['res_name'], res_id=info['id'], select=info['select']) 106 107 # The spin container display. 108 elif info['type'] == 'spin': 109 self.container = Spin(self.main_sizer, self, mol_name=info['mol_name'], res_num=info['res_num'], res_name=info['res_name'], spin_num=info['spin_num'], spin_name=info['spin_name'], spin_id=info['id'], select=info['select']) 110 111 # Re-perform the window layout. 112 self.Layout() 113 self.Refresh()
114 115 116
117 -class Container_base:
118 """The base class for the molecule, residue, and spin containers.""" 119 120 # Some class variables. 121 border = 10 122
123 - def create_head_text(self, text):
124 """Generate the wx.StaticText object for header text. 125 126 @param text: The text of the subtitle. 127 @type text: str 128 @return: The subtitle object. 129 @rtype: wx.StaticText instance 130 """ 131 132 # Unicode. 133 text = unicode(text) 134 135 # Fix for the '&' character. 136 text = text.replace('&', '&&') 137 138 # The object. 139 obj = wx.StaticText(self.parent, -1, text) 140 141 # Formatting. 142 obj.SetFont(wx.Font(pointSize=12, family=wx.FONTFAMILY_ROMAN, style=wx.ITALIC, weight=wx.NORMAL, face='Times')) 143 144 # Return the object. 145 return obj
146 147
148 - def create_subtitle(self, text):
149 """Generate the subtitle wx.StaticText object. 150 151 @param text: The text of the subtitle. 152 @type text: str 153 @return: The subtitle object. 154 @rtype: wx.StaticText instance 155 """ 156 157 # Unicode. 158 text = unicode(text) 159 160 # Fix for the '&' character. 161 text = text.replace('&', '&&') 162 163 # The object. 164 obj = wx.StaticText(self.parent, -1, text) 165 166 # Formatting. 167 obj.SetFont(wx.Font(pointSize=16, family=wx.FONTFAMILY_ROMAN, style=wx.ITALIC, weight=wx.NORMAL, face='Times')) 168 169 # Return the object. 170 return obj
171 172
173 - def create_title(self, text):
174 """Generate the title wx.StaticText object. 175 176 @param text: The text of the subtitle. 177 @type text: str 178 @return: The subtitle object. 179 @rtype: wx.StaticText instance 180 """ 181 182 # The object. 183 title = wx.StaticText(self.parent, -1, text) 184 185 # Formatting. 186 title.SetFont(wx.Font(pointSize=32, family=wx.FONTFAMILY_ROMAN, style=wx.ITALIC, weight=wx.NORMAL, face='Times')) 187 188 # Return the object. 189 return title
190 191 192
193 -class Molecule(Container_base):
194 """The molecule container.""" 195
196 - def __init__(self, box, parent, mol_name=None, mol_id=None, select=True):
197 """Set up the molecule container. 198 199 @param box: The box sizer element to pack the contents into. 200 @type box: wx object 201 @param parent: The parent GUI element. 202 @type parent: wx object 203 @keyword mol_name: The name of the molecule. 204 @type mol_name: str 205 @keyword mol_id: The molecule ID string. 206 @type mol_id: str 207 @keyword select: The selection state. 208 @type select: bool 209 """ 210 211 # Store the args. 212 self.parent = parent 213 self.mol_name = mol_name 214 self.mol_id = mol_id 215 self.select = select 216 217 # Create the header. 218 sizer = self.header_molecule() 219 220 # Add to the sizer. 221 box.Add(sizer, 0, wx.ALL|wx.EXPAND, border=self.border) 222 223 # A divider. 224 line = wx.StaticLine(self.parent, -1, (25, 50)) 225 box.Add(line, 0, wx.EXPAND|wx.ALL, border=self.border)
226 227
228 - def header_molecule(self):
229 """Create the header for the molecule container. 230 231 @return: The sizer containing the header. 232 @rtype: wx.Sizer instance 233 """ 234 235 # A sizer for the header. 236 sizer = wx.BoxSizer(wx.HORIZONTAL) 237 238 # A sizer for the text component of the header. 239 text_sizer = wx.BoxSizer(wx.VERTICAL) 240 241 # The title 242 title = self.create_title("Molecule container") 243 text_sizer.Add(title, 0, wx.LEFT, 0) 244 245 # Spacer. 246 text_sizer.AddSpacer(30) 247 248 # The info grid. 249 grid_sizer = wx.FlexGridSizer(2, 2, 5, 50) 250 grid_sizer.Add(self.create_head_text("Molecule:"), 0, wx.ADJUST_MINSIZE, 0) 251 grid_sizer.Add(self.create_head_text(self.mol_name), 0, wx.ADJUST_MINSIZE, 0) 252 grid_sizer.Add(self.create_head_text("Molecule ID string:"), 0, wx.ADJUST_MINSIZE, 0) 253 grid_sizer.Add(self.create_head_text("'%s'" % self.mol_id), 0, wx.ADJUST_MINSIZE, 0) 254 text_sizer.Add(grid_sizer, 0, wx.LEFT, 0) 255 256 # Add the text sizer to the main header sizer. 257 sizer.Add(text_sizer, 1, wx.ALL|wx.EXPAND, 0) 258 259 # Stretch spacer. 260 sizer.AddStretchSpacer() 261 262 # The graphic. 263 if self.select: 264 path = WIZARD_IMAGE_PATH + 'molecule.png' 265 else: 266 path = WIZARD_IMAGE_PATH + 'molecule_grey.png' 267 image = wx.StaticBitmap(self.parent, -1, bitmap_setup(path)) 268 sizer.Add(image, 0, wx.RIGHT, 0) 269 270 # Return the sizer. 271 return sizer
272 273 274
275 -class Residue(Container_base):
276 """The residue container.""" 277
278 - def __init__(self, box, parent, mol_name=None, res_num=None, res_name=None, res_id=None, select=True):
279 """Set up the residue container. 280 281 @param box: The box sizer element to pack the contents into. 282 @type box: wx object 283 @param parent: The parent GUI element. 284 @type parent: wx object 285 @keyword mol_name: The molecule name. 286 @type mol_name: str 287 @keyword res_num: The residue number. 288 @type res_num: str 289 @keyword res_name: The residue name. 290 @type res_name: str 291 @keyword res_id: The residue ID string. 292 @type res_id: str 293 @keyword select: The selection state. 294 @type select: bool 295 """ 296 297 # Store the args. 298 self.parent = parent 299 self.mol_name = mol_name 300 self.res_num = res_num 301 self.res_name = res_name 302 self.res_id = res_id 303 self.select = select 304 305 # Create the header. 306 sizer = self.header_residue() 307 308 # Add to the main sizer. 309 box.Add(sizer, 0, wx.ALL|wx.EXPAND, border=self.border) 310 311 # A divider. 312 line = wx.StaticLine(self.parent, -1, (25, 50)) 313 box.Add(line, 0, wx.EXPAND|wx.ALL, border=self.border)
314 315
316 - def header_residue(self):
317 """Create the header for the residue container. 318 319 @return: The sizer containing the header. 320 @rtype: wx.Sizer instance 321 """ 322 323 # A sizer for the header. 324 sizer = wx.BoxSizer(wx.HORIZONTAL) 325 326 # A sizer for the text component of the header. 327 text_sizer = wx.BoxSizer(wx.VERTICAL) 328 329 # The title 330 title = self.create_title("Residue container") 331 text_sizer.Add(title, 0, wx.LEFT, 0) 332 333 # Spacer. 334 text_sizer.AddSpacer(30) 335 336 # The info grid. 337 grid_sizer = wx.FlexGridSizer(4, 2, 5, 50) 338 grid_sizer.Add(self.create_head_text("Molecule:"), 0, wx.ADJUST_MINSIZE, 0) 339 grid_sizer.Add(self.create_head_text(self.mol_name), 0, wx.ADJUST_MINSIZE, 0) 340 grid_sizer.Add(self.create_head_text("Residue number:"), 0, wx.ADJUST_MINSIZE, 0) 341 grid_sizer.Add(self.create_head_text(self.res_num), 0, wx.ADJUST_MINSIZE, 0) 342 grid_sizer.Add(self.create_head_text("Residue name:"), 0, wx.ADJUST_MINSIZE, 0) 343 grid_sizer.Add(self.create_head_text(self.res_name), 0, wx.ADJUST_MINSIZE, 0) 344 grid_sizer.Add(self.create_head_text("Residue ID string:"), 0, wx.ADJUST_MINSIZE, 0) 345 grid_sizer.Add(self.create_head_text("'%s'" % self.res_id), 0, wx.ADJUST_MINSIZE, 0) 346 text_sizer.Add(grid_sizer, 0, wx.LEFT, 0) 347 348 # Add the text sizer to the main header sizer. 349 sizer.Add(text_sizer, 1, wx.ALL|wx.EXPAND, 0) 350 351 # Stretch spacer. 352 sizer.AddStretchSpacer() 353 354 # The graphic. 355 if self.select: 356 path = WIZARD_IMAGE_PATH + 'residue.png' 357 else: 358 path = WIZARD_IMAGE_PATH + 'residue_grey.png' 359 image = wx.StaticBitmap(self.parent, -1, bitmap_setup(path)) 360 sizer.Add(image, 0, wx.RIGHT, 0) 361 362 # Return the sizer. 363 return sizer
364 365 366
367 -class Spin(Container_base):
368 """The spin container.""" 369
370 - def __init__(self, box, parent, mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None, spin_id=None, select=True):
371 """Set up the spin container. 372 373 @param box: The box sizer element to pack the contents into. 374 @type box: wx object 375 @param parent: The parent GUI element. 376 @type parent: wx object 377 @keyword mol_name: The molecule name. 378 @type mol_name: str 379 @keyword res_num: The residue number. 380 @type res_num: str 381 @keyword res_name: The residue name. 382 @type res_name: str 383 @keyword spin_num: The spin number. 384 @type spin_num: str 385 @keyword spin_name: The spin name. 386 @type spin_name: str 387 @keyword spin_id: The spin ID string. 388 @type spin_id: str 389 @keyword select: The selection state. 390 @type select: bool 391 """ 392 393 # Store the args. 394 self.parent = parent 395 self.mol_name = mol_name 396 self.res_num = res_num 397 self.res_name = res_name 398 self.spin_num = spin_num 399 self.spin_name = spin_name 400 self.spin_id = spin_id 401 self.select = select 402 403 # Create the header. 404 sizer = self.header_spin() 405 406 # Add to the main sizer. 407 box.Add(sizer, 0, wx.ALL|wx.EXPAND, border=self.border) 408 409 # A divider. 410 line = wx.StaticLine(self.parent, -1, (25, 50)) 411 box.Add(line, 0, wx.EXPAND|wx.ALL, border=self.border) 412 413 # The spin container variables. 414 sizer2 = self.spin_vars() 415 box.Add(sizer2, 1, wx.ALL|wx.EXPAND, border=self.border)
416 417
418 - def header_spin(self):
419 """Create the header for the spin container. 420 421 @return: The sizer containing the header. 422 @rtype: wx.Sizer instance 423 """ 424 425 # A sizer for the header. 426 sizer = wx.BoxSizer(wx.HORIZONTAL) 427 428 # A sizer for the text component of the header. 429 text_sizer = wx.BoxSizer(wx.VERTICAL) 430 431 # The title 432 title = self.create_title("Spin container") 433 text_sizer.Add(title, 0, wx.LEFT, 0) 434 435 # Spacer. 436 text_sizer.AddSpacer(30) 437 438 # The info grid. 439 grid_sizer = wx.FlexGridSizer(6, 2, 5, 50) 440 grid_sizer.Add(self.create_head_text("Molecule:"), 0, wx.ADJUST_MINSIZE, 0) 441 grid_sizer.Add(self.create_head_text(self.mol_name), 0, wx.ADJUST_MINSIZE, 0) 442 grid_sizer.Add(self.create_head_text("Residue number:"), 0, wx.ADJUST_MINSIZE, 0) 443 grid_sizer.Add(self.create_head_text(self.res_num), 0, wx.ADJUST_MINSIZE, 0) 444 grid_sizer.Add(self.create_head_text("Residue name:"), 0, wx.ADJUST_MINSIZE, 0) 445 grid_sizer.Add(self.create_head_text(self.res_name), 0, wx.ADJUST_MINSIZE, 0) 446 grid_sizer.Add(self.create_head_text("Spin number:"), 0, wx.ADJUST_MINSIZE, 0) 447 grid_sizer.Add(self.create_head_text(self.spin_num), 0, wx.ADJUST_MINSIZE, 0) 448 grid_sizer.Add(self.create_head_text("Spin name:"), 0, wx.ADJUST_MINSIZE, 0) 449 grid_sizer.Add(self.create_head_text(self.spin_name), 0, wx.ADJUST_MINSIZE, 0) 450 grid_sizer.Add(self.create_head_text("Spin ID string:"), 0, wx.ADJUST_MINSIZE, 0) 451 grid_sizer.Add(self.create_head_text("'%s'" % self.spin_id), 0, wx.ADJUST_MINSIZE, 0) 452 text_sizer.Add(grid_sizer, 0, wx.LEFT, 0) 453 454 # Add the text sizer to the main header sizer. 455 sizer.Add(text_sizer, 1, wx.ALL|wx.EXPAND, 0) 456 457 # Stretch spacer. 458 sizer.AddStretchSpacer() 459 460 # The graphic. 461 if self.select: 462 path = WIZARD_IMAGE_PATH + 'spin.png' 463 else: 464 path = WIZARD_IMAGE_PATH + 'spin_grey.png' 465 image = wx.StaticBitmap(self.parent, -1, bitmap_setup(path)) 466 sizer.Add(image, 0, wx.RIGHT, 0) 467 468 # Return the sizer. 469 return sizer
470 471
472 - def spin_vars(self, blacklist=[]):
473 """Create the variable table for the spin container. 474 475 @keyword blacklist: A list of spin container objects to blacklist from the variable display table. 476 @type blacklist: list of str 477 @return: The sizer containing the table. 478 @rtype: wx.Sizer instance 479 """ 480 481 # A sizer for the table. 482 sizer = wx.BoxSizer(wx.VERTICAL) 483 484 # The title 485 title = self.create_subtitle("Spin container contents") 486 sizer.Add(title, 0, wx.LEFT, 0) 487 488 # Add a spacer. 489 sizer.AddSpacer(20) 490 491 # The table. 492 table = wx.ListCtrl(self.parent, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT) 493 494 # The headers. 495 table.InsertColumn(0, "Variable") 496 table.InsertColumn(1, "Value") 497 table.InsertColumn(2, "Type") 498 499 # The widths. 500 table.SetColumnWidth(0, 300) 501 table.SetColumnWidth(1, 200) 502 table.SetColumnWidth(2, 200) 503 504 # The spin container. 505 spin = return_spin(self.spin_id) 506 507 # Add some names to the blacklist. 508 blacklist += ['is_empty'] 509 510 # Loop over the contents of the spin container. 511 for name in dir(spin): 512 # Skip special objects. 513 if search('^_', name): 514 continue 515 516 # Blacklisted names. 517 if name in blacklist: 518 continue 519 520 # Get the object. 521 obj = getattr(spin, name) 522 523 # The type. 524 obj_type = str(type(obj)).split("'")[1] 525 526 # List types. 527 if obj_type in ['list', 'numpy.ndarray'] and len(obj) > 1: 528 # The first row. 529 table.Append((str_to_gui(name), str_to_gui("[%s," % obj[0]), str_to_gui(obj_type))) 530 531 # The rest of the rows. 532 for i in range(1, len(obj)-1): 533 table.Append((str_to_gui(''), str_to_gui(" %s," % obj[i]), str_to_gui(''))) 534 535 # The last row. 536 table.Append((str_to_gui(''), str_to_gui(" %s]" % obj[-1]), str_to_gui(''))) 537 538 # Dictionary types. 539 elif obj_type == 'dict': 540 # The keys. 541 keys = sorted(obj.keys()) 542 543 # Single entry (or None). 544 if len(keys) < 2: 545 table.Append((str_to_gui(name), str_to_gui(obj), str_to_gui(obj_type))) 546 continue 547 548 # The first row. 549 table.Append((str_to_gui(name), str_to_gui("{'%s': %s," % (keys[0], obj[keys[0]])), str_to_gui(obj_type))) 550 551 # The rest of the rows. 552 for i in range(1, len(keys)-1): 553 table.Append((str_to_gui(''), str_to_gui(" '%s': %s," % (keys[i], obj[keys[i]])), str_to_gui(''))) 554 555 # The last row. 556 table.Append((str_to_gui(''), str_to_gui(" '%s': %s}" % (keys[-1], obj[keys[-1]])), str_to_gui(''))) 557 558 # All other data types. 559 else: 560 table.Append((str_to_gui(name), str_to_gui(obj), str_to_gui(obj_type))) 561 562 # Add the table to the sizer. 563 sizer.Add(table, 1, wx.ALL|wx.EXPAND, 0) 564 565 # Return the sizer. 566 return sizer
567 568 569
570 -class Root(Container_base):
571 """The root container.""" 572
573 - def __init__(self, box, parent):
574 """Set up the root container. 575 576 @param box: The box sizer element to pack the contents into. 577 @type box: wx object 578 @param parent: The parent GUI element. 579 @type parent: wx object 580 """ 581 582 # Store the arg. 583 self.parent = parent 584 585 # A sizer for the header. 586 sizer = wx.BoxSizer(wx.VERTICAL) 587 588 # The title 589 title = self.create_title("The spin view window") 590 sizer.Add(title, 0, wx.LEFT, 0) 591 592 # Add to the sizer. 593 box.Add(sizer, 0, wx.ALL|wx.EXPAND, border=self.border)
594