Package auto_analyses :: Module relax_disp
[hide private]
[frames] | no frames]

Source Code for Module auto_analyses.relax_disp

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2013-2014 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 automatic relaxation dispersion protocol.""" 
 24   
 25  # Python module imports. 
 26  from copy import deepcopy 
 27  from os import F_OK, access, getcwd, sep 
 28  import sys 
 29  from warnings import warn 
 30   
 31  # relax module imports. 
 32  from lib.errors import RelaxError, RelaxNoPipeError 
 33  from lib.text.sectioning import section, subsection, subtitle, title 
 34  from lib.warnings import RelaxWarning 
 35  from pipe_control.mol_res_spin import return_spin, spin_loop 
 36  from pipe_control.pipes import has_pipe 
 37  from prompt.interpreter import Interpreter 
 38  from specific_analyses.relax_disp.data import has_exponential_exp_type, has_cpmg_exp_type, has_fixed_time_exp_type, has_r1rho_exp_type, loop_frq 
 39  from specific_analyses.relax_disp.variables import MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_ANALYTIC, MODEL_LIST_R1RHO, MODEL_LIST_R1RHO_FULL, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_MP05, MODEL_MMQ_CR72, 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_PARAMS, MODEL_R2EFF, MODEL_TAP03, MODEL_TP02, MODEL_TSMFK01 
 40  from status import Status; status = Status() 
 41   
 42   
43 -class Relax_disp:
44 """The relaxation dispersion auto-analysis.""" 45 46 # Some class variables. 47 opt_func_tol = 1e-25 48 opt_max_iterations = int(1e7) 49
50 - def __init__(self, pipe_name=None, pipe_bundle=None, results_dir=None, models=[MODEL_R2EFF], grid_inc=11, mc_sim_num=500, exp_mc_sim_num=None, modsel='AIC', pre_run_dir=None, insignificance=0.0, numeric_only=False, mc_sim_all_models=False, eliminate=True, set_grid_r20=False):
51 """Perform a full relaxation dispersion analysis for the given list of models. 52 53 @keyword pipe_name: The name of the data pipe containing all of the data for the analysis. 54 @type pipe_name: str 55 @keyword pipe_bundle: The data pipe bundle to associate all spawned data pipes with. 56 @type pipe_bundle: str 57 @keyword results_dir: The directory where results files are saved. 58 @type results_dir: str 59 @keyword models: The list of relaxation dispersion models to optimise. 60 @type models: list of str 61 @keyword grid_inc: Number of grid search increments. If set to None, then the grid search will be turned off and the default parameter values will be used instead. 62 @type grid_inc: int or None 63 @keyword mc_sim_num: The number of Monte Carlo simulations to be used for error analysis at the end of the analysis. 64 @type mc_sim_num: int 65 @keyword exp_mc_sim_num: The number of Monte Carlo simulations for the error analysis in the 'R2eff' model when exponential curves are fitted. This defaults to the value of the mc_sim_num argument when not given. For the 2-point fixed-time calculation for the 'R2eff' model, this argument is ignored. 66 @type exp_mc_sim_num: int or None 67 @type 68 @keyword modsel: The model selection technique to use in the analysis to determine which model is the best for each spin cluster. This can currently be one of 'AIC', 'AICc', and 'BIC'. 69 @type modsel: str 70 @keyword pre_run_dir: 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. 71 @type pre_run_dir: None or str 72 @keyword insignificance: The R2eff/R1rho 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 'No Rex' model. Set this value to 0.0 to use all data. The value will be passed on to the relax_disp.insignificance user function. 73 @type insignificance: float 74 @keyword numeric_only: The class of models to use in the model selection. The default of False allows all dispersion models to be used 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. 75 @type numeric_only: bool 76 @keyword mc_sim_all_models: 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. 77 @type mc_sim_all_models: bool 78 @keyword eliminate: A flag which if True will enable the elimination of failed models and failed Monte Carlo simulations through the eliminate user function. 79 @type eliminate: bool 80 @keyword set_grid_r20: A flag which if True will set the grid R20 values from the minimum R2eff values through the r20_from_min_r2eff user function. This will speed up the grid search with a factor GRID_INC^(Nr_spec_freq). For a CPMG experiment with two fields and standard GRID_INC=21, the speed-up is a factor 441. 81 @type set_grid_r20: bool 82 """ 83 84 # Printout. 85 title(file=sys.stdout, text="Relaxation dispersion auto-analysis", prespace=4) 86 87 # Execution lock. 88 status.exec_lock.acquire(pipe_bundle, mode='auto-analysis') 89 90 # Set up the analysis status object. 91 status.init_auto_analysis(pipe_bundle, type='relax_disp') 92 status.current_analysis = pipe_bundle 93 94 # Store the args. 95 self.pipe_name = pipe_name 96 self.pipe_bundle = pipe_bundle 97 self.results_dir = results_dir 98 self.models = models 99 self.grid_inc = grid_inc 100 self.mc_sim_num = mc_sim_num 101 self.exp_mc_sim_num = exp_mc_sim_num 102 self.modsel = modsel 103 self.pre_run_dir = pre_run_dir 104 self.insignificance = insignificance 105 self.set_grid_r20 = set_grid_r20 106 self.numeric_only = numeric_only 107 self.mc_sim_all_models = mc_sim_all_models 108 self.eliminate = eliminate 109 110 # No results directory, so default to the current directory. 111 if not self.results_dir: 112 self.results_dir = getcwd() 113 114 # Data checks. 115 self.check_vars() 116 117 # Load the interpreter. 118 self.interpreter = Interpreter(show_script=False, raise_relax_error=True) 119 self.interpreter.populate_self() 120 self.interpreter.on(verbose=False) 121 122 # Execute. 123 try: 124 self.run() 125 126 # Finish and unlock execution. 127 finally: 128 status.auto_analysis[self.pipe_bundle].fin = True 129 status.current_analysis = None 130 status.exec_lock.release()
131 132
133 - def is_model_for_selection(self, model=None):
134 """Determine if the model should be used for model selection. 135 136 @keyword model: The model to check. 137 @type model: str 138 @return: True if the model should be included in the model selection list, False if not. 139 @rtype: bool 140 """ 141 142 # Skip the 'R2eff' base model. 143 if model == 'R2eff': 144 return False 145 146 # Do not use the analytic models. 147 if self.numeric_only and model in MODEL_LIST_ANALYTIC: 148 return False 149 150 # All models allowed. 151 return True
152 153
154 - def check_vars(self):
155 """Check that the user has set the variables correctly.""" 156 157 # Printout. 158 section(file=sys.stdout, text="Variable checking", prespace=2) 159 160 # The pipe name. 161 if not has_pipe(self.pipe_name): 162 raise RelaxNoPipeError(self.pipe_name) 163 164 # Check the model selection. 165 allowed = ['AIC', 'AICc', 'BIC'] 166 if self.modsel not in allowed: 167 raise RelaxError("The model selection technique '%s' is not in the allowed list of %s." % (self.modsel, allowed)) 168 169 # Some warning for the user if the pure numeric solution is selected. 170 if self.numeric_only: 171 # Loop over all models. 172 for model in self.models: 173 # Skip the models used for nesting. 174 if model in [MODEL_CR72, MODEL_MMQ_CR72, MODEL_MP05]: 175 continue 176 177 # Warnings for all other analytic models. 178 if model in MODEL_LIST_ANALYTIC: 179 warn(RelaxWarning("The analytic model '%s' will be optimised but will not be used in any way in this numeric model only auto-analysis." % model)) 180 181 # Printout. 182 print("The dispersion auto-analysis variables are OK.")
183 184
185 - def error_analysis(self):
186 """Perform an error analysis of the peak intensities for each field strength separately.""" 187 188 # Printout. 189 section(file=sys.stdout, text="Error analysis", prespace=2) 190 191 # Check if intensity errors have already been calculated by the user. 192 precalc = True 193 for spin in spin_loop(skip_desel=True): 194 # No structure. 195 if not hasattr(spin, 'peak_intensity_err'): 196 precalc = False 197 break 198 199 # Determine if a spectrum ID is missing from the list. 200 for id in cdp.spectrum_ids: 201 if id not in spin.peak_intensity_err: 202 precalc = False 203 break 204 205 # Skip. 206 if precalc: 207 print("Skipping the error analysis as it has already been performed.") 208 return 209 210 # Loop over the spectrometer frequencies. 211 for frq in loop_frq(): 212 # Generate a list of spectrum IDs matching the frequency. 213 ids = [] 214 for id in cdp.spectrum_ids: 215 # Check that the spectrometer frequency matches. 216 match_frq = True 217 if frq != None and cdp.spectrometer_frq[id] != frq: 218 match_frq = False 219 220 # Add the ID. 221 if match_frq: 222 ids.append(id) 223 224 # Run the error analysis on the subset. 225 self.interpreter.spectrum.error_analysis(subset=ids)
226 227
228 - def name_pipe(self, prefix):
229 """Generate a unique name for the data pipe. 230 231 @param prefix: The prefix of the data pipe name. 232 @type prefix: str 233 """ 234 235 # The unique pipe name. 236 name = "%s - %s" % (prefix, self.pipe_bundle) 237 238 # Return the name. 239 return name
240 241
242 - def nesting(self, model=None):
243 """Support for model nesting. 244 245 If model nesting is detected, the optimised parameters from the simpler model will be used for the more complex model. The method will then signal if the nesting condition is met for the model, allowing the grid search to be skipped. 246 247 248 @keyword model: The model to be optimised. 249 @type model: str 250 @return: True if the model is the more complex model in a nested pair and the parameters of the simpler model have been copied. False otherwise. 251 @rtype: bool 252 """ 253 254 # Printout. 255 subsection(file=sys.stdout, text="Nesting and model equivalence checks", prespace=1) 256 257 # The simpler model. 258 nested_pipe = None 259 if model == MODEL_LM63_3SITE and MODEL_LM63 in self.models: 260 nested_pipe = self.name_pipe(MODEL_LM63) 261 if model == MODEL_CR72_FULL and MODEL_CR72 in self.models: 262 nested_pipe = self.name_pipe(MODEL_CR72) 263 if model == MODEL_MMQ_CR72 and MODEL_CR72 in self.models: 264 nested_pipe = self.name_pipe(MODEL_CR72) 265 if model == MODEL_NS_CPMG_2SITE_3D_FULL and MODEL_NS_CPMG_2SITE_3D in self.models: 266 nested_pipe = self.name_pipe(MODEL_NS_CPMG_2SITE_3D) 267 if model == MODEL_NS_CPMG_2SITE_STAR_FULL and MODEL_NS_CPMG_2SITE_STAR in self.models: 268 nested_pipe = self.name_pipe(MODEL_NS_CPMG_2SITE_STAR) 269 if model == MODEL_NS_MMQ_3SITE_LINEAR and MODEL_NS_MMQ_2SITE in self.models: 270 nested_pipe = self.name_pipe(MODEL_NS_MMQ_2SITE) 271 if model == MODEL_NS_MMQ_3SITE: 272 if MODEL_NS_MMQ_3SITE_LINEAR in self.models: 273 nested_pipe = self.name_pipe(MODEL_NS_MMQ_3SITE_LINEAR) 274 elif MODEL_NS_MMQ_2SITE in self.models: 275 nested_pipe = self.name_pipe(MODEL_NS_MMQ_2SITE) 276 if model == MODEL_NS_R1RHO_3SITE_LINEAR and MODEL_NS_R1RHO_2SITE in self.models: 277 nested_pipe = self.name_pipe(MODEL_NS_R1RHO_2SITE) 278 if model == MODEL_NS_R1RHO_3SITE: 279 if MODEL_NS_R1RHO_3SITE_LINEAR in self.models: 280 nested_pipe = self.name_pipe(MODEL_NS_R1RHO_3SITE_LINEAR) 281 elif MODEL_NS_R1RHO_2SITE in self.models: 282 nested_pipe = self.name_pipe(MODEL_NS_R1RHO_2SITE) 283 284 285 # Using the analytic solution. 286 analytic = False 287 if model in [MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR] and MODEL_CR72 in self.models: 288 nested_pipe = self.name_pipe(MODEL_CR72) 289 analytic = True 290 elif model == MODEL_NS_MMQ_2SITE and MODEL_MMQ_CR72 in self.models: 291 nested_pipe = self.name_pipe(MODEL_MMQ_CR72) 292 analytic = True 293 if model == MODEL_NS_R1RHO_2SITE and MODEL_MP05 in self.models: 294 nested_pipe = self.name_pipe(MODEL_MP05) 295 analytic = True 296 297 # No nesting. 298 if not nested_pipe: 299 print("No model nesting or model equivalence detected.") 300 return False 301 302 # Printout. 303 if analytic: 304 print("Model equivalence detected, copying the optimised parameters from the analytic '%s' model rather than performing a grid search." % nested_pipe) 305 else: 306 print("Model nesting detected, copying the optimised parameters from the '%s' model rather than performing a grid search." % nested_pipe) 307 308 # Loop over the spins to copy the parameters. 309 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 310 # Get the nested spin. 311 nested_spin = return_spin(spin_id=spin_id, pipe=nested_pipe) 312 313 # The R20 parameters. 314 if hasattr(nested_spin, 'r2'): 315 if model in [MODEL_CR72_FULL, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_STAR_FULL]: 316 setattr(spin, 'r2a', deepcopy(nested_spin.r2)) 317 setattr(spin, 'r2b', deepcopy(nested_spin.r2)) 318 else: 319 setattr(spin, 'r2', deepcopy(nested_spin.r2)) 320 321 # The LM63 3-site model parameters. 322 if model == MODEL_LM63_3SITE: 323 setattr(spin, 'phi_ex_B', deepcopy(nested_spin.phi_ex)) 324 setattr(spin, 'phi_ex_C', deepcopy(nested_spin.phi_ex)) 325 setattr(spin, 'kB', deepcopy(nested_spin.kex)) 326 setattr(spin, 'kC', deepcopy(nested_spin.kex)) 327 328 # All other spin parameters. 329 for param in spin.params: 330 if param in ['r2', 'r2a', 'r2b']: 331 continue 332 333 # The parameter does not exist. 334 if not hasattr(nested_spin, param): 335 continue 336 337 # Skip the LM63 3-site model parameters 338 if model == MODEL_LM63_3SITE and param in ['phi_ex', 'kex']: 339 continue 340 341 # Copy the parameter. 342 setattr(spin, param, deepcopy(getattr(nested_spin, param))) 343 344 # Nesting. 345 return True
346 347
348 - def optimise(self, model=None):
349 """Optimise the model, taking model nesting into account. 350 351 @keyword model: The model to be optimised. 352 @type model: str 353 """ 354 355 # Printout. 356 section(file=sys.stdout, text="Optimisation", prespace=2) 357 358 # Deselect insignificant spins. 359 if model not in ['R2eff', 'No Rex']: 360 self.interpreter.relax_disp.insignificance(level=self.insignificance) 361 362 # Speed-up grid-search by using minium R2eff value. 363 if self.set_grid_r20 and model != MODEL_R2EFF: 364 self.interpreter.relax_disp.r20_from_min_r2eff(force=True) 365 366 # Use pre-run results as the optimisation starting point. 367 if self.pre_run_dir: 368 self.pre_run_parameters(model=model) 369 370 # Otherwise use the normal nesting check and grid search if not nested. 371 else: 372 # Nested model simplification. 373 nested = self.nesting(model=model) 374 375 # Otherwise use a grid search of default values to start optimisation with. 376 if not nested: 377 # Grid search. 378 if self.grid_inc: 379 self.interpreter.grid_search(inc=self.grid_inc) 380 381 # Default values. 382 else: 383 for param in MODEL_PARAMS[model]: 384 self.interpreter.value.set(param=param, index=None) 385 386 # Minimise. 387 self.interpreter.minimise('simplex', func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations, constraints=True) 388 389 # Model elimination. 390 if self.eliminate: 391 self.interpreter.eliminate() 392 393 # Monte Carlo simulations. 394 if self.mc_sim_all_models or len(self.models) < 2 or model == 'R2eff': 395 if model == 'R2eff' and self.exp_mc_sim_num != None: 396 self.interpreter.monte_carlo.setup(number=self.exp_mc_sim_num) 397 else: 398 self.interpreter.monte_carlo.setup(number=self.mc_sim_num) 399 self.interpreter.monte_carlo.create_data() 400 self.interpreter.monte_carlo.initial_values() 401 self.interpreter.minimise('simplex', func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations, constraints=True) 402 if self.eliminate: 403 self.interpreter.eliminate() 404 self.interpreter.monte_carlo.error_analysis()
405 406
407 - def pre_run_parameters(self, model=None):
408 """Copy parameters from an earlier analysis. 409 410 @keyword model: The model to be optimised. 411 @type model: str 412 """ 413 414 # Printout. 415 subsection(file=sys.stdout, text="Pre-run parameters", prespace=1) 416 417 # The data pipe name. 418 pipe_name = self.name_pipe('pre') 419 420 # Create a temporary data pipe for the previous run. 421 self.interpreter.pipe.create(pipe_name=pipe_name, pipe_type='relax_disp') 422 423 # Load the previous results. 424 path = self.pre_run_dir + sep + model 425 self.interpreter.results.read(file='results', dir=path) 426 427 # Copy the parameters. 428 self.interpreter.relax_disp.parameter_copy(pipe_from=pipe_name, pipe_to=self.name_pipe(model)) 429 430 # Finally, switch back to the original data pipe and delete the temporary one. 431 self.interpreter.pipe.switch(pipe_name=self.name_pipe(model)) 432 self.interpreter.pipe.delete(pipe_name=pipe_name)
433 434
435 - def run(self):
436 """Execute the auto-analysis.""" 437 438 # Peak intensity error analysis. 439 if MODEL_R2EFF in self.models: 440 self.error_analysis() 441 442 # Loop over the models. 443 self.model_pipes = [] 444 for model in self.models: 445 # Printout. 446 subtitle(file=sys.stdout, text="The '%s' model" % model, prespace=3) 447 448 # The results directory path. 449 path = self.results_dir+sep+model 450 451 # The name of the data pipe for the model. 452 model_pipe = self.name_pipe(model) 453 if self.is_model_for_selection(model): 454 self.model_pipes.append(model_pipe) 455 456 # Check that results do not already exist - i.e. a previous run was interrupted. 457 path1 = path + sep + 'results' 458 path2 = path1 + '.bz2' 459 path3 = path1 + '.gz' 460 if access(path1, F_OK) or access(path2, F_OK) or access(path2, F_OK): 461 # Printout. 462 print("Detected the presence of results files for the '%s' model - loading these instead of performing optimisation for a second time." % model) 463 464 # Create a data pipe and switch to it. 465 self.interpreter.pipe.create(pipe_name=model_pipe, pipe_type='relax_disp', bundle=self.pipe_bundle) 466 self.interpreter.pipe.switch(model_pipe) 467 468 # Load the results. 469 self.interpreter.results.read(file='results', dir=path) 470 471 # Jump to the next model. 472 continue 473 474 # Create the data pipe by copying the base pipe, then switching to it. 475 self.interpreter.pipe.copy(pipe_from=self.pipe_name, pipe_to=model_pipe, bundle_to=self.pipe_bundle) 476 self.interpreter.pipe.switch(model_pipe) 477 478 # Select the model. 479 self.interpreter.relax_disp.select_model(model) 480 481 # Copy the R2eff values from the R2eff model data pipe. 482 if model != MODEL_R2EFF and MODEL_R2EFF in self.models: 483 self.interpreter.value.copy(pipe_from=self.name_pipe(MODEL_R2EFF), pipe_to=model_pipe, param='r2eff') 484 485 # Calculate the R2eff values for the fixed relaxation time period data types. 486 if model == MODEL_R2EFF and not has_exponential_exp_type(): 487 self.interpreter.calc() 488 489 # Optimise the model. 490 else: 491 self.optimise(model=model) 492 493 # Write out the results. 494 self.write_results(path=path, model=model) 495 496 # The final model selection data pipe. 497 if len(self.models) >= 2: 498 # Printout. 499 section(file=sys.stdout, text="Final results", prespace=2) 500 501 # Perform model selection. 502 self.interpreter.model_selection(method=self.modsel, modsel_pipe=self.name_pipe('final'), bundle=self.pipe_bundle, pipes=self.model_pipes) 503 504 # Final Monte Carlo simulations only. 505 if not self.mc_sim_all_models: 506 self.interpreter.monte_carlo.setup(number=self.mc_sim_num) 507 self.interpreter.monte_carlo.create_data() 508 self.interpreter.monte_carlo.initial_values() 509 self.interpreter.minimise('simplex', func_tol=self.opt_func_tol, max_iter=self.opt_max_iterations, constraints=True) 510 if self.eliminate: 511 self.interpreter.eliminate() 512 self.interpreter.monte_carlo.error_analysis() 513 514 # Writing out the final results. 515 self.write_results(path=self.results_dir+sep+'final') 516 517 # No model selection. 518 else: 519 warn(RelaxWarning("Model selection in the dispersion auto-analysis has been skipped as only %s models have been optimised." % len(self.model_pipes))) 520 521 # Finally save the program state. 522 self.interpreter.state.save(state='final_state', dir=self.results_dir, force=True)
523 524
525 - def write_results(self, path=None, model=None):
526 """Create a set of results, text and Grace files for the current data pipe. 527 528 @keyword path: The directory to place the files into. 529 @type path: str 530 """ 531 532 # Printout. 533 section(file=sys.stdout, text="Results writing", prespace=2) 534 535 # Exponential curves. 536 if model == 'R2eff' and has_exponential_exp_type(): 537 self.interpreter.relax_disp.plot_exp_curves(file='intensities.agr', dir=path, force=True) # Average peak intensities. 538 self.interpreter.relax_disp.plot_exp_curves(file='intensities_norm.agr', dir=path, force=True, norm=True) # Average peak intensities (normalised). 539 540 # Dispersion curves. 541 self.interpreter.relax_disp.plot_disp_curves(dir=path, force=True) 542 self.interpreter.relax_disp.write_disp_curves(dir=path, force=True) 543 544 # The selected models for the final run. 545 if model == None: 546 self.interpreter.value.write(param='model', file='model.out', dir=path, force=True) 547 548 # The R2eff parameter. 549 if model == 'R2eff': 550 self.interpreter.value.write(param='r2eff', file='r2eff.out', dir=path, force=True) 551 self.interpreter.grace.write(x_data_type='res_num', y_data_type='r2eff', file='r2eff.agr', dir=path, force=True) 552 553 # The I0 parameter. 554 if model == 'R2eff' and has_exponential_exp_type(): 555 self.interpreter.value.write(param='i0', file='i0.out', dir=path, force=True) 556 self.interpreter.grace.write(x_data_type='res_num', y_data_type='i0', file='i0.agr', dir=path, force=True) 557 558 # The calculation of theta and w_eff parameter in R1rho experiments. 559 if model in MODEL_LIST_R1RHO_FULL and has_r1rho_exp_type(): 560 self.interpreter.value.write(param='theta', file='theta.out', dir=path, force=True) 561 self.interpreter.value.write(param='w_eff', file='w_eff.out', dir=path, force=True) 562 563 # The R20 parameter. 564 if has_cpmg_exp_type() and model in [None, MODEL_LM63, MODEL_B14, MODEL_CR72, MODEL_IT99, MODEL_M61, MODEL_DPL94, MODEL_M61B, MODEL_MMQ_CR72, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_MMQ_2SITE, MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR]: 565 self.interpreter.value.write(param='r2', file='r20.out', dir=path, force=True) 566 self.interpreter.grace.write(x_data_type='res_num', y_data_type='r2', file='r20.agr', dir=path, force=True) 567 568 # The R20A and R20B parameters. 569 if has_cpmg_exp_type() and model in [None, MODEL_B14_FULL, MODEL_CR72_FULL, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_STAR_FULL]: 570 self.interpreter.value.write(param='r2a', file='r20a.out', dir=path, force=True) 571 self.interpreter.value.write(param='r2b', file='r20b.out', dir=path, force=True) 572 self.interpreter.grace.write(x_data_type='res_num', y_data_type='r2a', file='r20a.agr', dir=path, force=True) 573 self.interpreter.grace.write(x_data_type='res_num', y_data_type='r2b', file='r20b.agr', dir=path, force=True) 574 575 # The R1rho0 parameter. 576 if has_r1rho_exp_type() and model in [None] + MODEL_LIST_R1RHO: 577 self.interpreter.value.write(param='r2', file='r1rho0.out', dir=path, force=True) 578 self.interpreter.grace.write(x_data_type='res_num', y_data_type='r2', file='r1rho0.agr', dir=path, force=True) 579 580 # The pA, pB, and pC parameters. 581 if model in [None, MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_IT99, MODEL_M61B, MODEL_MMQ_CR72, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_MMQ_2SITE, MODEL_NS_R1RHO_2SITE, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR, MODEL_TP02, MODEL_TAP03, MODEL_MP05, MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR]: 582 self.interpreter.value.write(param='pA', file='pA.out', dir=path, force=True) 583 self.interpreter.value.write(param='pB', file='pB.out', dir=path, force=True) 584 self.interpreter.grace.write(x_data_type='res_num', y_data_type='pA', file='pA.agr', dir=path, force=True) 585 self.interpreter.grace.write(x_data_type='res_num', y_data_type='pB', file='pB.agr', dir=path, force=True) 586 if model in [MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR]: 587 self.interpreter.value.write(param='pC', file='pC.out', dir=path, force=True) 588 self.interpreter.grace.write(x_data_type='res_num', y_data_type='pC', file='pC.agr', dir=path, force=True) 589 590 # The Phi_ex parameter. 591 if model in [None, MODEL_LM63, MODEL_M61, MODEL_DPL94]: 592 self.interpreter.value.write(param='phi_ex', file='phi_ex.out', dir=path, force=True) 593 self.interpreter.grace.write(x_data_type='res_num', y_data_type='phi_ex', file='phi_ex.agr', dir=path, force=True) 594 595 # The Phi_ex_B nd Phi_ex_C parameters. 596 if model in [None, MODEL_LM63_3SITE]: 597 self.interpreter.value.write(param='phi_ex_B', file='phi_ex_B.out', dir=path, force=True) 598 self.interpreter.value.write(param='phi_ex_C', file='phi_ex_C.out', dir=path, force=True) 599 self.interpreter.grace.write(x_data_type='res_num', y_data_type='phi_ex_B', file='phi_ex_B.agr', dir=path, force=True) 600 self.interpreter.grace.write(x_data_type='res_num', y_data_type='phi_ex_C', file='phi_ex_C.agr', dir=path, force=True) 601 602 # The dw parameter. 603 if model in [None, MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_IT99, MODEL_M61B, MODEL_MMQ_CR72, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_MMQ_2SITE, MODEL_NS_R1RHO_2SITE, MODEL_TP02, MODEL_TAP03, MODEL_MP05, MODEL_TSMFK01]: 604 self.interpreter.value.write(param='dw', file='dw.out', dir=path, force=True) 605 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dw', file='dw.agr', dir=path, force=True) 606 if model in [MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR]: 607 self.interpreter.value.write(param='dw_AB', file='dw_AB.out', dir=path, force=True) 608 self.interpreter.value.write(param='dw_BC', file='dw_BC.out', dir=path, force=True) 609 self.interpreter.value.write(param='dw_AC', file='dw_AC.out', dir=path, force=True) 610 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dw_AB', file='dw_AB.agr', dir=path, force=True) 611 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dw_BC', file='dw_BC.agr', dir=path, force=True) 612 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dw_AC', file='dw_AC.agr', dir=path, force=True) 613 614 # The dwH parameter. 615 if model in [None, MODEL_MMQ_CR72, MODEL_NS_MMQ_2SITE]: 616 self.interpreter.value.write(param='dwH', file='dwH.out', dir=path, force=True) 617 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dwH', file='dwH.agr', dir=path, force=True) 618 if model in [MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR]: 619 self.interpreter.value.write(param='dwH_AB', file='dwH_AB.out', dir=path, force=True) 620 self.interpreter.value.write(param='dwH_BC', file='dwH_BC.out', dir=path, force=True) 621 self.interpreter.value.write(param='dwH_AC', file='dwH_AC.out', dir=path, force=True) 622 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dwH_AB', file='dwH_AB.agr', dir=path, force=True) 623 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dwH_BC', file='dwH_BC.agr', dir=path, force=True) 624 self.interpreter.grace.write(x_data_type='res_num', y_data_type='dwH_AC', file='dwH_AC.agr', dir=path, force=True) 625 626 # The k_AB, kex and tex parameters. 627 if model in [None, MODEL_LM63, MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_IT99, MODEL_M61, MODEL_DPL94, MODEL_M61B, MODEL_MMQ_CR72, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_MMQ_2SITE, MODEL_NS_R1RHO_2SITE, MODEL_TP02, MODEL_TAP03, MODEL_MP05]: 628 self.interpreter.value.write(param='k_AB', file='k_AB.out', dir=path, force=True) 629 self.interpreter.value.write(param='kex', file='kex.out', dir=path, force=True) 630 self.interpreter.value.write(param='tex', file='tex.out', dir=path, force=True) 631 self.interpreter.grace.write(x_data_type='res_num', y_data_type='k_AB', file='k_AB.agr', dir=path, force=True) 632 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kex', file='kex.agr', dir=path, force=True) 633 self.interpreter.grace.write(x_data_type='res_num', y_data_type='tex', file='tex.agr', dir=path, force=True) 634 if model in [MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR]: 635 self.interpreter.value.write(param='kex_AB', file='kex_AB.out', dir=path, force=True) 636 self.interpreter.value.write(param='kex_BC', file='kex_BC.out', dir=path, force=True) 637 self.interpreter.value.write(param='kex_AC', file='kex_AC.out', dir=path, force=True) 638 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kex_AB', file='kex_AB.agr', dir=path, force=True) 639 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kex_BC', file='kex_BC.agr', dir=path, force=True) 640 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kex_AC', file='kex_AC.agr', dir=path, force=True) 641 642 # The k_AB parameter. 643 if model in [None, MODEL_TSMFK01]: 644 self.interpreter.value.write(param='k_AB', file='k_AB.out', dir=path, force=True) 645 self.interpreter.grace.write(x_data_type='res_num', y_data_type='k_AB', file='k_AB.agr', dir=path, force=True) 646 647 # The kB and kC parameters. 648 if model in [None, MODEL_LM63_3SITE]: 649 self.interpreter.value.write(param='kB', file='kB.out', dir=path, force=True) 650 self.interpreter.value.write(param='kC', file='kC.out', dir=path, force=True) 651 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kB', file='kB.agr', dir=path, force=True) 652 self.interpreter.grace.write(x_data_type='res_num', y_data_type='kC', file='kC.agr', dir=path, force=True) 653 654 # Minimisation statistics. 655 if not (model == 'R2eff' and has_fixed_time_exp_type()): 656 self.interpreter.value.write(param='chi2', file='chi2.out', dir=path, force=True) 657 self.interpreter.grace.write(y_data_type='chi2', file='chi2.agr', dir=path, force=True) 658 659 # Finally save the results. This is last to allow the continuation of an interrupted analysis while ensuring that all results files have been created. 660 self.interpreter.results.write(file='results', dir=path, force=True)
661