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

Source Code for Module gui.analyses.auto_relax_disp

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 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  """Module for the automatic relaxation dispersion analysis.""" 
 24   
 25  # Python module imports. 
 26  import wx 
 27   
 28  # relax module imports. 
 29  from auto_analyses.relax_disp import Relax_disp 
 30  from data_store import Relax_data_store; ds = Relax_data_store() 
 31  from graphics import ANALYSIS_IMAGE_PATH, fetch_icon 
 32  from gui.analyses.base import Base_analysis 
 33  from gui.analyses.elements.bool_element import Boolean_ctrl 
 34  from gui.analyses.elements.float_element import Float_ctrl 
 35  from gui.analyses.elements.spin_element import Spin_ctrl 
 36  from gui.analyses.elements.text_element import Text_ctrl 
 37  from gui.analyses.elements.model_list import Model_list 
 38  from gui.analyses.execute import Execute 
 39  from gui.base_classes import Container 
 40  from gui.components.spectrum import Spectra_list 
 41  from gui.filedialog import RelaxDirDialog 
 42  from gui.fonts import font 
 43  from gui.message import error_message, Missing_data 
 44  from gui.string_conv import float_to_gui, gui_to_bool, gui_to_float, gui_to_int, gui_to_str, str_to_gui 
 45  from gui.uf_objects import Uf_storage; uf_store = Uf_storage() 
 46  from gui.wizards.peak_intensity import Peak_intensity_wizard 
 47  from lib.text.gui import dw, dw_AB, dw_BC, dwH, dwH_AB, dwH_BC, i0, kex, kAB, kBC, kAC, padw2, phi_ex, phi_exB, phi_exC, r1, r1rho, r1rho_prime, r2, r2a, r2b, r2eff 
 48  from pipe_control.mol_res_spin import exists_mol_res_spin_data, spin_loop 
 49  from pipe_control.pipes import has_bundle, has_pipe 
 50  from specific_analyses.relax_disp.disp_data import has_cpmg_exp_type, has_r1rho_exp_type 
 51  from specific_analyses.relax_disp.variables import MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_CPMG, MODEL_LIST_R1RHO, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_MMQ_CR72, MODEL_MP05, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_MMQ_2SITE, MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_2SITE, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR, MODEL_R2EFF, MODEL_TAP03, MODEL_TP02, MODEL_TSMFK01 
 52  from status import Status; status = Status() 
 53   
 54   
55 -class Auto_relax_disp(Base_analysis):
56 """The relaxation dispersion auto-analysis GUI element.""" 57 58 # Hardcoded variables. 59 analysis_type = None 60 bitmap = ANALYSIS_IMAGE_PATH+"relax_disp_200x200.png" 61 label = 'Relax-disp' 62
63 - 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, pipe_bundle=None, uf_exec=[], data_index=None):
64 """Build the automatic R1 and R2 analysis GUI frame elements. 65 66 @param parent: The parent wx element. 67 @type parent: wx object 68 @keyword id: The unique ID number. 69 @type id: int 70 @keyword pos: The position. 71 @type pos: wx.Size object 72 @keyword size: The size. 73 @type size: wx.Size object 74 @keyword style: The style. 75 @type style: int 76 @keyword name: The name for the panel. 77 @type name: unicode 78 @keyword gui: The main GUI class. 79 @type gui: gui.relax_gui.Main instance 80 @keyword analysis_name: The name of the analysis (the name in the tab part of the notebook). 81 @type analysis_name: str 82 @keyword pipe_name: The name of the data pipe associated with this analysis. 83 @type pipe_name: str 84 @keyword pipe_bundle: The name of the data pipe bundle associated with this analysis. 85 @type pipe_bundle: str 86 @keyword uf_exec: The list of user function on_execute methods returned from the new analysis wizard. 87 @type uf_exec: list of methods 88 @keyword data_index: The index of the analysis in the relax data store (set to None if no data currently exists). 89 @type data_index: None or int 90 """ 91 92 # Store the GUI main class. 93 self.gui = gui 94 95 # Init. 96 self.init_flag = True 97 98 # New data container. 99 if data_index == None: 100 # First create the data pipe if not already in existence. 101 if not has_pipe(pipe_name): 102 self.gui.interpreter.apply('pipe.create', pipe_name=pipe_name, pipe_type='relax_disp', bundle=pipe_bundle) 103 104 # Create the data pipe bundle if needed. 105 if not has_bundle(pipe_bundle): 106 self.gui.interpreter.apply('pipe.bundle', bundle=pipe_bundle, pipe=pipe_name) 107 108 # Generate a storage container in the relax data store, and alias it for easy access. 109 data_index = ds.relax_gui.analyses.add(self.label) 110 111 # Store the analysis and pipe names. 112 ds.relax_gui.analyses[data_index].analysis_name = analysis_name 113 ds.relax_gui.analyses[data_index].pipe_name = pipe_name 114 ds.relax_gui.analyses[data_index].pipe_bundle = pipe_bundle 115 116 # Initialise the variables. 117 ds.relax_gui.analyses[data_index].numeric_only = False 118 ds.relax_gui.analyses[data_index].grid_inc = None 119 ds.relax_gui.analyses[data_index].mc_sim_num = None 120 ds.relax_gui.analyses[data_index].pre_run_dir = None 121 ds.relax_gui.analyses[data_index].mc_sim_all_models = False 122 ds.relax_gui.analyses[data_index].insignificance = 1.0 123 ds.relax_gui.analyses[data_index].save_dir = self.gui.launch_dir 124 125 # Set the default dispersion models based on the experiment type. 126 ds.relax_gui.analyses[data_index].disp_models = [ 127 MODEL_R2EFF, 128 MODEL_NOREX, 129 MODEL_CR72, 130 MODEL_NS_CPMG_2SITE_EXPANDED, 131 MODEL_MP05, 132 MODEL_NS_R1RHO_2SITE 133 ] 134 135 # Error checking. 136 if ds.relax_gui.analyses[data_index].pipe_bundle == None: 137 raise RelaxError("The pipe bundle must be supplied.") 138 139 # Alias the data. 140 self.data = ds.relax_gui.analyses[data_index] 141 self.data_index = data_index 142 143 # Register the method for updating the spin count for the completion of user functions. 144 self.observer_register() 145 146 # Execute the base class method to build the panel. 147 super(Auto_relax_disp, self).__init__(parent, id=id, pos=pos, size=size, style=style, name=name) 148 149 # Optimisation variables for speeding up the test suite. 150 self.opt_func_tol = 1e-25 151 self.opt_max_iterations = int(1e7) 152 153 # Update the isotope and cluster information. 154 self.update_clusters()
155 156
157 - def activate(self):
158 """Activate or deactivate certain elements of the analysis in response to the execution lock.""" 159 160 # Flag for enabling or disabling the elements. 161 enable = False 162 if not status.exec_lock.locked(): 163 enable = True 164 165 # Activate or deactivate the elements. 166 wx.CallAfter(self.field_results_dir.Enable, enable) 167 wx.CallAfter(self.field_pre_run_dir.Enable, enable) 168 wx.CallAfter(self.spin_systems.Enable, enable) 169 wx.CallAfter(self.field_cluster.Enable, enable) 170 wx.CallAfter(self.button_isotope.Enable, enable) 171 wx.CallAfter(self.button_r1.Enable, enable) 172 wx.CallAfter(self.button_chemical_shift.Enable, enable) 173 wx.CallAfter(self.button_interatom_define.Enable, enable) 174 wx.CallAfter(self.peak_intensity.Enable, enable) 175 wx.CallAfter(self.model_field.Enable, enable) 176 wx.CallAfter(self.button_exec_relax.Enable, enable)
177 178
179 - def add_buttons(self, box):
180 """Add all of the buttons. 181 182 @param box: The box element to pack the GUI element into. 183 @type box: wx.BoxSizer instance 184 """ 185 186 # Sizer. 187 sizer = wx.BoxSizer(wx.HORIZONTAL) 188 189 # Isotope type button. 190 self.button_isotope = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Spin isotope") 191 self.button_isotope.SetBitmapLabel(wx.Bitmap(fetch_icon("relax.nuclear_symbol", "22x22"), wx.BITMAP_TYPE_ANY)) 192 self.button_isotope.SetFont(font.normal) 193 self.button_isotope.SetSize((-1, 25)) 194 self.button_isotope.SetToolTipString("Set the nuclear isotope types via the spin.isotope user function.") 195 self.gui.Bind(wx.EVT_BUTTON, self.spin_isotope, self.button_isotope) 196 sizer.Add(self.button_isotope, 1, wx.ALL|wx.EXPAND, 0) 197 198 # R1 button. 199 self.button_r1 = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " %s relaxation data"%r1) 200 self.button_r1.SetBitmapLabel(wx.Bitmap(fetch_icon("relax.fid", "22x22"), wx.BITMAP_TYPE_ANY)) 201 self.button_r1.SetFont(font.normal) 202 self.button_r1.SetSize((-1, 25)) 203 self.button_r1.SetToolTipString("Load the %s relaxation data for the off-resonance %s-type experiments. For all other experiment types this is unused. One %s data set per magnetic field strength must be loaded."%(r1, r1rho, r1)) 204 self.gui.Bind(wx.EVT_BUTTON, self.load_r1_data, self.button_r1) 205 sizer.Add(self.button_r1, 1, wx.ALL|wx.EXPAND, 0) 206 207 # Chemical shift button. 208 self.button_chemical_shift = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Chemical shift") 209 self.button_chemical_shift.SetBitmapLabel(wx.Bitmap(fetch_icon("relax.chemical_shift", "22x22"), wx.BITMAP_TYPE_ANY)) 210 self.button_chemical_shift.SetFont(font.normal) 211 self.button_chemical_shift.SetSize((-1, 25)) 212 self.button_chemical_shift.SetToolTipString("Read chemical shifts from a peak list for the off-resonance %s-type experiments. For all other experiment types this is unused."%r1rho) 213 self.gui.Bind(wx.EVT_BUTTON, self.load_cs_data, self.button_chemical_shift) 214 sizer.Add(self.button_chemical_shift, 1, wx.ALL|wx.EXPAND, 0) 215 216 # Interatomic interaction button. 217 self.button_interatom_define = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Interatomic interaction") 218 self.button_interatom_define.SetBitmapLabel(wx.Bitmap(fetch_icon("relax.dipole_pair", "22x22"), wx.BITMAP_TYPE_ANY)) 219 self.button_interatom_define.SetFont(font.normal) 220 self.button_interatom_define.SetSize((-1, 25)) 221 self.button_interatom_define.SetToolTipString("Define the interatomic interations via the interatom.define user function for the MQ dispersion models.") 222 self.gui.Bind(wx.EVT_BUTTON, self.interatom_define, self.button_interatom_define) 223 sizer.Add(self.button_interatom_define, 1, wx.ALL|wx.EXPAND, 0) 224 225 # value.set button. 226 self.button_value_set = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Value setting") 227 self.button_value_set.SetBitmapLabel(wx.Bitmap(fetch_icon("relax.value", "22x22"), wx.BITMAP_TYPE_ANY)) 228 self.button_value_set.SetFont(font.normal) 229 self.button_value_set.SetSize((-1, 25)) 230 tooltip = "Set certain parameters to experimentally determined values.\n\nThis is simply used to speed up optimisation by skipping this parameter in the initial grid search. The result is that the number of dimensions in the grid search is decreased, resulting in roughly one order of magnitude decrease in time for each parameter in this part of the analysis. Important to note is that the parameter will be optimised after the initial grid search." 231 self.button_value_set.SetToolTipString(tooltip) 232 self.gui.Bind(wx.EVT_BUTTON, self.value_set, self.button_value_set) 233 sizer.Add(self.button_value_set, 1, wx.ALL|wx.EXPAND, 0) 234 235 # Add the element to the box. 236 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
237 238
239 - def assemble_data(self):
240 """Assemble the data required for the Auto_noe class. 241 242 @return: A container with all the data required for the auto-analysis, the missing list, and a list of models that don't match the experiment types. 243 @rtype: class instance, list of str, list of str 244 """ 245 246 # The data container. 247 data = Container() 248 missing = [] 249 model_mismatch = [] 250 251 # The pipe name and bundle. 252 data.pipe_name = self.data.pipe_name 253 data.pipe_bundle = self.data.pipe_bundle 254 255 # Results directories. 256 data.save_dir = self.data.save_dir 257 data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue()) 258 259 # Check if sequence data is loaded 260 if not exists_mol_res_spin_data(): 261 missing.append("Sequence data") 262 263 # Spin variables. 264 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 265 # The message skeleton. 266 msg = "Spin '%s' - %s (try the %s user function)." % (spin_id, "%s", "%s") 267 268 # Test if the nuclear isotope type has been set. 269 if not hasattr(spin, 'isotope') or spin.isotope == None: 270 missing.append(msg % ("nuclear isotope data", "spin.isotope")) 271 272 # Spectral data. 273 if not hasattr(cdp, 'spectrum_ids') or len(cdp.spectrum_ids) < 2: 274 missing.append("Spectral data") 275 276 # The dispersion models. 277 data.models = self.model_field.GetValue() 278 279 # Invalid models. 280 for model in data.models: 281 # Invalid CPMG models. 282 if model != MODEL_NOREX and model in MODEL_LIST_CPMG and not has_cpmg_exp_type(): 283 model_mismatch.append([model, 'CPMG']) 284 285 # Invalid R1rho models. 286 if model != MODEL_NOREX and model in MODEL_LIST_R1RHO and not has_r1rho_exp_type(): 287 model_mismatch.append([model, 'R1rho']) 288 289 # The numeric only solution. 290 data.numeric_only = self.numeric_only.GetValue() 291 292 # Increment size. 293 data.inc = gui_to_int(self.grid_inc.GetValue()) 294 295 # The number of Monte Carlo simulations to be used for error analysis at the end of the analysis. 296 data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 297 data.mc_sim_all_models = self.mc_sim_all_models.GetValue() 298 299 # The insignificance level. 300 data.insignificance = self.insignificance.GetValue() 301 try: 302 data.insignificance = gui_to_float(data.insignificance) 303 except: 304 missing.append("The insignificance level must be a number.") 305 306 # Optimisation precision. 307 data.opt_func_tol = self.opt_func_tol 308 data.opt_max_iterations = self.opt_max_iterations 309 310 # Return the container, the list of missing data, and any models that don't match the experiment types. 311 return data, missing, model_mismatch
312 313
314 - def build_right_box(self):
315 """Construct the right hand box to pack into the main relax_disp box. 316 317 @return: The right hand box element containing all relaxation dispersion GUI elements (excluding the bitmap) to pack into the main box. 318 @rtype: wx.BoxSizer instance 319 """ 320 321 # Use a vertical packing of elements. 322 box = wx.BoxSizer(wx.VERTICAL) 323 324 # Add the frame title. 325 self.add_title(box, "Relaxation dispersion analysis") 326 327 # Display the data pipe. 328 Text_ctrl(box, self, text="The data pipe bundle:", default=self.data.pipe_bundle, tooltip="This is the data pipe bundle associated with this analysis.", editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 329 330 # Add the results directory GUI element. 331 self.field_results_dir = Text_ctrl(box, self, text="Results directory:", icon=fetch_icon('oxygen.actions.document-open-folder', "16x16"), default=self.data.save_dir, tooltip="The directory in which all automatically created files will be saved.", tooltip_button="Select the results directory.", fn=self.results_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 332 333 # Add the results directory GUI element. 334 tooltip = "The optional directory containing the dispersion auto-analysis results from a previous run. The optimised parameters from these previous results will be used as the starting point for optimisation rather than performing a grid search. This is essential for when large spin clusters are specified, as a grid search becomes prohibitively expensive with clusters of three or more spins. At some point a RelaxError will occur because the grid search is impossibly large. For the cluster specific parameters, i.e. the populations of the states and the exchange parameters, an average value will be used as the starting point. For all other parameters, the R20 values for each spin and magnetic field, as well as the parameters related to the chemical shift difference dw, the optimised values of the previous run will be directly copied." 335 self.field_pre_run_dir = Text_ctrl(box, self, text="Previous run directory:", icon=fetch_icon('oxygen.actions.document-open-folder', "16x16"), tooltip=tooltip, tooltip_button="Select the results directory of the previous run.", fn=self.pre_run_directory, button=True, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 336 337 # Add the spin GUI element. 338 self.add_spin_systems(box, self) 339 340 # Spin cluster setup. 341 self.field_cluster = Text_ctrl(box, self, text="Spin cluster IDs:", button_text=" Cluster", icon=fetch_icon("relax.cluster", "16x16"), tooltip="The list of currently defined spin clusters. A spin cluster will share the same the dispersion parameters during the optimisation of the dispersion model. The special 'free spins' cluster ID refers to all non-clustered spins.", tooltip_button="Define clusters of spins using the relax_disp.cluster user function.", fn=self.relax_disp_cluster, button=True, editable=False, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 342 343 # Add the buttons. 344 box.AddSpacer(20) 345 self.add_buttons(box=box) 346 347 # Add the peak list selection GUI element, with spacing. 348 box.AddSpacer(20) 349 self.peak_intensity = Spectra_list(gui=self.gui, parent=self, box=box, id=str(self.data_index), fn_add=self.peak_wizard_launch, relax_disp_flag=True) 350 box.AddSpacer(10) 351 352 # Add the dispersion models GUI element, with spacing. 353 self.model_field = Disp_model_list(self, box) 354 self.model_field.set_value(self.data.disp_models) 355 356 # The numeric only solution. 357 tooltip = "The class of models to use in the final model selection.\n\nThe default of False allows all dispersion models to be compared for statistical significance in the analysis (no exchange, the analytic models and the numeric models). The value of True will activate a pure numeric solution - the analytic models will be optimised, as they are very useful for replacing the grid search for the numeric models, but the final model selection will not include them." 358 self.numeric_only = Boolean_ctrl(box, self, text="Pure numeric solutions:", default=False, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 359 360 # The grid search optimisation settings. 361 self.grid_inc = Spin_ctrl(box, self, text="Grid search increments:", default=21, 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) 362 363 # The MC simulation settings. 364 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. For best results, at least 500 is recommended.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 365 self.mc_sim_all_models = Boolean_ctrl(box, self, text="Per model error analysis:", default=False, tooltip="A flag which if True will cause Monte Carlo simulations to be performed for each individual model. Otherwise Monte Carlo simulations will be reserved for the final model.", width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 366 367 # The insignificance cutoff. 368 tooltip = "The %s/%s value in rad/s by which to judge insignificance. If the maximum difference between two points on all dispersion curves for a spin is less than this value, that spin will be deselected. This does not affect the '%s' model. Set this value to 0.0 to use all data." % (r2eff, r1rho, MODEL_NOREX) 369 self.insignificance = Float_ctrl(box, self, text="Insignificance level:", default=1.0, tooltip=tooltip, width_text=self.width_text, width_button=self.width_button, spacer=self.spacer_horizontal) 370 371 # Stretchable spacing (with a minimal space). 372 box.AddSpacer(30) 373 box.AddStretchSpacer() 374 375 # Add the execution GUI element. 376 self.button_exec_relax = self.add_execute_analysis(box, self.execute) 377 378 # Return the box. 379 return box
380 381
382 - def delete(self):
383 """Unregister the spin count from the user functions.""" 384 385 # Unregister the observer methods. 386 self.observer_register(remove=True) 387 388 # Clean up the peak intensity object. 389 self.peak_intensity.delete()
390 391
392 - def execute(self, event):
393 """Set up, execute, and process the automatic Rx analysis. 394 395 @param event: The wx event. 396 @type event: wx event 397 """ 398 399 # Flush the GUI interpreter internal queue to make sure all user functions are complete. 400 self.gui.interpreter.flush() 401 402 # relax execution lock. 403 if status.exec_lock.locked(): 404 error_message("relax is currently executing.", "relax execution lock") 405 event.Skip() 406 return 407 408 # User warning to close windows. 409 self.gui.close_windows() 410 411 # Synchronise the frame data to the relax data store. 412 self.sync_ds(upload=True) 413 414 # Assemble all the data needed for the auto-analysis. 415 data, missing, model_mismatch = self.assemble_data() 416 417 # Missing data. 418 if len(missing): 419 Missing_data(missing) 420 return 421 422 # Model mismatch. 423 if len(model_mismatch): 424 # Generate the text. 425 text = '' 426 for model, exp in model_mismatch: 427 text += "The '%s' %s model cannot be used as no %s experiment types have been set up.\n" % (model, exp, exp) 428 429 # The error message. 430 error_message(text, caption='Model mismatch') 431 return 432 433 # Display the relax controller, and go to the end of the log window. 434 self.gui.show_controller(None) 435 self.gui.controller.log_panel.on_goto_end(None) 436 437 # Start the thread. 438 self.thread = Execute_relax_disp(self.gui, data, self.data_index) 439 self.thread.start() 440 441 # Terminate the event. 442 event.Skip()
443 444
445 - def interatom_define(self, event=None):
446 """Define the interatomic interactions of the spins via the interatom.define user function. 447 448 @keyword event: The wx event. 449 @type event: wx event 450 """ 451 452 # Call the user function. 453 uf_store['interatom.define'](wx_wizard_modal=True, spin_id1='@N', spin_id2='@H')
454 455
456 - def load_cs_data(self, event=None):
457 """Read chemical shift data from a peak list via the chemical_shift.read user function. 458 459 @keyword event: The wx event. 460 @type event: wx event 461 """ 462 463 # Call the user function. 464 uf_store['chemical_shift.read'](wx_wizard_modal=True)
465 466
467 - def load_r1_data(self, event=None):
468 """Load R1 relaxation data via the relax_data.read user function. 469 470 @keyword event: The wx event. 471 @type event: wx event 472 """ 473 474 # Call the user function. 475 uf_store['relax_data.read'](wx_wizard_modal=True, ri_type='R1')
476 477
478 - def observer_register(self, remove=False):
479 """Register and unregister methods with the observer objects. 480 481 @keyword remove: If set to True, then the methods will be unregistered. 482 @type remove: False 483 """ 484 485 # Register. 486 if not remove: 487 status.observers.gui_uf.register('spin count - %s' % self.data.pipe_bundle, self.update_spin_count, method_name='update_spin_count') 488 status.observers.exec_lock.register(self.data.pipe_bundle, self.activate, method_name='activate') 489 status.observers.gui_uf.register('clusters - %s' % self.data.pipe_bundle, self.update_clusters, method_name='update_clusters') 490 491 # Unregister. 492 else: 493 # The methods. 494 status.observers.gui_uf.unregister('spin count - %s' % self.data.pipe_bundle) 495 status.observers.exec_lock.unregister(self.data.pipe_bundle) 496 status.observers.gui_uf.unregister('isotopes - %s' % self.data.pipe_bundle) 497 status.observers.gui_uf.unregister('clusters - %s' % self.data.pipe_bundle) 498 499 # The embedded objects methods. 500 self.peak_intensity.observer_register(remove=True)
501 502
503 - def peak_wizard_launch(self, event):
504 """Launch the peak loading wizard. 505 506 @param event: The wx event. 507 @type event: wx event 508 """ 509 510 # A new wizard instance. 511 self.peak_wizard = Peak_intensity_wizard(relax_disp=True)
512 513
514 - def pre_run_directory(self, event):
515 """The pre-run directory selection. 516 517 @param event: The wx event. 518 @type event: wx event 519 """ 520 521 # The dialog. 522 dialog = RelaxDirDialog(parent=self, message='Select the directory of the previous run', defaultPath=self.field_pre_run_dir.GetValue()) 523 524 # Show the dialog and catch if no file has been selected. 525 if status.show_gui and dialog.ShowModal() != wx.ID_OK: 526 # Don't do anything. 527 return 528 529 # The path (don't do anything if not set). 530 path = gui_to_str(dialog.get_path()) 531 if not path: 532 return 533 534 # Place the path in the text box. 535 self.field_pre_run_dir.SetValue(str_to_gui(path))
536 537
538 - def relax_disp_cluster(self, event=None):
539 """Set up spin clustering via the relax_disp.cluster user function. 540 541 @keyword event: The wx event. 542 @type event: wx event 543 """ 544 545 # Call the user function. 546 uf_store['relax_disp.cluster'](wx_wizard_modal=True)
547 548
549 - def results_directory(self, event):
550 """The results directory selection. 551 552 @param event: The wx event. 553 @type event: wx event 554 """ 555 556 # The dialog. 557 dialog = RelaxDirDialog(parent=self, message='Select the results directory', defaultPath=self.field_results_dir.GetValue()) 558 559 # Show the dialog and catch if no file has been selected. 560 if status.show_gui and dialog.ShowModal() != wx.ID_OK: 561 # Don't do anything. 562 return 563 564 # The path (don't do anything if not set). 565 path = gui_to_str(dialog.get_path()) 566 if not path: 567 return 568 569 # Store the path. 570 self.data.save_dir = path 571 572 # Place the path in the text box. 573 self.field_results_dir.SetValue(str_to_gui(path))
574 575
576 - def spin_isotope(self, event=None):
577 """Set the nuclear isotope types of the spins via the spin.isotope user function. 578 579 @keyword event: The wx event. 580 @type event: wx event 581 """ 582 583 # Call the user function. 584 uf_store['spin.isotope'](wx_wizard_modal=True, isotope='15N', spin_id='@N*')
585 586
587 - def sync_ds(self, upload=False):
588 """Synchronise the analysis frame and the relax data store, both ways. 589 590 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. 591 592 @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. 593 @type upload: bool 594 """ 595 596 # The numeric solution only flag. 597 if upload: 598 self.data.numeric_only = self.numeric_only.GetValue() 599 elif hasattr(self.data, 'numeric_only'): 600 self.numeric_only.SetValue(bool(self.data.numeric_only)) 601 602 # The grid incs. 603 if upload: 604 self.data.grid_inc = gui_to_int(self.grid_inc.GetValue()) 605 elif hasattr(self.data, 'grid_inc'): 606 self.grid_inc.SetValue(int(self.data.grid_inc)) 607 608 # The MC sim number. 609 if upload: 610 self.data.mc_sim_num = gui_to_int(self.mc_sim_num.GetValue()) 611 elif hasattr(self.data, 'mc_sim_num'): 612 self.mc_sim_num.SetValue(int(self.data.mc_sim_num)) 613 614 # The All model MC sim flag. 615 if upload: 616 self.data.mc_sim_all_models = self.mc_sim_all_models.GetValue() 617 elif hasattr(self.data, 'mc_sim_all_models'): 618 self.mc_sim_all_models.SetValue(bool(self.data.mc_sim_all_models)) 619 620 # The insignificance level. 621 if upload: 622 self.data.insignificance = self.insignificance.GetValue() 623 try: 624 self.data.insignificance = gui_to_float(self.data.insignificance) 625 except: 626 pass 627 elif hasattr(self.data, 'insignificance'): 628 self.insignificance.SetValue(float_to_gui(self.data.insignificance)) 629 630 # The results directory. 631 if upload: 632 self.data.save_dir = gui_to_str(self.field_results_dir.GetValue()) 633 else: 634 self.field_results_dir.SetValue(str_to_gui(self.data.save_dir)) 635 636 # The previous run results directory. 637 if upload: 638 self.data.pre_run_dir = gui_to_str(self.field_pre_run_dir.GetValue()) 639 elif hasattr(self.data, 'pre_run_dir'): 640 self.field_pre_run_dir.SetValue(str_to_gui(self.data.pre_run_dir)) 641 642 # The models to use. 643 if upload: 644 self.data.disp_models = self.model_field.GetValue() 645 else: 646 self.model_field.set_value(self.data.disp_models)
647 648
649 - def update_clusters(self):
650 """Update the cluster field.""" 651 652 # Assemble a list of all unique isotope types. 653 cluster_keys = [] 654 if hasattr(cdp, 'clustering'): 655 cluster_keys = sorted(cdp.clustering.keys()) 656 657 # Nothing yet. 658 if not len(cluster_keys): 659 wx.CallAfter(self.field_cluster.SetValue, "free spins") 660 661 # List the clusters. 662 else: 663 # Build the text to show. 664 text = "" 665 if "free spins" in cluster_keys: 666 text += "free spins" 667 for i in range(len(cluster_keys)): 668 if cluster_keys[i] != "free spins": 669 text += ", %s" % cluster_keys[i] 670 671 # Update the text. 672 wx.CallAfter(self.field_cluster.SetValue, text)
673 674
675 - def value_set(self, event=None):
676 """Launch the value.set user function. 677 678 @keyword event: The wx event. 679 @type event: wx event 680 """ 681 682 # Call the user function. 683 uf_store['value.set'](wx_wizard_modal=True)
684 685 686
687 -class Execute_relax_disp(Execute):
688 """The relaxation dispersion analysis execution object.""" 689
690 - def run_analysis(self):
691 """Execute the calculation.""" 692 693 # Optimisation precision. 694 Relax_disp.opt_func_tol = self.data.opt_func_tol 695 Relax_disp.opt_max_iterations = self.data.opt_max_iterations 696 697 # Execute. 698 Relax_disp(pipe_name=self.data.pipe_name, pipe_bundle=self.data.pipe_bundle, results_dir=self.data.save_dir, models=self.data.models, grid_inc=self.data.inc, mc_sim_num=self.data.mc_sim_num, pre_run_dir=self.data.pre_run_dir, mc_sim_all_models=self.data.mc_sim_all_models, insignificance=self.data.insignificance, numeric_only=self.data.numeric_only) 699 700 # Alias the relax data store data. 701 data = ds.relax_gui.analyses[self.data_index]
702 703 704
705 -class Disp_model_list(Model_list):
706 """The diffusion model list GUI element.""" 707 708 # Class variables. 709 desc = "Relaxation dispersion models:" 710 models = [ 711 MODEL_R2EFF, 712 None, 713 MODEL_NOREX, 714 None, 715 MODEL_LM63, 716 MODEL_LM63_3SITE, 717 MODEL_CR72, 718 MODEL_CR72_FULL, 719 MODEL_IT99, 720 MODEL_TSMFK01, 721 MODEL_NS_CPMG_2SITE_EXPANDED, 722 MODEL_NS_CPMG_2SITE_3D, 723 MODEL_NS_CPMG_2SITE_3D_FULL, 724 MODEL_NS_CPMG_2SITE_STAR, 725 MODEL_NS_CPMG_2SITE_STAR_FULL, 726 None, 727 MODEL_M61, 728 MODEL_M61B, 729 MODEL_DPL94, 730 MODEL_TP02, 731 MODEL_TAP03, 732 MODEL_MP05, 733 MODEL_NS_R1RHO_2SITE, 734 MODEL_NS_R1RHO_3SITE_LINEAR, 735 MODEL_NS_R1RHO_3SITE, 736 None, 737 MODEL_MMQ_CR72, 738 MODEL_NS_MMQ_2SITE, 739 MODEL_NS_MMQ_3SITE_LINEAR, 740 MODEL_NS_MMQ_3SITE 741 ] 742 params = [ 743 "{%s/%s, %s}" % (r2eff, r1rho, i0), 744 None, 745 "{%s, ...}" % (r2), 746 None, 747 "{%s, ..., %s, %s}" % (r2, phi_ex, kex), 748 "{%s, ..., %s, kB, %s, kC}" % (r2, phi_exB, phi_exC), 749 "{%s, ..., pA, %s, %s}" % (r2, dw, kex), 750 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex), 751 "{%s, ..., %s, %s, %s}" % (r2, phi_ex, padw2, kex), 752 "{%s, ..., %s, k_AB}" % (r2a, dw), 753 "{%s, ..., pA, %s, %s}" % (r2, dw, kex), 754 "{%s, ..., pA, %s, %s}" % (r2, dw, kex), 755 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex), 756 "{%s, ..., pA, %s, %s}" % (r2, dw, kex), 757 "{%s, %s, ..., pA, %s, %s}" % (r2a, r2b, dw, kex), 758 None, 759 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex), 760 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex), 761 "{%s, ..., %s, %s}" % (r1rho_prime, phi_ex, kex), 762 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex), 763 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex), 764 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex), 765 "{%s, ..., pA, %s, %s}" % (r1rho_prime, dw, kex), 766 "{%s, ..., pA, %s, %s, pB, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC), 767 "{%s, ..., pA, %s, %s, pB, %s, %s, %s}" % (r1rho_prime, dw_AB, kAB, dw_BC, kBC, kAC), 768 None, 769 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex), 770 "{%s, ..., pA, %s, %s, %s}" % (r2, dw, dwH, kex), 771 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC), 772 "{%s, ..., pA, %s, %s, %s, pB, %s, %s, %s, %s}" % (r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC, kAC) 773 ] 774 model_desc = [ 775 "The base model for determining the %s/%s values and errors for all other models." % (r2eff, r1rho), 776 None, 777 "The model for no chemical exchange relaxation.", 778 None, 779 "The original Luz and Meiboom (1963) 2-site fast exchange equation.", 780 "The original Luz and Meiboom (1963) 3-site fast exchange equation.", 781 "The Carver and Richards (1972) 2-site equation for all time scales (with %s = %s)." % (r2a, r2b), 782 "The Carver and Richards (1972) 2-site equation for all time scales.", 783 "The Ishima and Torchia (1999) 2-site model for all time scales with pA >> pB.", 784 "The Tollinger et al. (2001) 2-site very-slow exchange model.", 785 "The 2-site numerical solution expanded using Maple by Nikolai Skrynnikov.", 786 "The 2-site numerical solution using 3D magnetisation vectors (with %s = %s)." % (r2a, r2b), 787 "The 2-site numerical solution using 3D magnetisation vectors.", 788 "The 2-site numerical solution using complex conjugate matrices (with %s = %s)." % (r2a, r2b), 789 "The 2-site numerical solution using complex conjugate matrices.", 790 None, 791 "The Meiboom (1961) 2-site fast exchange equation.", 792 "The Meiboom (1961) 2-site equation for all time scales with pA >> pB.", 793 "The Davis, Perlman and London (1994) 2-site fast exchange equation.", 794 "The Trott and Palmer (2002) 2-site equation for all time scales.", 795 "The Trott, Abergel and Palmer (2003) off-resonance 2-site equation for all time scales.", 796 "The Miloushev and Palmer (2005) off-resonance 2-site equation for all time scales.", 797 "The 2-site numerical solution using 3D magnetisation vectors.", 798 "The 3-site linearised numerical solution using 3D magnetisation vectors.", 799 "The 3-site numerical solution using 3D magnetisation vectors.", 800 None, 801 "The CR72 2-site model extended to MMQ CPMG data by Korzhnev et al., 2004.", 802 "The 2-site numerical solution of Korzhnev et al. (2004) from multi-quantum CPMG data.", 803 "The 3-site linearised numerical solution of Korzhnev et al. (2005) for MMQ CPMG data.", 804 "The 3-site numerical solution of Korzhnev et al. (2005) for MMQ CPMG data." 805 ] 806 size = wx.Size(1024, 750) 807 tooltip = "The list of all relaxation dispersion models to be optimised as part of the protocol." 808 tooltip_button = "Open the model list selector window."
809