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