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

Source Code for Module gui.analyses.auto_model_free

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2009 Michael Bieri                                            # 
   4  # Copyright (C) 2010-2011 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 for the automatic model-free protocol frame.""" 
  26   
  27  # Python module imports. 
  28  from os import sep 
  29  import sys 
  30  import wx 
  31  import wx.lib.buttons 
  32  import wx.lib.mixins.listctrl 
  33   
  34  # relax module imports. 
  35  from auto_analyses import dauvergne_protocol 
  36  from data import Relax_data_store; ds = Relax_data_store() 
  37  from doc_builder import LIST, PARAGRAPH, SECTION, SUBSECTION, TITLE 
  38  from generic_fns.pipes import has_pipe 
  39  from generic_fns.mol_res_spin import exists_mol_res_spin_data, spin_loop 
  40  from status import Status; status = Status() 
  41   
  42  # relax GUI module imports. 
  43  from gui.about import About_base 
  44  from gui.analyses.base import Base_analysis 
  45  from gui.analyses.elements import Spin_ctrl, Text_ctrl 
  46  from gui.analyses.execute import Execute 
  47  from gui.base_classes import Container 
  48  from gui.components.relax_data import Relax_data_list 
  49  from gui.filedialog import RelaxDirDialog 
  50  from gui.fonts import font 
  51  from gui.message import error_message, Question, Missing_data 
  52  from gui.misc import add_border, gui_to_int, gui_to_str, list_to_gui, protected_exec, str_to_gui 
  53  from gui import paths 
  54  from gui.user_functions.structure import Read_pdb_page, Vectors_page 
  55  from gui.user_functions import User_functions; user_functions = User_functions() 
  56  from gui.wizard import Wiz_window 
  57   
  58   
59 -class About_window(About_base):
60 """The model-free about window.""" 61 62 # The relax background colour. 63 colour1 = '#e5feff' 64 colour2 = '#88cbff' 65 66 # Dimensions. 67 dim_x = 800 68 dim_y = 800 69 max_y = 2500 70 71 # Spacer size (px). 72 border = 10 73 74 # Window style. 75 style = wx.DEFAULT_DIALOG_STYLE 76 77 # Destroy on clicking. 78 DESTROY_ON_CLICK = False 79
80 - def __init__(self, parent):
81 """Set up the user function class.""" 82 83 # Execute the base class method. 84 super(About_window, self).__init__(parent, id=-1, title="Automatic model-free analysis about window")
85 86
87 - def build_widget(self):
88 """Build the dialog using the dauvergne_protocol docstring.""" 89 90 # A global Y offset for packing the elements together (initialise to the border position). 91 self.offset(self.border) 92 93 # Loop over the lines. 94 for i in range(len(dauvergne_protocol.doc)): 95 # The level and text. 96 level, text = dauvergne_protocol.doc[i] 97 98 # The title. 99 if level == TITLE: 100 self.draw_title(text, point_size=18) 101 102 # The section. 103 elif level == SECTION: 104 self.draw_title(text, point_size=14) 105 106 # The section. 107 elif level == SUBSECTION: 108 self.draw_title(text, point_size=12) 109 110 # Paragraphs. 111 elif level == PARAGRAPH: 112 self.draw_wrapped_text(text) 113 114 # Lists. 115 elif level == LIST: 116 # Start of list. 117 if i and dauvergne_protocol.doc[i-1][0] != LIST: 118 self.offset(10) 119 120 # The text. 121 self.draw_wrapped_text(" - %s" % text) 122 123 # End of list. 124 if i < len(dauvergne_protocol.doc) and dauvergne_protocol.doc[i+1][0] == PARAGRAPH: 125 self.offset(10) 126 127 # Resize the window. 128 dim_x = self.dim_x 129 virt_y = self.offset() + self.border 130 self.SetSize((dim_x, self.dim_y)) 131 self.window.SetVirtualSize((dim_x, virt_y)) 132 self.window.EnableScrolling(x_scrolling=False, y_scrolling=True)
133 134 135
136 -class Auto_model_free(Base_analysis):
137 """The model-free auto-analysis GUI element.""" 138
139 - def __init__(self, parent, id=-1, pos=wx.Point(-1, -1), size=wx.Size(-1, -1), style=524288, name='scrolledpanel', gui=None, analysis_name=None, pipe_name=None, data_index=None):
140 """Build the automatic model-free protocol GUI element. 141 142 @param parent: The parent wx element. 143 @type parent: wx object 144 @keyword id: The unique ID number. 145 @type id: int 146 @keyword pos: The position. 147 @type pos: wx.Size object 148 @keyword size: The size. 149 @type size: wx.Size object 150 @keyword style: The style. 151 @type style: int 152 @keyword name: The name for the panel. 153 @type name: unicode 154 @keyword gui: The main GUI class. 155 @type gui: gui.relax_gui.Main instance 156 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook). 157 @type analysis_name: str 158 @keyword pipe_name: The name of the data pipe associated with this analysis. 159 @type pipe_name: str 160 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists). 161 @type data_index: None or int 162 """ 163 164 # Store the GUI main class. 165 self.gui = gui 166 167 # Init. 168 self.init_flag = True 169 170 # New data container. 171 if data_index == None: 172 # First create the data pipe if not already in existence. 173 if not has_pipe(pipe_name): 174 self.gui.interpreter.apply('pipe.create', pipe_name, 'mf') 175 176 # Generate a storage container in the relax data store, and alias it for easy access. 177 data_index = ds.relax_gui.analyses.add('model-free') 178 179 # Store the analysis and pipe names. 180 ds.relax_gui.analyses[data_index].analysis_name = analysis_name 181 ds.relax_gui.analyses[data_index].pipe_name = pipe_name 182 183 # Initialise the variables. 184 ds.relax_gui.analyses[data_index].grid_inc = None 185 ds.relax_gui.analyses[data_index].diff_tensor_grid_inc = {'sphere': 11, 'prolate': 11, 'oblate': 11, 'ellipsoid': 6} 186 ds.relax_gui.analyses[data_index].mc_sim_num = None 187 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir 188 ds.relax_gui.analyses[data_index].local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9'] 189 ds.relax_gui.analyses[data_index].mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9'] 190 ds.relax_gui.analyses[data_index].max_iter = 30 191 192 # Alias the data. 193 self.data = ds.relax_gui.analyses[data_index] 194 self.data_index = data_index 195 196 # Backward compatibility. 197 if not hasattr(self.data, 'local_tm_models'): 198 self.data.local_tm_models = ['tm0', 'tm1', 'tm2', 'tm3', 'tm4', 'tm5', 'tm6', 'tm7', 'tm8', 'tm9'] 199 if not hasattr(self.data, 'mf_models'): 200 self.data.mf_models = ['m0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'm9'] 201 202 # Initialise the mode selection window. 203 self.mode_win = Protocol_mode_sel_window() 204 205 # Register the method for updating the spin count for the completion of user functions. 206 self.observer_register() 207 208 # Execute the base class method to build the panel. 209 super(Auto_model_free, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
210 211
212 - def _about(self, event):
213 """The about window. 214 215 @param event: The wx event. 216 @type event: wx event 217 """ 218 219 # Initialise the dialog. 220 dialog = About_window(self) 221 222 # Show the dialog. 223 if status.show_gui: 224 dialog.Show()
225 226
227 - def activate(self):
228 """Activate or deactivate certain elements of the analysis in response to the execution lock.""" 229 230 # Flag for enabling or disabling the elements. 231 enable = False 232 if not status.exec_lock.locked(): 233 enable = True 234 235 # Activate or deactivate the elements. 236 wx.CallAfter(self.field_results_dir.Enable, enable) 237 wx.CallAfter(self.spin_systems.Enable, enable) 238 wx.CallAfter(self.relax_data.Enable, enable) 239 wx.CallAfter(self.button_csa.Enable, enable) 240 wx.CallAfter(self.button_r.Enable, enable) 241 wx.CallAfter(self.button_h_type.Enable, enable) 242 wx.CallAfter(self.button_x_type.Enable, enable) 243 wx.CallAfter(self.button_vectors.Enable, enable) 244 wx.CallAfter(self.local_tm_model_field.Enable, enable) 245 wx.CallAfter(self.mf_model_field.Enable, enable) 246 wx.CallAfter(self.grid_inc.Enable, enable) 247 wx.CallAfter(self.mc_sim_num.Enable, enable) 248 wx.CallAfter(self.max_iter.Enable, enable) 249 wx.CallAfter(self.mode.Enable, enable) 250 wx.CallAfter(self.button_exec_relax.Enable, enable)
251 252
253 - def add_values(self, box):
254 """Create and add the value.set buttons for the model-free analysis. 255 256 @param box: The box element to pack the GUI element into. 257 @type box: wx.BoxSizer instance 258 """ 259 260 # Sizer. 261 sizer = wx.BoxSizer(wx.HORIZONTAL) 262 263 # CSA button. 264 self.button_csa = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " CSA") 265 self.button_csa.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY)) 266 self.button_csa.SetFont(font.normal) 267 self.button_csa.SetSize((-1, 20)) 268 self.button_csa.SetToolTipString("Set the Chemical Shift Anisotropy (CSA) values via the value.set user function.") 269 self.gui.Bind(wx.EVT_BUTTON, self.value_set_csa, self.button_csa) 270 sizer.Add(self.button_csa, 1, wx.ALL|wx.EXPAND, 0) 271 272 # Bond length button. 273 self.button_r = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Bond length") 274 self.button_r.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY)) 275 self.button_r.SetFont(font.normal) 276 self.button_r.SetSize((-1, 20)) 277 self.button_r.SetToolTipString("Set the bond length (r) values via the value.set user function.") 278 self.gui.Bind(wx.EVT_BUTTON, self.value_set_r, self.button_r) 279 sizer.Add(self.button_r, 1, wx.ALL|wx.EXPAND, 0) 280 281 # Proton type button. 282 self.button_h_type = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " H type") 283 self.button_h_type.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY)) 284 self.button_h_type.SetFont(font.normal) 285 self.button_h_type.SetSize((-1, 20)) 286 self.button_h_type.SetToolTipString("Set the type of proton via the value.set user function.") 287 self.gui.Bind(wx.EVT_BUTTON, self.value_set_proton_type, self.button_h_type) 288 sizer.Add(self.button_h_type, 1, wx.ALL|wx.EXPAND, 0) 289 290 # Heteronucleus type button. 291 self.button_x_type = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " X type") 292 self.button_x_type.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.add, wx.BITMAP_TYPE_ANY)) 293 self.button_x_type.SetFont(font.normal) 294 self.button_x_type.SetSize((-1, 20)) 295 self.button_x_type.SetToolTipString("Set the type of heteronucleus via the value.set user function.") 296 self.gui.Bind(wx.EVT_BUTTON, self.value_set_heteronuc_type, self.button_x_type) 297 sizer.Add(self.button_x_type, 1, wx.ALL|wx.EXPAND, 0) 298 299 # Unit vectors button. 300 self.button_vectors = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Unit vectors") 301 self.button_vectors.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.structure, wx.BITMAP_TYPE_ANY)) 302 self.button_vectors.SetFont(font.normal) 303 self.button_vectors.SetSize((-1, 20)) 304 self.button_vectors.SetToolTipString("Load unit vectors from PDB files.") 305 self.gui.Bind(wx.EVT_BUTTON, self.load_unit_vectors, self.button_vectors) 306 sizer.Add(self.button_vectors, 1, wx.ALL|wx.EXPAND, 0) 307 308 # Add the element to the box. 309 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
310 311
312 - def assemble_data(self):
313 """Assemble the data required for the auto-analysis. 314 315 See the docstring for auto_analyses.dauvernge_protocol for details. All data is taken from the relax data store, so data upload from the GUI to there must have been previously performed. 316 317 @return: A container with all the data required for the auto-analysis. 318 @rtype: class instance, list of str 319 """ 320 321 # The data container. 322 data = Container() 323 missing = [] 324 325 # The pipe name. 326 data.pipe_name = self.data.pipe_name 327 328 # The model-free models (do not change these unless absolutely necessary). 329 data.local_tm_models = self.local_tm_model_field.GetValue() 330 data.mf_models = self.mf_model_field.GetValue() 331 332 # Automatic looping over all rounds until convergence (must be a boolean value of True or False). 333 data.conv_loop = True 334 335 # Increment size. 336 data.inc = gui_to_int(self.grid_inc.GetValue()) 337 if hasattr(self.data, 'diff_tensor_grid_inc'): 338 data.diff_tensor_grid_inc = self.data.diff_tensor_grid_inc 339 else: 340 data.diff_tensor_grid_inc = {'sphere': 11, 'prolate': 11, 'oblate': 11, 'ellipsoid': 6} 341 342 # The number of Monte Carlo simulations to be used for error analysis at the end of the analysis. 343 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 344 345 # Number of maximum iterations. 346 data.max_iter = self.data.max_iter 347 348 # Results directory. 349 data.save_dir = self.data.save_dir 350 351 # Check if sequence data is loaded 352 if not exists_mol_res_spin_data(): 353 missing.append("Sequence data") 354 355 # Relaxation data. 356 if not hasattr(cdp, 'ri_ids') or len(cdp.ri_ids) == 0: 357 missing.append("Relaxation data") 358 359 # Insufficient data. 360 if hasattr(cdp, 'ri_ids') and len(cdp.ri_ids) <= 3: 361 missing.append("Insufficient relaxation data, 4 or more data sets are essential for the execution of the dauvergne_protocol auto-analysis.") 362 363 # Get the mode. 364 mode = gui_to_str(self.mode.GetValue()) 365 366 # Solve for all global models. 367 if mode == 'Fully automated': 368 # The global model list. 369 data.global_models = ['local_tm', 'sphere', 'prolate', 'oblate', 'ellipsoid', 'final'] 370 371 # Any global model selected. 372 else: 373 data.global_models = [mode] 374 375 # Check for vectors. 376 vector_check = False 377 if 'prolate' in data.global_models or 'oblate' in data.global_models or 'ellipsoid' in data.global_models: 378 vector_check = True 379 380 # Spin vars. 381 for spin, spin_id in spin_loop(return_id=True): 382 # Skip deselected spins. 383 if not spin.select: 384 continue 385 386 # The message skeleton. 387 msg = "Spin '%s' - %s (try the %s user function)." % (spin_id, "%s", "%s") 388 389 # Test if the bond length has been set. 390 if not hasattr(spin, 'r') or spin.r == None: 391 missing.append(msg % ("bond length data", "value.set")) 392 393 # Test if the CSA value has been set. 394 if not hasattr(spin, 'csa') or spin.csa == None: 395 missing.append(msg % ("CSA data", "value.set")) 396 397 # Test if the heteronucleus type has been set. 398 if not hasattr(spin, 'heteronuc_type') or spin.heteronuc_type == None: 399 missing.append(msg % ("heteronucleus type data", "value.set")) 400 401 # Test if the proton type has been set. 402 if not hasattr(spin, 'proton_type') or spin.proton_type == None: 403 missing.append(msg % ("proton type data", "value.set")) 404 405 # Test if the unit vectors have been loaded. 406 if vector_check and (not hasattr(spin, 'xh_vect') or spin.xh_vect == None): 407 missing.append(msg % ("unit vectors", "structure.vectors")) 408 409 # Return the container and list of missing data. 410 return data, missing
411 412
413 - def build_left_box(self):
414 """Construct the left hand box to pack into the main model-free box. 415 416 @return: The left hand box element containing the bitmap and about button to pack into the main model-free box. 417 @rtype: wx.BoxSizer instance 418 """ 419 420 # Build the left hand box. 421 left_box = wx.BoxSizer(wx.VERTICAL) 422 423 # The images. 424 bitmaps = [paths.ANALYSIS_IMAGE_PATH+"model_free"+sep+"model_free_200x200.png", 425 paths.IMAGE_PATH+'modelfree.png'] 426 427 # Add the model-free bitmap picture. 428 for i in range(len(bitmaps)): 429 # The bitmap. 430 bitmap = wx.StaticBitmap(self, -1, wx.Bitmap(bitmaps[i], wx.BITMAP_TYPE_ANY)) 431 432 # Add it. 433 left_box.Add(bitmap, 0, wx.ALL, 0) 434 435 # A spacer. 436 left_box.AddStretchSpacer() 437 438 # A button sizer, with some initial spacing. 439 button_sizer = wx.BoxSizer(wx.HORIZONTAL) 440 441 # An about button. 442 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, "About") 443 button.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.about, wx.BITMAP_TYPE_ANY)) 444 button.SetFont(font.normal) 445 button.SetToolTipString("Information about this automatic analysis") 446 447 # Bind the click. 448 self.Bind(wx.EVT_BUTTON, self._about, button) 449 450 # A cursor for the button. 451 cursor = wx.StockCursor(wx.CURSOR_QUESTION_ARROW) 452 button.SetCursor(cursor) 453 454 # Pack the button. 455 button_sizer.Add(button, 0, 0, 0) 456 left_box.Add(button_sizer, 0, wx.ALL, 0) 457 458 # Return the packed box. 459 return left_box
460 461
462 - def build_right_box(self):
463 """Construct the right hand box to pack into the main model-free box. 464 465 @return: The right hand box element containing all model-free GUI elements (excluding the bitmap) to pack into the main model-free box. 466 @rtype: wx.BoxSizer instance 467 """ 468 469 # Use a vertical packing of elements. 470 box = wx.BoxSizer(wx.VERTICAL) 471 472 # Add the frame title. 473 self.add_title(box, "Setup for model-free analysis") 474 475 # Display the data pipe. 476 Text_ctrl(box, self, text="The data pipe:", default=self.data.pipe_name, tooltip="This is the data pipe associated with this analysis.", editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 477 478 # Add the results directory GUI element. 479 self.field_results_dir = Text_ctrl(box, self, text="Results directory", icon=paths.icon_16x16.open_folder, default=self.data.save_dir, fn=self.results_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 480 481 # Add the spin GUI element. 482 self.add_spin_systems(box, self) 483 484 # Add the relaxation data list GUI element, with spacing. 485 box.AddSpacer(10) 486 self.relax_data = Relax_data_list(gui=self.gui, parent=self, box=box, id=str(self.data_index)) 487 box.AddSpacer(10) 488 489 # Add the value.set buttons. 490 self.add_values(box) 491 box.AddSpacer(10) 492 493 # Add the local tau_m models GUI element, with spacing. 494 self.local_tm_model_field = Local_tm_list(self, box) 495 self.local_tm_model_field.set_value(self.data.local_tm_models) 496 497 # Add the model-free models GUI element, with spacing. 498 self.mf_model_field = Mf_list(self, box) 499 self.mf_model_field.set_value(self.data.mf_models) 500 501 # The optimisation settings. 502 self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=11, min=1, max=100, tooltip="This is the number of increments per dimension of the grid search performed prior to numerical optimisation.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 503 self.mc_sim_num = Spin_ctrl(box, self, text="Monte Carlo simulation number:", default=500, min=1, max=100000, tooltip="This is the number of Monte Carlo simulations performed for error propagation and analysis.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 504 505 # Add maximum iteration selector. 506 self.max_iter = Spin_ctrl(box, self, text="Maximum interations", default=self.data.max_iter, min=25, max=100, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 507 508 # The calculation mode. 509 self.mode = Text_ctrl(box, self, text="Protocol mode:", default='Fully automated', tooltip="Select if the dauvergne_protocol analysis will be fully automated or whether the individual global models will be optimised one by one.", icon=paths.icon_16x16.system_run, fn=self.mode_dialog, editable=False, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 510 511 # Stretchable spacing (with a minimal space). 512 box.AddSpacer(30) 513 box.AddStretchSpacer() 514 515 # Add the execution GUI element. 516 self.button_exec_relax = self.add_execute_relax(box, self.execute) 517 518 # Return the box. 519 return box
520 521
522 - def delete(self):
523 """Unregister the spin count from the user functions.""" 524 525 # Unregister the observer methods. 526 self.observer_register(remove=True) 527 528 # Clean up the relaxation data list object. 529 self.relax_data.delete()
530 531
532 - def execute(self, event):
533 """Set up, execute, and process the automatic model-free protocol. 534 535 @param event: The wx event. 536 @type event: wx event 537 """ 538 539 # Flush the GUI interpreter internal queue to make sure all user functions are complete. 540 self.gui.interpreter.flush() 541 542 # relax execution lock. 543 if status.exec_lock.locked(): 544 error_message("relax is currently executing.", "relax execution lock") 545 event.Skip() 546 return 547 548 # User warning to close windows. 549 self.gui.close_windows() 550 551 # Synchronise the frame data to the relax data store. 552 self.sync_ds(upload=True) 553 554 # Assemble all the data needed for the auto-analysis. 555 data, missing = self.assemble_data() 556 557 # Missing data. 558 if len(missing): 559 Missing_data(missing) 560 return 561 562 # Display the relax controller, and go to the end of the log window. 563 self.gui.show_controller(None) 564 self.gui.controller.log_panel.on_goto_end(None) 565 566 # Start the thread. 567 self.thread = Execute_mf(self.gui, data, self.data_index) 568 self.thread.start() 569 570 # Terminate the event. 571 event.Skip()
572 573
574 - def load_unit_vectors(self, event):
575 """Create the wizard for structure.read_pdb and structure.vectors. 576 577 @param event: The wx event. 578 @type event: wx event 579 """ 580 581 # Change the cursor to busy. 582 wx.BeginBusyCursor() 583 584 # Create the wizard. 585 self.vect_wizard = Wiz_window(parent=self.gui, size_x=800, size_y=600, title="Load unit vectors from file") 586 587 # Create the PDB reading page. 588 page = Read_pdb_page(self.vect_wizard) 589 self.vect_wizard.add_page(page, skip_button=True) 590 591 # Create the vector loading page. 592 page = Vectors_page(self.vect_wizard) 593 self.vect_wizard.add_page(page) 594 595 # Reset the cursor. 596 if wx.IsBusy(): 597 wx.EndBusyCursor() 598 599 # Execute the wizard. 600 self.vect_wizard.run()
601 602
603 - def mode_dialog(self, event):
604 """The calculation mode selection. 605 606 @param event: The wx event. 607 @type event: wx event 608 """ 609 610 # Show the model selector window. 611 if status.show_gui: 612 self.mode_win.ShowModal() 613 614 # Set the model. 615 self.mode.SetValue(str_to_gui(self.mode_win.select))
616 617
618 - def observer_register(self, remove=False):
619 """Register and unregister methods with the observer objects. 620 621 @keyword remove: If set to True, then the methods will be unregistered. 622 @type remove: False 623 """ 624 625 # Register. 626 if not remove: 627 status.observers.gui_uf.register(self.data.pipe_name, self.update_spin_count) 628 status.observers.exec_lock.register(self.data.pipe_name, self.activate) 629 630 # Unregister. 631 else: 632 # The model-free methods. 633 status.observers.gui_uf.unregister(self.data.pipe_name) 634 status.observers.exec_lock.unregister(self.data.pipe_name) 635 636 # The embedded objects methods. 637 self.relax_data.observer_register(remove=True)
638 639
640 - def results_directory(self, event):
641 """The results directory selection. 642 643 @param event: The wx event. 644 @type event: wx event 645 """ 646 647 # The dialog. 648 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue()) 649 650 # Show the dialog and catch if no file has been selected. 651 if status.show_gui and dialog.ShowModal() != wx.ID_OK: 652 # Don't do anything. 653 return 654 655 # The path (don't do anything if not set). 656 path = gui_to_str(dialog.get_path()) 657 if not path: 658 return 659 660 # Store the path. 661 self.data.save_dir = path 662 663 # Place the path in the text box. 664 self.field_results_dir.SetValue(str_to_gui(path))
665 666
667 - def sync_ds(self, upload=False):
668 """Synchronise the analysis frame and the relax data store, both ways. 669 670 This method allows the frame information to be uploaded into the relax data store, or for the information in the relax data store to be downloaded by the frame. 671 672 @keyword upload: A flag which if True will cause the frame to send data to the relax data store. If False, data will be downloaded from the relax data store to update the frame. 673 @type upload: bool 674 """ 675 676 # The local tau_m models to use. 677 if upload: 678 self.data.local_tm_models = self.local_tm_model_field.GetValue() 679 else: 680 self.local_tm_model_field.set_value(self.data.local_tm_models) 681 682 # The model-free models to use. 683 if upload: 684 self.data.mf_models = self.mf_model_field.GetValue() 685 else: 686 self.mf_model_field.set_value(self.data.mf_models) 687 688 # The grid incs. 689 if upload: 690 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue()) 691 elif hasattr(self.data, 'grid_inc'): 692 self.grid_inc.SetValue(int(self.data.grid_inc)) 693 694 # The MC sim number. 695 if upload: 696 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 697 elif hasattr(self.data, 'mc_sim_num'): 698 self.mc_sim_num.SetValue(int(self.data.mc_sim_num)) 699 700 # The results directory. 701 if upload: 702 self.data.save_dir = str(self.field_results_dir.GetValue()) 703 else: 704 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir)) 705 706 # Maximum iterations. 707 if upload: 708 self.data.max_iter = gui_to_int(self.max_iter.GetValue()) 709 else: 710 self.max_iter.SetValue(int(self.data.max_iter))
711 712
713 - def value_set_csa(self, event):
714 """Set the CSA via the value.set uf. 715 716 @param event: The wx event. 717 @type event: wx event 718 """ 719 720 # Call the user function. 721 user_functions.value.set(param='csa')
722 723
724 - def value_set_heteronuc_type(self, event):
725 """Set the type of heteronucleus via the value.set uf. 726 727 @param event: The wx event. 728 @type event: wx event 729 """ 730 731 # Call the user function. 732 user_functions.value.set(param='heteronuc_type')
733 734
735 - def value_set_proton_type(self, event):
736 """Set the type of proton via the value.set uf. 737 738 @param event: The wx event. 739 @type event: wx event 740 """ 741 742 # Call the user function. 743 user_functions.value.set(param='proton_type')
744 745
746 - def value_set_r(self, event):
747 """Set the bond length via the value.set uf. 748 749 @param event: The wx event. 750 @type event: wx event 751 """ 752 753 # Call the user function. 754 user_functions.value.set(param='r')
755 756 757
758 -class Execute_mf(Execute):
759 """The model-free analysis execution object.""" 760
761 - def run_analysis(self):
762 """Execute the calculation.""" 763 764 # Start the protocol. 765 dauvergne_protocol.dAuvergne_protocol(pipe_name=self.data.pipe_name, results_dir=self.data.save_dir, diff_model=self.data.global_models, mf_models=self.data.mf_models, local_tm_models=self.data.local_tm_models, grid_inc=self.data.inc, diff_tensor_grid_inc=self.data.diff_tensor_grid_inc, mc_sim_num=self.data.mc_sim_num, max_iter=self.data.max_iter, conv_loop=self.data.conv_loop)
766 767 768
769 -class Local_tm_list:
770 """The model-free model list GUI element.""" 771 772 # Some class variables. 773 desc = u'Local \u03C4m models:' 774 models = [ 775 "tm0", 776 "tm1", 777 "tm2", 778 "tm3", 779 "tm4", 780 "tm5", 781 "tm6", 782 "tm7", 783 "tm8", 784 "tm9" 785 ] 786 params = [ 787 "{local_tm}", 788 "{local_tm, S2}", 789 "{local_tm, S2, te}", 790 "{local_tm, S2, Rex}", 791 "{local_tm, S2, te, Rex}", 792 "{local_tm, S2, S2f, ts}", 793 "{local_tm, S2, tf, S2f, ts}", 794 "{local_tm, S2, S2f, ts, Rex}", 795 "{local_tm, S2, tf, S2f, ts, Rex}", 796 "{local_tm, Rex}" 797 ] 798
799 - def __init__(self, parent, box):
800 """Build the combo box list widget for a list of list selections. 801 802 @param parent: The parent GUI element. 803 @type parent: wx object instance 804 @param box: The sizer to put the combo box widget into. 805 @type box: wx.Sizer instance 806 """ 807 808 # Store some args. 809 self.parent = parent 810 811 # Initialise all models as being selected. 812 self.select = [] 813 for i in range(len(self.models)): 814 self.select.append(True) 815 816 # Initialise the model selection window. 817 self.model_win = Model_sel_window(self.models, self.params) 818 819 # Horizontal packing for this element. 820 sizer = wx.BoxSizer(wx.HORIZONTAL) 821 822 # Add a label. 823 label = self.parent.add_static_text(sizer, self.parent, text=self.desc, width=self.parent.width_text) 824 825 # Spacer. 826 sizer.AddSpacer((self.parent.spacer_horizontal, -1)) 827 828 # The text input field. 829 self.field = self.parent.add_text_control(sizer, self.parent, text=list_to_gui(self.GetValue()), editable=False) 830 831 # Spacer. 832 sizer.AddSpacer((self.parent.spacer_horizontal, -1)) 833 834 # Add the button. 835 self.button = self.parent.add_button_open(sizer, self.parent, icon=paths.icon_16x16.flag_blue, text="Modify", fn=self.modify, width=self.parent.width_button, height=label.GetSize()[1]+8) 836 837 # Add the contents to the main box. 838 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
839 840
841 - def Enable(self, enable=True):
842 """Enable or disable the element. 843 844 @keyword enable: The flag specifying if the element should be enabled or disabled. 845 @type enable: bool 846 """ 847 848 # Call the control and button's method. 849 self.field.Enable(enable) 850 self.button.Enable(enable)
851 852
853 - def GetValue(self):
854 """Return the list of model-free models. 855 856 @return: The list of model-free models. 857 @rtype: list of str 858 """ 859 860 # Initialise. 861 model_list = [] 862 863 # Add the models if they are selected. 864 for i in range(len(self.models)): 865 if self.select[i]: 866 model_list.append(self.models[i]) 867 868 # Return the list. 869 return model_list
870 871
872 - def set_value(self, value):
873 """Store the list of model-free models. 874 875 @param value: The list of model-free models. 876 @type value: list of str 877 """ 878 879 # First set all models as being deselected. 880 for i in range(len(self.models)): 881 self.select[i] = False 882 883 # Select all models in the list. 884 for model in value: 885 # The model index. 886 index = self.models.index(model) 887 888 # Set the selected flag. 889 self.select[index] = True 890 891 # Update the button. 892 self.update_button() 893 894 # Update the GUI element. 895 self.field.SetValue(list_to_gui(self.GetValue()))
896 897
898 - def modify(self, event):
899 """Modify the model-free model selection. 900 901 @param event: The wx event. 902 @type event: wx event 903 """ 904 905 # First state that this should not be done. 906 msg = "The model-free models used in dauvergne_protocol auto-analysis should almost never be changed! The consequences will be unpredictable. Please proceed only if you are sure of what you are doing. Would you like to modify the model-free model list?" 907 if status.show_gui and not Question(msg, title="Warning - do not change!", size=(420, 210), default=False).ShowModal() == wx.ID_YES: 908 return 909 910 # Set the model selector window selections. 911 self.model_win.set_selection(self.select) 912 913 # Show the model selector window. 914 if status.show_gui: 915 self.model_win.ShowModal() 916 self.model_win.Close() 917 918 # Set the values. 919 self.select = self.model_win.get_selection() 920 921 # Update the button. 922 self.update_button() 923 924 # Update the GUI element. 925 self.field.SetValue(list_to_gui(self.GetValue()))
926 927
928 - def update_button(self):
929 """Update the button bitmap as needed.""" 930 931 # Change the flag to red to indicate to the user that changing the models is a bad thing! 932 if False in self.select: 933 self.button.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.flag_red, wx.BITMAP_TYPE_ANY)) 934 935 # Otherwise set it to blue (in case all models are selected again). 936 else: 937 self.button.SetBitmapLabel(wx.Bitmap(paths.icon_16x16.flag_blue, wx.BITMAP_TYPE_ANY))
938 939 940
941 -class Mf_list(Local_tm_list):
942 """The model-free model list GUI element.""" 943 944 # Some class variables. 945 desc = "Model-free models:" 946 models = [ 947 "m0", 948 "m1", 949 "m2", 950 "m3", 951 "m4", 952 "m5", 953 "m6", 954 "m7", 955 "m8", 956 "m9" 957 ] 958 params = [ 959 "{}", 960 "{S2}", 961 "{S2, te}", 962 "{S2, Rex}", 963 "{S2, te, Rex}", 964 "{S2, S2f, ts}", 965 "{S2, tf, S2f, ts}", 966 "{S2, S2f, ts, Rex}", 967 "{S2, tf, S2f, ts, Rex}", 968 "{Rex}" 969 ]
970 971 972
973 -class Model_sel_window(wx.Dialog):
974 """The model-free model selector window object.""" 975
976 - def __init__(self, models, params):
977 """Set up the model-free model selector window. 978 979 @param models: The list of model-free models. 980 @type models: list of str 981 @param params: The list of parameters corresponding to the models. 982 @type params: list of str 983 """ 984 985 # Set up the dialog. 986 wx.Dialog.__init__(self, None, id=-1, title="Model-free model selector") 987 988 # Initialise some values 989 size_x = 500 990 size_y = 300 991 border = 10 992 width = size_x - 2*border 993 994 # Set the frame properties. 995 self.SetSize((size_x, size_y)) 996 self.Centre() 997 self.SetFont(font.normal) 998 999 # The main box sizer. 1000 main_sizer = wx.BoxSizer(wx.VERTICAL) 1001 1002 # Pack the sizer into the frame. 1003 self.SetSizer(main_sizer) 1004 1005 # Build the central sizer, with borders. 1006 sizer = add_border(main_sizer, border=border, packing=wx.VERTICAL) 1007 1008 # Add a list control. 1009 self.model_list = ModelSelListCtrl(self) 1010 1011 # The headers. 1012 self.model_list.InsertColumn(0, "Model-free model") 1013 self.model_list.InsertColumn(1, "Parameters") 1014 1015 # The widths. 1016 self.model_list.SetColumnWidth(0, int(0.4*width)) 1017 self.model_list.SetColumnWidth(1, int(0.5*width)) 1018 1019 # Add the models and parameters. 1020 for i in range(len(models)): 1021 # Set the text. 1022 self.model_list.Append((str_to_gui(models[i]), str_to_gui(params[i]))) 1023 1024 # Set all selections to True. 1025 self.model_list.CheckItem(i) 1026 1027 # Add the table to the sizer. 1028 sizer.Add(self.model_list, 1, wx.ALL|wx.EXPAND, 0)
1029 1030
1031 - def get_selection(self):
1032 """Return the selection as a list of booleans. 1033 1034 @return: The list of models selected. 1035 @rtype: list of bool 1036 """ 1037 1038 # Init. 1039 select = [] 1040 1041 # Loop over the entries. 1042 for i in range(self.model_list.GetItemCount()): 1043 select.append(self.model_list.IsChecked(i)) 1044 1045 # Return the list. 1046 return select
1047 1048
1049 - def set_selection(self, select):
1050 """Set the selection. 1051 1052 @param select: The list of selections. 1053 @type select: list of bool 1054 """ 1055 1056 # Loop over the entries. 1057 for i in range(self.model_list.GetItemCount()): 1058 self.model_list.CheckItem(i, check=select[i])
1059 1060 1061
1062 -class ModelSelListCtrl(wx.ListCtrl, wx.lib.mixins.listctrl.CheckListCtrlMixin):
1063 """A special list control with checkboxes.""" 1064
1065 - def __init__(self, parent):
1066 """Initialise the control. 1067 1068 @param parent: The parent window. 1069 @type parent: wx.Frame instance 1070 """ 1071 1072 # Execute the list control __init__() method. 1073 wx.ListCtrl.__init__(self, parent, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT) 1074 1075 # Execute the CheckListCtrlMixin __init__() method. 1076 wx.lib.mixins.listctrl.CheckListCtrlMixin.__init__(self)
1077 1078 1079
1080 -class Protocol_mode_sel_window(wx.Dialog):
1081 """The protocol mode selector window object.""" 1082
1083 - def __init__(self):
1084 """Set up the window.""" 1085 1086 # Set up the dialog. 1087 wx.Dialog.__init__(self, None, id=-1, title="Protocol mode selection") 1088 1089 # Initialise some values 1090 size_x = 600 1091 size_y = 600 1092 border = 10 1093 self.select = 'Fully automated' 1094 1095 # Set the frame properties. 1096 self.SetSize((size_x, size_y)) 1097 self.Centre() 1098 self.SetFont(font.normal) 1099 1100 # The main box sizer. 1101 main_sizer = wx.BoxSizer(wx.VERTICAL) 1102 1103 # Pack the sizer into the frame. 1104 self.SetSizer(main_sizer) 1105 1106 # Build the central sizer, with borders. 1107 sizer = add_border(main_sizer, border=border, packing=wx.HORIZONTAL) 1108 1109 # Build the automatic part. 1110 self.build_auto(sizer) 1111 1112 # Line separator. 1113 sizer.Add(wx.StaticLine(self, -1, style=wx.LI_VERTICAL), 0, wx.EXPAND|wx.ALL, border) 1114 1115 # Build the manual part. 1116 self.build_manual(sizer)
1117 1118
1119 - def build_auto(self, sizer):
1120 """Build the fully automated part of the window. 1121 1122 @param sizer: The sizer to pack the elements into. 1123 @type sizer: wx.BoxSizer instance 1124 """ 1125 1126 # Create a vertical sizer for the elements. 1127 sub_sizer = wx.BoxSizer(wx.VERTICAL) 1128 1129 # The title. 1130 title = wx.StaticText(self, -1, "Fully automated") 1131 title.SetFont(font.subtitle) 1132 sub_sizer.Add(title, 0, wx.ALIGN_CENTRE_HORIZONTAL, 0) 1133 1134 # Spacing. 1135 sub_sizer.AddStretchSpacer() 1136 1137 # The button. 1138 button = wx.BitmapButton(self, -1, wx.Bitmap(paths.icon_48x48.go_bottom, wx.BITMAP_TYPE_ANY)) 1139 button.SetMinSize((80, 80)) 1140 button.SetToolTipString("Perform a fully automated analysis, looping over global models I to V and terminating with the final run. Please click on the 'About' button for more information.") 1141 sub_sizer.Add(button, 3, wx.EXPAND, 0) 1142 self.Bind(wx.EVT_BUTTON, self.select_full_analysis, button) 1143 1144 # Spacing. 1145 sub_sizer.AddStretchSpacer() 1146 1147 # Add the sub-sizer. 1148 sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0)
1149 1150
1151 - def build_manual(self, sizer):
1152 """Build the manual part of the window. 1153 1154 @param sizer: The sizer to pack the elements into. 1155 @type sizer: wx.BoxSizer instance 1156 """ 1157 1158 # Create a vertical sizer for the elements. 1159 sub_sizer = wx.BoxSizer(wx.VERTICAL) 1160 1161 # The title. 1162 title = wx.StaticText(self, -1, "Manual modes") 1163 title.SetFont(font.subtitle) 1164 sub_sizer.Add(title, 0, wx.ALIGN_CENTRE_HORIZONTAL, 0) 1165 1166 # Spacing. 1167 sub_sizer.AddSpacer(10) 1168 1169 # The local_tm button. 1170 button = wx.Button(self, -1, u"Local \u03C4m") 1171 button.SetToolTipString("Optimise global model I, the local tm models. Please click on the 'About' button for more information.") 1172 button.SetFont(font.normal) 1173 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1174 self.Bind(wx.EVT_BUTTON, self.select_local_tm, button) 1175 1176 # The sphere button. 1177 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Sphere")) 1178 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'sphere.png', wx.BITMAP_TYPE_ANY)) 1179 button.SetFont(font.normal) 1180 button.SetToolTipString("Optimise global model II, the spherical diffusion model. Please click on the 'About' button for more information.") 1181 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1182 self.Bind(wx.EVT_BUTTON, self.select_sphere, button) 1183 1184 # The prolate spheroid button. 1185 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Prolate spheroid")) 1186 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'prolate.png', wx.BITMAP_TYPE_ANY)) 1187 button.SetFont(font.normal) 1188 button.SetToolTipString("Optimise global model III, the prolate spheroid diffusion model. Please click on the 'About' button for more information.") 1189 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1190 self.Bind(wx.EVT_BUTTON, self.select_prolate, button) 1191 1192 # The oblate spheroid button. 1193 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Oblate spheroid")) 1194 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'oblate.png', wx.BITMAP_TYPE_ANY)) 1195 button.SetFont(font.normal) 1196 button.SetToolTipString("Optimise global model IV, the oblate spheroid diffusion model. Please click on the 'About' button for more information.") 1197 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1198 self.Bind(wx.EVT_BUTTON, self.select_oblate, button) 1199 1200 # The ellipsoid button. 1201 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, str_to_gui(" Ellipsoid")) 1202 button.SetBitmapLabel(wx.Bitmap(paths.IMAGE_PATH+'ellipsoid.png', wx.BITMAP_TYPE_ANY)) 1203 button.SetFont(font.normal) 1204 button.SetToolTipString("Optimise global model V, the ellipsoid diffusion model. Please click on the 'About' button for more information.") 1205 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1206 self.Bind(wx.EVT_BUTTON, self.select_ellipsoid, button) 1207 1208 # The final button. 1209 button = wx.Button(self, -1, str_to_gui("Final")) 1210 button.SetToolTipString("The final run of the protocol. Please click on the 'About' button for more information.") 1211 button.SetFont(font.normal) 1212 sub_sizer.Add(button, 1, wx.EXPAND, 0) 1213 self.Bind(wx.EVT_BUTTON, self.select_final, button) 1214 1215 # Add the sub-sizer. 1216 sizer.Add(sub_sizer, 1, wx.ALL|wx.EXPAND, 0)
1217 1218
1219 - def select_ellipsoid(self, event):
1220 """The ellipsoid global model has been selected. 1221 1222 @param event: The wx event. 1223 @type event: wx event 1224 """ 1225 1226 # Set the value. 1227 self.select = 'ellipsoid' 1228 1229 # Close the dialog. 1230 self.Close()
1231 1232
1233 - def select_final(self, event):
1234 """The final stage of the protocol has been selected. 1235 1236 @param event: The wx event. 1237 @type event: wx event 1238 """ 1239 1240 # Set the value. 1241 self.select = 'final' 1242 1243 # Close the dialog. 1244 self.Close()
1245 1246
1247 - def select_full_analysis(self, event):
1248 """The full analysis has been selected. 1249 1250 @param event: The wx event. 1251 @type event: wx event 1252 """ 1253 1254 # Set the value. 1255 self.select = 'Fully automated' 1256 1257 # Close the dialog. 1258 self.Close()
1259 1260
1261 - def select_local_tm(self, event):
1262 """The local_tm global model has been selected. 1263 1264 @param event: The wx event. 1265 @type event: wx event 1266 """ 1267 1268 # Set the value. 1269 self.select = 'local_tm' 1270 1271 # Close the dialog. 1272 self.Close()
1273 1274
1275 - def select_prolate(self, event):
1276 """The prolate global model has been selected. 1277 1278 @param event: The wx event. 1279 @type event: wx event 1280 """ 1281 1282 # Set the value. 1283 self.select = 'prolate' 1284 1285 # Close the dialog. 1286 self.Close()
1287 1288
1289 - def select_oblate(self, event):
1290 """The oblate global model has been selected. 1291 1292 @param event: The wx event. 1293 @type event: wx event 1294 """ 1295 1296 # Set the value. 1297 self.select = 'oblate' 1298 1299 # Close the dialog. 1300 self.Close()
1301 1302
1303 - def select_sphere(self, event):
1304 """The sphere global model has been selected. 1305 1306 @param event: The wx event. 1307 @type event: wx event 1308 """ 1309 1310 # Set the value. 1311 self.select = 'sphere' 1312 1313 # Close the dialog. 1314 self.Close()
1315