Package specific_fns :: Package model_free :: Module main
[hide private]
[frames] | no frames]

Source Code for Module specific_fns.model_free.main

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2003-2012 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  # Python module imports. 
  23  from copy import deepcopy 
  24  from math import pi 
  25  from numpy import float64, array, identity, zeros 
  26  from re import match, search 
  27  from types import MethodType 
  28  from warnings import warn 
  29   
  30  # relax module imports. 
  31  import arg_check 
  32  from generic_fns import diffusion_tensor, interatomic, pipes, sequence 
  33  from generic_fns.mol_res_spin import count_spins, exists_mol_res_spin_data, find_index, return_spin, return_spin_from_index, return_spin_indices, spin_loop 
  34  import specific_fns 
  35  from relax_errors import RelaxError, RelaxFault, RelaxFuncSetupError, RelaxNoModelError, RelaxNoSequenceError, RelaxNoTensorError, RelaxTensorError 
  36  from relax_warnings import RelaxDeselectWarning 
  37  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
  38  from user_functions.objects import Desc_container 
  39   
  40   
  41   
42 -class Model_free_main:
43 """Class containing functions specific to model-free analysis.""" 44
45 - def _are_mf_params_set(self, spin):
46 """Test if the model-free parameter values are set. 47 48 @param spin: The spin container object. 49 @type spin: SpinContainer instance 50 @return: The name of the first parameter in the parameter list in which the 51 corresponding parameter value is None. If all parameters are set, then None 52 is returned. 53 @rtype: str or None 54 """ 55 56 # Deselected residue. 57 if spin.select == 0: 58 return 59 60 # Loop over the model-free parameters. 61 for j in range(len(spin.params)): 62 # Local tm. 63 if spin.params[j] == 'local_tm' and spin.local_tm == None: 64 return spin.params[j] 65 66 # S2. 67 elif spin.params[j] == 's2' and spin.s2 == None: 68 return spin.params[j] 69 70 # S2f. 71 elif spin.params[j] == 's2f' and spin.s2f == None: 72 return spin.params[j] 73 74 # S2s. 75 elif spin.params[j] == 's2s' and spin.s2s == None: 76 return spin.params[j] 77 78 # te. 79 elif spin.params[j] == 'te' and spin.te == None: 80 return spin.params[j] 81 82 # tf. 83 elif spin.params[j] == 'tf' and spin.tf == None: 84 return spin.params[j] 85 86 # ts. 87 elif spin.params[j] == 'ts' and spin.ts == None: 88 return spin.params[j] 89 90 # Rex. 91 elif spin.params[j] == 'rex' and spin.rex == None: 92 return spin.params[j] 93 94 # r. 95 elif spin.params[j] == 'r' and spin.r == None: 96 return spin.params[j] 97 98 # CSA. 99 elif spin.params[j] == 'csa' and spin.csa == None: 100 return spin.params[j]
101 102
103 - def _assemble_param_names(self, model_type, spin_id=None):
104 """Function for assembling a list of all the model parameter names. 105 106 @param model_type: The model-free model type. This must be one of 'mf', 'local_tm', 107 'diff', or 'all'. 108 @type model_type: str 109 @param spin_id: The spin identification string. 110 @type spin_id: str 111 @return: A list containing all the parameters of the model-free model. 112 @rtype: list of str 113 """ 114 115 # Initialise. 116 param_names = [] 117 118 # Diffusion tensor parameters. 119 if model_type == 'diff' or model_type == 'all': 120 # Spherical diffusion. 121 if cdp.diff_tensor.type == 'sphere': 122 param_names.append('tm') 123 124 # Spheroidal diffusion. 125 elif cdp.diff_tensor.type == 'spheroid': 126 param_names.append('tm') 127 param_names.append('Da') 128 param_names.append('theta') 129 param_names.append('phi') 130 131 # Ellipsoidal diffusion. 132 elif cdp.diff_tensor.type == 'ellipsoid': 133 param_names.append('tm') 134 param_names.append('Da') 135 param_names.append('Dr') 136 param_names.append('alpha') 137 param_names.append('beta') 138 param_names.append('gamma') 139 140 # Model-free parameters (spin specific parameters). 141 if model_type != 'diff': 142 # Loop over the spins. 143 for spin in spin_loop(spin_id): 144 # Skip deselected spins. 145 if not spin.select: 146 continue 147 148 # Add the spin specific model-free parameters. 149 param_names = param_names + spin.params 150 151 # Return the parameter names. 152 return param_names
153 154
155 - def _assemble_param_vector(self, spin=None, spin_id=None, sim_index=None, model_type=None):
156 """Assemble the model-free parameter vector (as numpy array). 157 158 If the spin argument is supplied, then the spin_id argument will be ignored. 159 160 @keyword spin: The spin data container. 161 @type spin: SpinContainer instance 162 @keyword spin_id: The spin identification string. 163 @type spin_id: str 164 @keyword sim_index: The optional MC simulation index. 165 @type sim_index: int 166 @keyword model_type: The optional model type, one of 'all', 'diff', 'mf', or 'local_tm'. 167 @type model_type: str or None 168 @return: An array of the parameter values of the model-free model. 169 @rtype: numpy array 170 """ 171 172 # Initialise. 173 param_vector = [] 174 175 # Determine the model type. 176 if not model_type: 177 model_type = self._determine_model_type() 178 179 # Diffusion tensor parameters. 180 if model_type == 'diff' or model_type == 'all': 181 # Normal parameters. 182 if sim_index == None: 183 # Spherical diffusion. 184 if cdp.diff_tensor.type == 'sphere': 185 param_vector.append(cdp.diff_tensor.tm) 186 187 # Spheroidal diffusion. 188 elif cdp.diff_tensor.type == 'spheroid': 189 param_vector.append(cdp.diff_tensor.tm) 190 param_vector.append(cdp.diff_tensor.Da) 191 param_vector.append(cdp.diff_tensor.theta) 192 param_vector.append(cdp.diff_tensor.phi) 193 194 # Ellipsoidal diffusion. 195 elif cdp.diff_tensor.type == 'ellipsoid': 196 param_vector.append(cdp.diff_tensor.tm) 197 param_vector.append(cdp.diff_tensor.Da) 198 param_vector.append(cdp.diff_tensor.Dr) 199 param_vector.append(cdp.diff_tensor.alpha) 200 param_vector.append(cdp.diff_tensor.beta) 201 param_vector.append(cdp.diff_tensor.gamma) 202 203 # Monte Carlo diffusion tensor parameters. 204 else: 205 # Spherical diffusion. 206 if cdp.diff_tensor.type == 'sphere': 207 param_vector.append(cdp.diff_tensor.tm_sim[sim_index]) 208 209 # Spheroidal diffusion. 210 elif cdp.diff_tensor.type == 'spheroid': 211 param_vector.append(cdp.diff_tensor.tm_sim[sim_index]) 212 param_vector.append(cdp.diff_tensor.Da_sim[sim_index]) 213 param_vector.append(cdp.diff_tensor.theta_sim[sim_index]) 214 param_vector.append(cdp.diff_tensor.phi_sim[sim_index]) 215 216 # Ellipsoidal diffusion. 217 elif cdp.diff_tensor.type == 'ellipsoid': 218 param_vector.append(cdp.diff_tensor.tm_sim[sim_index]) 219 param_vector.append(cdp.diff_tensor.Da_sim[sim_index]) 220 param_vector.append(cdp.diff_tensor.Dr_sim[sim_index]) 221 param_vector.append(cdp.diff_tensor.alpha_sim[sim_index]) 222 param_vector.append(cdp.diff_tensor.beta_sim[sim_index]) 223 param_vector.append(cdp.diff_tensor.gamma_sim[sim_index]) 224 225 # Model-free parameters (spin specific parameters). 226 if model_type != 'diff': 227 # The loop. 228 if spin: 229 loop = [spin] 230 else: 231 loop = spin_loop(spin_id) 232 233 # Loop over the spins. 234 for spin in loop: 235 # Skip deselected spins. 236 if not spin.select: 237 continue 238 239 # Skip spins with no parameters. 240 if not hasattr(spin, 'params'): 241 continue 242 243 # Loop over the model-free parameters. 244 for i in range(len(spin.params)): 245 # local tm. 246 if spin.params[i] == 'local_tm': 247 if sim_index == None: 248 param_vector.append(spin.local_tm) 249 else: 250 param_vector.append(spin.local_tm_sim[sim_index]) 251 252 # S2. 253 elif spin.params[i] == 's2': 254 if sim_index == None: 255 param_vector.append(spin.s2) 256 else: 257 param_vector.append(spin.s2_sim[sim_index]) 258 259 # S2f. 260 elif spin.params[i] == 's2f': 261 if sim_index == None: 262 param_vector.append(spin.s2f) 263 else: 264 param_vector.append(spin.s2f_sim[sim_index]) 265 266 # S2s. 267 elif spin.params[i] == 's2s': 268 if sim_index == None: 269 param_vector.append(spin.s2s) 270 else: 271 param_vector.append(spin.s2s_sim[sim_index]) 272 273 # te. 274 elif spin.params[i] == 'te': 275 if sim_index == None: 276 param_vector.append(spin.te) 277 else: 278 param_vector.append(spin.te_sim[sim_index]) 279 280 # tf. 281 elif spin.params[i] == 'tf': 282 if sim_index == None: 283 param_vector.append(spin.tf) 284 else: 285 param_vector.append(spin.tf_sim[sim_index]) 286 287 # ts. 288 elif spin.params[i] == 'ts': 289 if sim_index == None: 290 param_vector.append(spin.ts) 291 else: 292 param_vector.append(spin.ts_sim[sim_index]) 293 294 # Rex. 295 elif spin.params[i] == 'rex': 296 if sim_index == None: 297 param_vector.append(spin.rex) 298 else: 299 param_vector.append(spin.rex_sim[sim_index]) 300 301 # r. 302 elif spin.params[i] == 'r': 303 if sim_index == None: 304 param_vector.append(spin.r) 305 else: 306 param_vector.append(spin.r_sim[sim_index]) 307 308 # CSA. 309 elif spin.params[i] == 'csa': 310 if sim_index == None: 311 param_vector.append(spin.csa) 312 else: 313 param_vector.append(spin.csa_sim[sim_index]) 314 315 # Unknown parameter. 316 else: 317 raise RelaxError("Unknown parameter.") 318 319 # Replace all instances of None with 0.0 to allow the list to be converted to a numpy array. 320 for i in range(len(param_vector)): 321 if param_vector[i] == None: 322 param_vector[i] = 0.0 323 324 # Return a numpy array. 325 return array(param_vector, float64)
326 327
328 - def _assemble_scaling_matrix(self, num_params, model_type=None, spin=None, spin_id=None, scaling=True):
329 """Create and return the scaling matrix. 330 331 If the spin argument is supplied, then the spin_id argument will be ignored. 332 333 @param num_params: The number of parameters in the model. 334 @type num_params: int 335 @keyword model_type: The model type, one of 'all', 'diff', 'mf', or 'local_tm'. 336 @type model_type: str 337 @keyword spin: The spin data container. 338 @type spin: SpinContainer instance 339 @keyword spin_id: The spin identification string. 340 @type spin_id: str 341 @return: The diagonal and square scaling matrix. 342 @rtype: numpy diagonal matrix 343 """ 344 345 # Initialise. 346 if num_params == 0: 347 scaling_matrix = zeros((0, 0), float64) 348 else: 349 scaling_matrix = identity(num_params, float64) 350 i = 0 351 352 # No diagonal scaling, so return the identity matrix. 353 if not scaling: 354 return scaling_matrix 355 356 # tm, te, tf, and ts (must all be the same for diagonal scaling!). 357 ti_scaling = 1e-12 358 359 # Diffusion tensor parameters. 360 if model_type == 'diff' or model_type == 'all': 361 # Spherical diffusion. 362 if cdp.diff_tensor.type == 'sphere': 363 # tm. 364 scaling_matrix[i, i] = ti_scaling 365 366 # Increment i. 367 i = i + 1 368 369 # Spheroidal diffusion. 370 elif cdp.diff_tensor.type == 'spheroid': 371 # tm, Da, theta, phi 372 scaling_matrix[i, i] = ti_scaling 373 scaling_matrix[i+1, i+1] = 1e7 374 scaling_matrix[i+2, i+2] = 1.0 375 scaling_matrix[i+3, i+3] = 1.0 376 377 # Increment i. 378 i = i + 4 379 380 # Ellipsoidal diffusion. 381 elif cdp.diff_tensor.type == 'ellipsoid': 382 # tm, Da, Dr, alpha, beta, gamma. 383 scaling_matrix[i, i] = ti_scaling 384 scaling_matrix[i+1, i+1] = 1e7 385 scaling_matrix[i+2, i+2] = 1.0 386 scaling_matrix[i+3, i+3] = 1.0 387 scaling_matrix[i+4, i+4] = 1.0 388 scaling_matrix[i+5, i+5] = 1.0 389 390 # Increment i. 391 i = i + 6 392 393 # Model-free parameters. 394 if model_type != 'diff': 395 # The loop. 396 if spin: 397 loop = [spin] 398 else: 399 loop = spin_loop(spin_id) 400 401 # Loop over the spins. 402 for spin in loop: 403 # Skip deselected spins. 404 if not spin.select: 405 continue 406 407 # Loop over the model-free parameters. 408 for k in range(len(spin.params)): 409 # Local tm, te, tf, and ts (must all be the same for diagonal scaling!). 410 if spin.params[k] == 'local_tm' or search('^t', spin.params[k]): 411 scaling_matrix[i, i] = ti_scaling 412 413 # Rex. 414 elif spin.params[k] == 'rex': 415 scaling_matrix[i, i] = 1.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]]) ** 2 416 417 # Interatomic distances. 418 elif spin.params[k] == 'r': 419 scaling_matrix[i, i] = 1e-10 420 421 # CSA. 422 elif spin.params[k] == 'csa': 423 scaling_matrix[i, i] = 1e-4 424 425 # Increment i. 426 i = i + 1 427 428 # Return the scaling matrix. 429 return scaling_matrix
430 431
432 - def back_calc_ri(self, spin_index=None, ri_id=None, ri_type=None, frq=None):
433 """Back-calculation of relaxation data from the model-free parameter values. 434 435 @keyword spin_index: The global spin index. 436 @type spin_index: int 437 @keyword ri_id: The relaxation data ID string. 438 @type ri_id: str 439 @keyword ri_type: The relaxation data type. 440 @type ri_type: str 441 @keyword frq: The field strength. 442 @type frq: float 443 @return: The back calculated relaxation data value corresponding to the index. 444 @rtype: float 445 """ 446 447 # Get the spin container. 448 spin, spin_id = return_spin_from_index(global_index=spin_index, return_spin_id=True) 449 450 # Missing interatomic vectors. 451 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'): 452 interatoms = interatomic.return_interatom_list(spin_id) 453 for i in range(len(interatoms)): 454 # No dipolar relaxation mechanism. 455 if not interatoms[i].dipole_pair: 456 continue 457 458 # Check the unit vectors. 459 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector == None: 460 warn(RelaxDeselectWarning(spin_id, 'missing structural data')) 461 return 462 463 # Execute the over-fit deselection. 464 self.overfit_deselect(data_check=False, verbose=False) 465 466 # Get the relaxation value from the minimise function. 467 value = self.minimise(min_algor='back_calc', min_options=(spin_index, ri_id, ri_type, frq)) 468 469 # Return the relaxation value. 470 return value
471 472
473 - def _compare_objects(self, object_from, object_to, pipe_from, pipe_to):
474 """Compare the contents of the two objects and raise RelaxErrors if they are not the same. 475 476 @param object_from: The first object. 477 @type object_from: any object 478 @param object_to: The second object. 479 @type object_to: any object 480 @param pipe_from: The name of the data pipe containing the first object. 481 @type pipe_from: str 482 @param pipe_to: The name of the data pipe containing the second object. 483 @type pipe_to: str 484 """ 485 486 # Loop over the modifiable objects. 487 for data_name in dir(object_from): 488 # Skip special objects (starting with _, or in the original class and base class namespaces). 489 if search('^_', data_name) or data_name in list(object_from.__class__.__dict__.keys()) or (hasattr(object_from.__class__, '__bases__') and len(object_from.__class__.__bases__) and data_name in list(object_from.__class__.__bases__[0].__dict__.keys())): 490 continue 491 492 # Skip some more special objects. 493 if data_name in ['structural_data']: 494 continue 495 496 # Get the original object. 497 data_from = None 498 if hasattr(object_from, data_name): 499 data_from = getattr(object_from, data_name) 500 501 # Get the target object. 502 if data_from and not hasattr(object_to, data_name): 503 raise RelaxError("The structural object " + repr(data_name) + " of the " + repr(pipe_from) + " data pipe is not located in the " + repr(pipe_to) + " data pipe.") 504 elif data_from: 505 data_to = getattr(object_to, data_name) 506 else: 507 continue 508 509 # The data must match! 510 if data_from != data_to: 511 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".")
512 513
514 - def _conv_factor_rex(self):
515 """Calculate and return the Rex conversion factor. 516 517 @return: The Rex conversion factor. 518 @rtype: float 519 """ 520 521 # The factor. 522 return 1.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2
523 524
525 - def _create_model(self, model=None, equation=None, params=None, spin_id=None):
526 """Function for creating a custom model-free model. 527 528 @param model: The name of the model. 529 @type model: str 530 @param equation: The equation type to use. The 3 allowed types are: 'mf_orig' for the original model-free equations with parameters {s2, te}; 'mf_ext' for the extended model-free equations with parameters {s2f, tf, s2, ts}; and 'mf_ext2' for the extended model-free equations with parameters {s2f, tf, s2s, ts}. 531 @type equation: str 532 @param params: A list of the parameters to include in the model. The allowed parameter names includes those for the equation type as well as chemical exchange 'rex', the bond length 'r', and the chemical shift anisotropy 'csa'. 533 @type params: list of str 534 @param spin_id: The spin identification string. 535 @type spin_id: str 536 """ 537 538 # Test if the current data pipe exists. 539 pipes.test() 540 541 # Test if the pipe type is 'mf'. 542 function_type = pipes.get_type() 543 if function_type != 'mf': 544 raise RelaxFuncSetupError(specific_fns.get_string(function_type)) 545 546 # Test if sequence data is loaded. 547 if not exists_mol_res_spin_data(): 548 raise RelaxNoSequenceError 549 550 # Check the validity of the model-free equation type. 551 valid_types = ['mf_orig', 'mf_ext', 'mf_ext2'] 552 if not equation in valid_types: 553 raise RelaxError("The model-free equation type argument " + repr(equation) + " is invalid and should be one of " + repr(valid_types) + ".") 554 555 # Check the validity of the parameter array. 556 s2, te, s2f, tf, s2s, ts, rex, csa, r = 0, 0, 0, 0, 0, 0, 0, 0, 0 557 for i in range(len(params)): 558 # Invalid parameter flag. 559 invalid_param = 0 560 561 # S2. 562 if params[i] == 's2': 563 # Does the array contain more than one instance of S2. 564 if s2: 565 invalid_param = 1 566 s2 = 1 567 568 # Does the array contain S2s. 569 s2s_flag = 0 570 for j in range(len(params)): 571 if params[j] == 's2s': 572 s2s_flag = 1 573 if s2s_flag: 574 invalid_param = 1 575 576 # te. 577 elif params[i] == 'te': 578 # Does the array contain more than one instance of te and has the extended model-free formula been selected. 579 if equation == 'mf_ext' or te: 580 invalid_param = 1 581 te = 1 582 583 # Does the array contain the parameter S2. 584 s2_flag = 0 585 for j in range(len(params)): 586 if params[j] == 's2': 587 s2_flag = 1 588 if not s2_flag: 589 invalid_param = 1 590 591 # S2f. 592 elif params[i] == 's2f': 593 # Does the array contain more than one instance of S2f and has the original model-free formula been selected. 594 if equation == 'mf_orig' or s2f: 595 invalid_param = 1 596 s2f = 1 597 598 # S2s. 599 elif params[i] == 's2s': 600 # Does the array contain more than one instance of S2s and has the original model-free formula been selected. 601 if equation == 'mf_orig' or s2s: 602 invalid_param = 1 603 s2s = 1 604 605 # tf. 606 elif params[i] == 'tf': 607 # Does the array contain more than one instance of tf and has the original model-free formula been selected. 608 if equation == 'mf_orig' or tf: 609 invalid_param = 1 610 tf = 1 611 612 # Does the array contain the parameter S2f. 613 s2f_flag = 0 614 for j in range(len(params)): 615 if params[j] == 's2f': 616 s2f_flag = 1 617 if not s2f_flag: 618 invalid_param = 1 619 620 # ts. 621 elif params[i] == 'ts': 622 # Does the array contain more than one instance of ts and has the original model-free formula been selected. 623 if equation == 'mf_orig' or ts: 624 invalid_param = 1 625 ts = 1 626 627 # Does the array contain the parameter S2 or S2s. 628 flag = 0 629 for j in range(len(params)): 630 if params[j] == 's2' or params[j] == 's2f': 631 flag = 1 632 if not flag: 633 invalid_param = 1 634 635 # Rex. 636 elif params[i] == 'rex': 637 if rex: 638 invalid_param = 1 639 rex = 1 640 641 # Interatomic distances. 642 elif params[i] == 'r': 643 if r: 644 invalid_param = 1 645 r = 1 646 647 # CSA. 648 elif params[i] == 'csa': 649 if csa: 650 invalid_param = 1 651 csa = 1 652 653 # Unknown parameter. 654 else: 655 raise RelaxError("The parameter " + params[i] + " is not supported.") 656 657 # The invalid parameter flag is set. 658 if invalid_param: 659 raise RelaxError("The parameter array " + repr(params) + " contains an invalid combination of parameters.") 660 661 # Set up the model. 662 self._model_setup(model, equation, params, spin_id)
663 664
665 - def _delete(self):
666 """Delete all the model-free data.""" 667 668 # Test if the current pipe exists. 669 pipes.test() 670 671 # Test if the pipe type is set to 'mf'. 672 function_type = pipes.get_type() 673 if function_type != 'mf': 674 raise RelaxFuncSetupError(specific_fns.setup.get_string(function_type)) 675 676 # Test if the sequence data is loaded. 677 if not exists_mol_res_spin_data(): 678 raise RelaxNoSequenceError 679 680 # Get all data structure names. 681 names = self.data_names(scope='spin') 682 683 # Loop over the spins. 684 for spin in spin_loop(): 685 # Loop through the data structure names. 686 for name in names: 687 # Skip the data structure if it does not exist. 688 if not hasattr(spin, name): 689 continue 690 691 # Delete the data. 692 delattr(spin, name)
693 694
695 - def _determine_model_type(self):
696 """Determine the global model type. 697 698 @return: The name of the model type, which will be one of 'all', 'diff', 'mf', or 'local_tm'. If all parameters are fixed (and no spins selected), None is returned. 699 @rtype: str or None 700 """ 701 702 # Test if sequence data is loaded. 703 if not exists_mol_res_spin_data(): 704 raise RelaxNoSequenceError 705 706 # If there is a local tm, fail if not all residues have a local tm parameter. 707 local_tm = False 708 for spin in spin_loop(): 709 # Skip deselected spins. 710 if not spin.select: 711 continue 712 713 # No params. 714 if not hasattr(spin, 'params') or not spin.params: 715 continue 716 717 # Local tm. 718 if not local_tm and 'local_tm' in spin.params: 719 local_tm = True 720 721 # Inconsistencies. 722 elif local_tm and not 'local_tm' in spin.params: 723 raise RelaxError("All spins must either have a local tm parameter or not.") 724 725 # Check if any model-free parameters are allowed to vary. 726 mf_all_fixed = True 727 mf_all_deselected = True 728 for spin in spin_loop(): 729 # Skip deselected spins. 730 if not spin.select: 731 continue 732 733 # At least one spin is selected. 734 mf_all_deselected = False 735 736 # Test the fixed flag. 737 if not hasattr(spin, 'fixed'): 738 mf_all_fixed = False 739 break 740 if not spin.fixed: 741 mf_all_fixed = False 742 break 743 744 # No spins selected?!? 745 if mf_all_deselected: 746 # All parameters fixed! 747 if not hasattr(cdp, 'diff_tensor') or cdp.diff_tensor.fixed: 748 return None 749 750 return 'diff' 751 752 # Local tm. 753 if local_tm: 754 return 'local_tm' 755 756 # Test if the diffusion tensor data is loaded. 757 if not diffusion_tensor.diff_data_exists(): 758 # Catch when the local tm value is set but not in the parameter list. 759 for spin in spin_loop(): 760 if hasattr(spin, 'local_tm') and spin.local_tm != None and not 'local_tm' in spin.params: 761 raise RelaxError("The local tm value is set but not located in the model parameter list.") 762 763 # Normal error. 764 raise RelaxNoTensorError('diffusion') 765 766 # 'diff' model type. 767 if mf_all_fixed: 768 # All parameters fixed! 769 if cdp.diff_tensor.fixed: 770 return None 771 772 return 'diff' 773 774 # 'mf' model type. 775 if cdp.diff_tensor.fixed: 776 return 'mf' 777 778 # 'all' model type. 779 else: 780 return 'all'
781 782
783 - def _model_map(self, model):
784 """Return the equation name and parameter list corresponding to the given model. 785 786 @param model: The model-free model. 787 @type model: str 788 @return: The equation type (either 'mf_orig' or 'mf_ext') and the model-free parameter list corresponding to the model. 789 @rtype: str, list 790 """ 791 792 # Block 1. 793 if model == 'm0': 794 equation = 'mf_orig' 795 params = [] 796 elif model == 'm1': 797 equation = 'mf_orig' 798 params = ['s2'] 799 elif model == 'm2': 800 equation = 'mf_orig' 801 params = ['s2', 'te'] 802 elif model == 'm3': 803 equation = 'mf_orig' 804 params = ['s2', 'rex'] 805 elif model == 'm4': 806 equation = 'mf_orig' 807 params = ['s2', 'te', 'rex'] 808 elif model == 'm5': 809 equation = 'mf_ext' 810 params = ['s2f', 's2', 'ts'] 811 elif model == 'm6': 812 equation = 'mf_ext' 813 params = ['s2f', 'tf', 's2', 'ts'] 814 elif model == 'm7': 815 equation = 'mf_ext' 816 params = ['s2f', 's2', 'ts', 'rex'] 817 elif model == 'm8': 818 equation = 'mf_ext' 819 params = ['s2f', 'tf', 's2', 'ts', 'rex'] 820 elif model == 'm9': 821 equation = 'mf_orig' 822 params = ['rex'] 823 824 # Block 2. 825 elif model == 'm10': 826 equation = 'mf_orig' 827 params = ['csa'] 828 elif model == 'm11': 829 equation = 'mf_orig' 830 params = ['csa', 's2'] 831 elif model == 'm12': 832 equation = 'mf_orig' 833 params = ['csa', 's2', 'te'] 834 elif model == 'm13': 835 equation = 'mf_orig' 836 params = ['csa', 's2', 'rex'] 837 elif model == 'm14': 838 equation = 'mf_orig' 839 params = ['csa', 's2', 'te', 'rex'] 840 elif model == 'm15': 841 equation = 'mf_ext' 842 params = ['csa', 's2f', 's2', 'ts'] 843 elif model == 'm16': 844 equation = 'mf_ext' 845 params = ['csa', 's2f', 'tf', 's2', 'ts'] 846 elif model == 'm17': 847 equation = 'mf_ext' 848 params = ['csa', 's2f', 's2', 'ts', 'rex'] 849 elif model == 'm18': 850 equation = 'mf_ext' 851 params = ['csa', 's2f', 'tf', 's2', 'ts', 'rex'] 852 elif model == 'm19': 853 equation = 'mf_orig' 854 params = ['csa', 'rex'] 855 856 # Block 3. 857 elif model == 'm20': 858 equation = 'mf_orig' 859 params = ['r'] 860 elif model == 'm21': 861 equation = 'mf_orig' 862 params = ['r', 's2'] 863 elif model == 'm22': 864 equation = 'mf_orig' 865 params = ['r', 's2', 'te'] 866 elif model == 'm23': 867 equation = 'mf_orig' 868 params = ['r', 's2', 'rex'] 869 elif model == 'm24': 870 equation = 'mf_orig' 871 params = ['r', 's2', 'te', 'rex'] 872 elif model == 'm25': 873 equation = 'mf_ext' 874 params = ['r', 's2f', 's2', 'ts'] 875 elif model == 'm26': 876 equation = 'mf_ext' 877 params = ['r', 's2f', 'tf', 's2', 'ts'] 878 elif model == 'm27': 879 equation = 'mf_ext' 880 params = ['r', 's2f', 's2', 'ts', 'rex'] 881 elif model == 'm28': 882 equation = 'mf_ext' 883 params = ['r', 's2f', 'tf', 's2', 'ts', 'rex'] 884 elif model == 'm29': 885 equation = 'mf_orig' 886 params = ['r', 'rex'] 887 888 # Block 4. 889 elif model == 'm30': 890 equation = 'mf_orig' 891 params = ['r', 'csa'] 892 elif model == 'm31': 893 equation = 'mf_orig' 894 params = ['r', 'csa', 's2'] 895 elif model == 'm32': 896 equation = 'mf_orig' 897 params = ['r', 'csa', 's2', 'te'] 898 elif model == 'm33': 899 equation = 'mf_orig' 900 params = ['r', 'csa', 's2', 'rex'] 901 elif model == 'm34': 902 equation = 'mf_orig' 903 params = ['r', 'csa', 's2', 'te', 'rex'] 904 elif model == 'm35': 905 equation = 'mf_ext' 906 params = ['r', 'csa', 's2f', 's2', 'ts'] 907 elif model == 'm36': 908 equation = 'mf_ext' 909 params = ['r', 'csa', 's2f', 'tf', 's2', 'ts'] 910 elif model == 'm37': 911 equation = 'mf_ext' 912 params = ['r', 'csa', 's2f', 's2', 'ts', 'rex'] 913 elif model == 'm38': 914 equation = 'mf_ext' 915 params = ['r', 'csa', 's2f', 'tf', 's2', 'ts', 'rex'] 916 elif model == 'm39': 917 equation = 'mf_orig' 918 params = ['r', 'csa', 'rex'] 919 920 921 # Preset models with local correlation time. 922 ############################################ 923 924 # Block 1. 925 elif model == 'tm0': 926 equation = 'mf_orig' 927 params = ['local_tm'] 928 elif model == 'tm1': 929 equation = 'mf_orig' 930 params = ['local_tm', 's2'] 931 elif model == 'tm2': 932 equation = 'mf_orig' 933 params = ['local_tm', 's2', 'te'] 934 elif model == 'tm3': 935 equation = 'mf_orig' 936 params = ['local_tm', 's2', 'rex'] 937 elif model == 'tm4': 938 equation = 'mf_orig' 939 params = ['local_tm', 's2', 'te', 'rex'] 940 elif model == 'tm5': 941 equation = 'mf_ext' 942 params = ['local_tm', 's2f', 's2', 'ts'] 943 elif model == 'tm6': 944 equation = 'mf_ext' 945 params = ['local_tm', 's2f', 'tf', 's2', 'ts'] 946 elif model == 'tm7': 947 equation = 'mf_ext' 948 params = ['local_tm', 's2f', 's2', 'ts', 'rex'] 949 elif model == 'tm8': 950 equation = 'mf_ext' 951 params = ['local_tm', 's2f', 'tf', 's2', 'ts', 'rex'] 952 elif model == 'tm9': 953 equation = 'mf_orig' 954 params = ['local_tm', 'rex'] 955 956 # Block 2. 957 elif model == 'tm10': 958 equation = 'mf_orig' 959 params = ['local_tm', 'csa'] 960 elif model == 'tm11': 961 equation = 'mf_orig' 962 params = ['local_tm', 'csa', 's2'] 963 elif model == 'tm12': 964 equation = 'mf_orig' 965 params = ['local_tm', 'csa', 's2', 'te'] 966 elif model == 'tm13': 967 equation = 'mf_orig' 968 params = ['local_tm', 'csa', 's2', 'rex'] 969 elif model == 'tm14': 970 equation = 'mf_orig' 971 params = ['local_tm', 'csa', 's2', 'te', 'rex'] 972 elif model == 'tm15': 973 equation = 'mf_ext' 974 params = ['local_tm', 'csa', 's2f', 's2', 'ts'] 975 elif model == 'tm16': 976 equation = 'mf_ext' 977 params = ['local_tm', 'csa', 's2f', 'tf', 's2', 'ts'] 978 elif model == 'tm17': 979 equation = 'mf_ext' 980 params = ['local_tm', 'csa', 's2f', 's2', 'ts', 'rex'] 981 elif model == 'tm18': 982 equation = 'mf_ext' 983 params = ['local_tm', 'csa', 's2f', 'tf', 's2', 'ts', 'rex'] 984 elif model == 'tm19': 985 equation = 'mf_orig' 986 params = ['local_tm', 'csa', 'rex'] 987 988 # Block 3. 989 elif model == 'tm20': 990 equation = 'mf_orig' 991 params = ['local_tm', 'r'] 992 elif model == 'tm21': 993 equation = 'mf_orig' 994 params = ['local_tm', 'r', 's2'] 995 elif model == 'tm22': 996 equation = 'mf_orig' 997 params = ['local_tm', 'r', 's2', 'te'] 998 elif model == 'tm23': 999 equation = 'mf_orig' 1000 params = ['local_tm', 'r', 's2', 'rex'] 1001 elif model == 'tm24': 1002 equation = 'mf_orig' 1003 params = ['local_tm', 'r', 's2', 'te', 'rex'] 1004 elif model == 'tm25': 1005 equation = 'mf_ext' 1006 params = ['local_tm', 'r', 's2f', 's2', 'ts'] 1007 elif model == 'tm26': 1008 equation = 'mf_ext' 1009 params = ['local_tm', 'r', 's2f', 'tf', 's2', 'ts'] 1010 elif model == 'tm27': 1011 equation = 'mf_ext' 1012 params = ['local_tm', 'r', 's2f', 's2', 'ts', 'rex'] 1013 elif model == 'tm28': 1014 equation = 'mf_ext' 1015 params = ['local_tm', 'r', 's2f', 'tf', 's2', 'ts', 'rex'] 1016 elif model == 'tm29': 1017 equation = 'mf_orig' 1018 params = ['local_tm', 'r', 'rex'] 1019 1020 # Block 4. 1021 elif model == 'tm30': 1022 equation = 'mf_orig' 1023 params = ['local_tm', 'r', 'csa'] 1024 elif model == 'tm31': 1025 equation = 'mf_orig' 1026 params = ['local_tm', 'r', 'csa', 's2'] 1027 elif model == 'tm32': 1028 equation = 'mf_orig' 1029 params = ['local_tm', 'r', 'csa', 's2', 'te'] 1030 elif model == 'tm33': 1031 equation = 'mf_orig' 1032 params = ['local_tm', 'r', 'csa', 's2', 'rex'] 1033 elif model == 'tm34': 1034 equation = 'mf_orig' 1035 params = ['local_tm', 'r', 'csa', 's2', 'te', 'rex'] 1036 elif model == 'tm35': 1037 equation = 'mf_ext' 1038 params = ['local_tm', 'r', 'csa', 's2f', 's2', 'ts'] 1039 elif model == 'tm36': 1040 equation = 'mf_ext' 1041 params = ['local_tm', 'r', 'csa', 's2f', 'tf', 's2', 'ts'] 1042 elif model == 'tm37': 1043 equation = 'mf_ext' 1044 params = ['local_tm', 'r', 'csa', 's2f', 's2', 'ts', 'rex'] 1045 elif model == 'tm38': 1046 equation = 'mf_ext' 1047 params = ['local_tm', 'r', 'csa', 's2f', 'tf', 's2', 'ts', 'rex'] 1048 elif model == 'tm39': 1049 equation = 'mf_orig' 1050 params = ['local_tm', 'r', 'csa', 'rex'] 1051 1052 # Invalid model. 1053 else: 1054 raise RelaxError("The model '%s' is invalid." % model) 1055 1056 # Return the values. 1057 return equation, params
1058 1059
1060 - def _model_setup(self, model=None, equation=None, params=None, spin_id=None):
1061 """Function for updating various data structures depending on the model selected. 1062 1063 @param model: The name of the model. 1064 @type model: str 1065 @param equation: The equation type to use. The 3 allowed types are: 'mf_orig' for the original model-free equations with parameters {s2, te}; 'mf_ext' for the extended model-free equations with parameters {s2f, tf, s2, ts}; and 'mf_ext2' for the extended model-free equations with parameters {s2f, tf, s2s, ts}. 1066 @type equation: str 1067 @param params: A list of the parameters to include in the model. The allowed parameter names includes those for the equation type as well as chemical exchange 'rex', the bond length 'r', and the chemical shift anisotropy 'csa'. 1068 @type params: list of str 1069 @param spin_id: The spin identification string. 1070 @type spin_id: str 1071 """ 1072 1073 # Test that no diffusion tensor exists if local tm is a parameter in the model. 1074 if params: 1075 for param in params: 1076 if param == 'local_tm' and hasattr(pipes.get_pipe(), 'diff_tensor'): 1077 raise RelaxTensorError('diffusion') 1078 1079 # Loop over the sequence. 1080 for spin in spin_loop(spin_id): 1081 # Initialise the data structures (if needed). 1082 self.data_init(spin) 1083 1084 # Model-free model, equation, and parameter types. 1085 spin.model = model 1086 spin.equation = equation 1087 spin.params = params
1088 1089
1090 - def _remove_tm(self, spin_id=None):
1091 """Remove local tm from the set of model-free parameters for the given spins. 1092 1093 @param spin_id: The spin identification string. 1094 @type spin_id: str or None 1095 """ 1096 1097 # Test if the current data pipe exists. 1098 pipes.test() 1099 1100 # Test if the pipe type is 'mf'. 1101 function_type = pipes.get_type() 1102 if function_type != 'mf': 1103 raise RelaxFuncSetupError(specific_fns.get_string(function_type)) 1104 1105 # Test if sequence data is loaded. 1106 if not exists_mol_res_spin_data(): 1107 raise RelaxNoSequenceError 1108 1109 # Loop over the spins. 1110 for spin in spin_loop(spin_id): 1111 # Skip deselected spins. 1112 if not spin.select: 1113 continue 1114 1115 # Test if a local tm parameter exists. 1116 if not hasattr(spin, 'params') or not 'local_tm' in spin.params: 1117 continue 1118 1119 # Remove tm. 1120 spin.params.remove('local_tm') 1121 1122 # Model name. 1123 if match('^tm', spin.model): 1124 spin.model = spin.model[1:] 1125 1126 # Delete the local tm variable. 1127 del spin.local_tm 1128 1129 # Set all the minimisation stats to None. 1130 spin.chi2 = None 1131 spin.iter = None 1132 spin.f_count = None 1133 spin.g_count = None 1134 spin.h_count = None 1135 spin.warning = None 1136 1137 # Set the global minimisation stats to None. 1138 cdp.chi2 = None 1139 cdp.iter = None 1140 cdp.f_count = None 1141 cdp.g_count = None 1142 cdp.h_count = None 1143 cdp.warning = None
1144 1145
1146 - def _select_model(self, model=None, spin_id=None):
1147 """Function for the selection of a preset model-free model. 1148 1149 @param model: The name of the model. 1150 @type model: str 1151 @param spin_id: The spin identification string. 1152 @type spin_id: str 1153 """ 1154 1155 # Test if the current data pipe exists. 1156 pipes.test() 1157 1158 # Test if the pipe type is 'mf'. 1159 function_type = pipes.get_type() 1160 if function_type != 'mf': 1161 raise RelaxFuncSetupError(specific_fns.get_string(function_type)) 1162 1163 # Test if sequence data is loaded. 1164 if not exists_mol_res_spin_data(): 1165 raise RelaxNoSequenceError 1166 1167 # Obtain the model info. 1168 equation, params = self._model_map(model) 1169 1170 # Set up the model. 1171 self._model_setup(model, equation, params, spin_id)
1172 1173
1174 - def _units_rex(self):
1175 """Return the units for the Rex parameter. 1176 1177 @return: The field strength dependent Rex units. 1178 @rtype: str 1179 """ 1180 1181 # No frequency info. 1182 if not hasattr(cdp, 'frq_labels') or len(cdp.frq_labels) == 0: 1183 return '' 1184 1185 # The units. 1186 return cdp.frq_labels[0] + ' MHz'
1187 1188
1189 - def create_mc_data(self, data_id=None):
1190 """Create the Monte Carlo Ri data. 1191 1192 @keyword data_id: The spin identification string, as yielded by the base_data_loop() generator method. 1193 @type data_id: str 1194 @return: The Monte Carlo simulation data. 1195 @rtype: list of floats 1196 """ 1197 1198 # Initialise the MC data structure. 1199 mc_data = [] 1200 1201 # Get the spin container and global spin index. 1202 spin = return_spin(data_id) 1203 global_index = find_index(data_id) 1204 1205 # Skip deselected spins. 1206 if not spin.select: 1207 return 1208 1209 # Test if the model is set. 1210 if not hasattr(spin, 'model') or not spin.model: 1211 raise RelaxNoModelError 1212 1213 # Loop over the relaxation data. 1214 for ri_id in cdp.ri_ids: 1215 # Back calculate the value. 1216 value = self.back_calc_ri(spin_index=global_index, ri_id=ri_id, ri_type=cdp.ri_type[ri_id], frq=cdp.frq[ri_id]) 1217 1218 # Append the value. 1219 mc_data.append(value) 1220 1221 # Return the data. 1222 return mc_data
1223 1224
1225 - def data_init(self, data_cont, sim=False):
1226 """Initialise the spin specific data structures. 1227 1228 @param data_cont: The spin data container. 1229 @type data_cont: SpinContainer instance 1230 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure. 1231 @type sim: bool 1232 """ 1233 1234 # Loop over the data structure names. 1235 for name in self.PARAMS.loop(scope='spin'): 1236 # Blacklisted data structures. 1237 if name in ['ri_data', 'ri_data_bc', 'ri_data_err']: 1238 continue 1239 1240 # Data structures which are initially empty arrays. 1241 list_data = [ 'params' ] 1242 if name in list_data: 1243 init_data = [] 1244 1245 # Set everything else initially to None or False. 1246 init_data = None 1247 if self.PARAMS.get_type(name) == bool: 1248 init_data = False 1249 if name == 'select': 1250 init_data = True 1251 1252 # If the name is not in 'data_cont', add it. 1253 if not hasattr(data_cont, name): 1254 setattr(data_cont, name, init_data)
1255 1256
1257 - def data_type(self, param=None):
1258 """Return the type of data, as a string, that the parameter should be. 1259 1260 @keyword param: The parameter name. 1261 @type param: list of str 1262 @return: The type of the parameter, as a string. I.e. 'int', 'float', 'str', 'bool', 'list of str', 'dict of bool', etc. 1263 @rtype: str 1264 """ 1265 1266 # A dictionary of all the types. 1267 types = { 1268 'select': bool, 1269 'fixed': bool, 1270 'nucleus': str, 1271 'model': str, 1272 'equation': str, 1273 'params': [str], 1274 's2': float, 1275 's2f': float, 1276 's2s': float, 1277 'local_tm': float, 1278 'te': float, 1279 'tf': float, 1280 'ts': float, 1281 'rex': float, 1282 'csa': float, 1283 'chi2': float, 1284 'iter': int, 1285 'f_count': int, 1286 'g_count': int, 1287 'h_count': int, 1288 'warning': str 1289 } 1290 1291 # Return the type, if in the list. 1292 if param in types: 1293 return types[param]
1294 1295 1296 default_value_doc = Desc_container("Model-free default values") 1297 _table = uf_tables.add_table(label="table: mf default values", caption="Model-free default values.") 1298 _table.add_headings(["Data type", "Object name", "Value"]) 1299 _table.add_row(["Local tm", "'local_tm'", "10 * 1e-9"]) 1300 _table.add_row(["Order parameters S2, S2f, and S2s", "'s2', 's2f', 's2s'", "0.8"]) 1301 _table.add_row(["Correlation time te", "'te'", "100 * 1e-12"]) 1302 _table.add_row(["Correlation time tf", "'tf'", "10 * 1e-12"]) 1303 _table.add_row(["Correlation time ts", "'ts'", "1000 * 1e-12"]) 1304 _table.add_row(["Chemical exchange relaxation", "'rex'", "0.0"]) 1305 _table.add_row(["CSA", "'csa'", "-172 * 1e-6"]) 1306 default_value_doc.add_table(_table.label) 1307
1308 - def default_value(self, param):
1309 """The default model-free parameter values. 1310 1311 @param param: The model-free parameter. 1312 @type param: str 1313 @return: The default value. 1314 @rtype: float 1315 """ 1316 1317 # Diffusion tensor parameter. 1318 diff_val = diffusion_tensor.default_value(param) 1319 if diff_val != None: 1320 return diff_val 1321 1322 # Model-free parameter. 1323 return self.PARAMS.get_default(param)
1324 1325
1326 - def deselect(self, model_info, sim_index=None):
1327 """Deselect models or simulations. 1328 1329 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1330 @type model_info: int 1331 @keyword sim_index: The optional Monte Carlo simulation index. If None, then models will be deselected, otherwise the given simulation will. 1332 @type sim_index: None or int 1333 """ 1334 1335 # Determine the model type. 1336 model_type = self._determine_model_type() 1337 1338 # Local models. 1339 if model_type == 'mf' or model_type == 'local_tm': 1340 # Get the spin. 1341 spin = return_spin_from_index(model_info) 1342 1343 # Spin deselection. 1344 if sim_index == None: 1345 spin.select = False 1346 1347 # Simulation deselection. 1348 else: 1349 spin.select_sim[sim_index] = False 1350 1351 # Global models. 1352 else: 1353 # Global model deselection. 1354 if sim_index == None: 1355 raise RelaxError("Cannot deselect the global model.") 1356 1357 # Simulation deselection. 1358 else: 1359 # Deselect. 1360 cdp.select_sim[sim_index] = False
1361 1362
1363 - def duplicate_data(self, pipe_from=None, pipe_to=None, model_info=None, global_stats=False, verbose=True):
1364 """Duplicate the data specific to a single model-free model. 1365 1366 @keyword pipe_from: The data pipe to copy the data from. 1367 @type pipe_from: str 1368 @keyword pipe_to: The data pipe to copy the data to. 1369 @type pipe_to: str 1370 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1371 @type model_info: int 1372 @keyword global_stats: The global statistics flag. 1373 @type global_stats: bool 1374 @keyword verbose: A flag which if True will cause info about each spin to be printed out as the sequence is generated. 1375 @type verbose: bool 1376 """ 1377 1378 # Arg tests. 1379 if model_info == None: 1380 raise RelaxError("The model_info argument cannot be None.") 1381 1382 # First create the pipe_to data pipe, if it doesn't exist, but don't switch to it. 1383 if not pipes.has_pipe(pipe_to): 1384 pipes.create(pipe_to, pipe_type='mf', switch=False) 1385 1386 # Get the data pipes. 1387 dp_from = pipes.get_pipe(pipe_from) 1388 dp_to = pipes.get_pipe(pipe_to) 1389 1390 # Duplicate all non-sequence specific data. 1391 for data_name in dir(dp_from): 1392 # Skip the container objects. 1393 if data_name in ['diff_tensor', 'mol', 'interatomic', 'structure', 'exp_info']: 1394 continue 1395 1396 # Skip special objects. 1397 if search('^_', data_name) or data_name in list(dp_from.__class__.__dict__.keys()): 1398 continue 1399 1400 # Get the original object. 1401 data_from = getattr(dp_from, data_name) 1402 1403 # The data already exists. 1404 if hasattr(dp_to, data_name): 1405 # Get the object in the target pipe. 1406 data_to = getattr(dp_to, data_name) 1407 1408 # The data must match! 1409 if data_from != data_to: 1410 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".") 1411 1412 # Skip the data. 1413 continue 1414 1415 # Duplicate the data. 1416 setattr(dp_to, data_name, deepcopy(data_from)) 1417 1418 # Diffusion tensor comparison. 1419 if hasattr(dp_from, 'diff_tensor'): 1420 # Duplicate the tensor if it doesn't exist. 1421 if not hasattr(dp_to, 'diff_tensor'): 1422 setattr(dp_to, 'diff_tensor', deepcopy(dp_from.diff_tensor)) 1423 1424 # Otherwise compare the objects inside the container. 1425 else: 1426 # Loop over the modifiable objects. 1427 for data_name in dp_from.diff_tensor._mod_attr: 1428 # Get the original object. 1429 data_from = None 1430 if hasattr(dp_from.diff_tensor, data_name): 1431 data_from = getattr(dp_from.diff_tensor, data_name) 1432 1433 # Get the target object. 1434 if data_from and not hasattr(dp_to.diff_tensor, data_name): 1435 raise RelaxError("The diffusion tensor object " + repr(data_name) + " of the " + repr(pipe_from) + " data pipe is not located in the " + repr(pipe_to) + " data pipe.") 1436 elif data_from: 1437 data_to = getattr(dp_to.diff_tensor, data_name) 1438 else: 1439 continue 1440 1441 # The data must match! 1442 if data_from != data_to: 1443 raise RelaxError("The object " + repr(data_name) + " is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".") 1444 1445 # Structure comparison. 1446 if hasattr(dp_from, 'structure'): 1447 # Duplicate the tensor if it doesn't exist. 1448 if not hasattr(dp_to, 'structure'): 1449 setattr(dp_to, 'structure', deepcopy(dp_from.structure)) 1450 1451 # Otherwise compare the objects inside the container. 1452 else: 1453 # Modifiable object checks. 1454 self._compare_objects(dp_from.structure, dp_to.structure, pipe_from, pipe_to) 1455 1456 # Tests for the model and molecule containers. 1457 if len(dp_from.structure.structural_data) != len(dp_from.structure.structural_data): 1458 raise RelaxError("The number of structural models is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".") 1459 1460 # Loop over the models. 1461 for i in range(len(dp_from.structure.structural_data)): 1462 # Alias. 1463 model_from = dp_from.structure.structural_data[i] 1464 model_to = dp_to.structure.structural_data[i] 1465 1466 # Model numbers. 1467 if model_from.num != model_to.num: 1468 raise RelaxError("The structure models are not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".") 1469 1470 # Molecule number. 1471 if len(model_from.mol) != len(model_to.mol): 1472 raise RelaxError("The number of molecules is not consistent between the pipes " + repr(pipe_from) + " and " + repr(pipe_to) + ".") 1473 1474 # Loop over the models. 1475 for mol_index in range(len(model_from.mol)): 1476 # Modifiable object checks. 1477 self._compare_objects(model_from.mol[mol_index], model_to.mol[mol_index], pipe_from, pipe_to) 1478 1479 # No sequence data, so skip the rest. 1480 if dp_from.mol.is_empty(): 1481 return 1482 1483 # Duplicate the sequence data if it doesn't exist. 1484 if dp_to.mol.is_empty(): 1485 sequence.copy(pipe_from=pipe_from, pipe_to=pipe_to, preserve_select=True, verbose=verbose) 1486 1487 # Duplicate the interatomic data if it doesn't exist. 1488 if dp_to.interatomic.is_empty(): 1489 interatomic.copy(pipe_from=pipe_from, pipe_to=pipe_to, verbose=verbose) 1490 1491 # Determine the model type of the original data pipe. 1492 pipes.switch(pipe_from) 1493 model_type = self._determine_model_type() 1494 1495 # Sequence specific data. 1496 spin, spin_id = return_spin_from_index(model_info, pipe=pipe_from, return_spin_id=True) 1497 if model_type == 'mf' or (model_type == 'local_tm' and not global_stats): 1498 # Duplicate the spin specific data. 1499 for name in dir(spin): 1500 # Skip special objects. 1501 if search('^__', name): 1502 continue 1503 1504 # Get the object. 1505 obj = getattr(spin, name) 1506 1507 # Skip methods. 1508 if isinstance(obj, MethodType): 1509 continue 1510 1511 # Duplicate the object. 1512 new_obj = deepcopy(getattr(spin, name)) 1513 setattr(dp_to.mol[spin._mol_index].res[spin._res_index].spin[spin._spin_index], name, new_obj) 1514 1515 # Duplicate the relaxation active spins which have not been copied yet. 1516 interatoms = interatomic.return_interatom_list(spin_id) 1517 for interatom in interatoms: 1518 # No relaxation mechanism. 1519 if not interatom.dipole_pair: 1520 continue 1521 1522 # The interacting spin. 1523 if spin_id != interatom.spin_id1: 1524 spin_id2 = interatom.spin_id1 1525 else: 1526 spin_id2 = interatom.spin_id2 1527 spin2 = return_spin(spin_id2) 1528 1529 # Duplicate the spin specific data. 1530 mol_index, res_index, spin_index = return_spin_indices(spin_id2) 1531 dp_to.mol[mol_index].res[res_index].spin[spin_index] = deepcopy(spin2) 1532 1533 # Other data types. 1534 else: 1535 # Duplicate all the spin specific data. 1536 dp_to.mol = deepcopy(dp_from.mol)
1537 1538 1539 eliminate_doc = [] 1540 eliminate_doc.append(Desc_container("Local tm model elimination rule")) 1541 eliminate_doc[-1].add_paragraph("The local tm, in some cases, may exceed the value expected for a global correlation time. Generally the tm value will be stuck at the upper limit defined for the parameter. These models are eliminated using the rule:") 1542 eliminate_doc[-1].add_verbatim(" tm >= c") 1543 eliminate_doc[-1].add_paragraph("The default value of c is 50 ns, although this can be overridden by supplying the value (in seconds) as the first element of the args tuple.") 1544 eliminate_doc.append(Desc_container("Internal correlation times {te, tf, ts} model elimination rules")) 1545 eliminate_doc[-1].add_paragraph("These parameters may experience the same problem as the local tm in that the model fails and the parameter value is stuck at the upper limit. These parameters are constrained using the formula (te, tf, ts <= 2tm). These failed models are eliminated using the rule:") 1546 eliminate_doc[-1].add_verbatim(" te, tf, ts >= c . tm.") 1547 eliminate_doc[-1].add_paragraph("The default value of c is 1.5. Because of round-off errors and the constraint algorithm, setting c to 2 will result in no models being eliminated as the minimised parameters will always be less than 2tm. The value can be changed by supplying the value as the second element of the tuple.") 1548 eliminate_doc.append(Desc_container("Arguments")) 1549 eliminate_doc[-1].add_paragraph("The 'args' argument must be a tuple of length 2, the elements of which must be numbers. For example, to eliminate models which have a local tm value greater than 25 ns and models with internal correlation times greater than 1.5 times tm, set 'args' to (25 * 1e-9, 1.5).") 1550
1551 - def eliminate(self, name, value, model_info, args, sim=None):
1552 """Model-free model elimination, parameter by parameter. 1553 1554 @param name: The parameter name. 1555 @type name: str 1556 @param value: The parameter value. 1557 @type value: float 1558 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1559 @type model_info: int 1560 @param args: The c1 and c2 elimination constant overrides. 1561 @type args: None or tuple of float 1562 @keyword sim: The Monte Carlo simulation index. 1563 @type sim: int 1564 @return: True if the model is to be eliminated, False otherwise. 1565 @rtype: bool 1566 """ 1567 1568 # Default values. 1569 c1 = 50.0 * 1e-9 1570 c2 = 1.5 1571 1572 # Depack the arguments. 1573 if args != None: 1574 c1, c2 = args 1575 1576 # Determine the model type. 1577 model_type = self._determine_model_type() 1578 1579 # Can't handle this one yet! 1580 if model_type != 'mf' and model_type != 'local_tm': 1581 raise RelaxError("Elimination of the global model is not yet supported.") 1582 1583 # Get the spin and it's id string. 1584 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True) 1585 1586 # Get the tm value. 1587 if model_type == 'local_tm': 1588 tm = spin.local_tm 1589 else: 1590 tm = cdp.diff_tensor.tm 1591 1592 # No tm value set, so skip the tests (no elimination). 1593 if tm == None: 1594 return False 1595 1596 # Local tm. 1597 if name == 'local_tm' and value >= c1: 1598 if sim == None: 1599 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), value, c1, spin_id)) 1600 else: 1601 print("Data pipe '%s': The local tm parameter of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), value, c1, sim, spin_id)) 1602 return True 1603 1604 # Internal correlation times. 1605 if match('t[efs]', name) and value >= c2 * tm: 1606 if sim == None: 1607 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, spin_id)) 1608 else: 1609 print("Data pipe '%s': The %s value of %.5g is greater than %.5g, eliminating simulation %i of spin system '%s'." % (pipes.cdp_name(), name, value, c2*tm, sim, spin_id)) 1610 return True 1611 1612 # Accept model. 1613 return False
1614 1615
1616 - def get_param_names(self, model_info=None):
1617 """Return a vector of parameter names. 1618 1619 @keyword model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1620 @type model_info: int 1621 @return: The vector of parameter names. 1622 @rtype: list of str 1623 """ 1624 1625 # Determine the model type. 1626 model_type = self._determine_model_type() 1627 1628 # Get the spin ids. 1629 if model_type == 'mf' or model_type == 'local_tm': 1630 # Get the spin and it's id string. 1631 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True) 1632 else: 1633 spin_id = None 1634 1635 # Assemble and return the parameter names. 1636 return self._assemble_param_names(model_type, spin_id=spin_id)
1637 1638
1639 - def get_param_values(self, model_info=None, sim_index=None):
1640 """Return a vector of parameter values. 1641 1642 @keyword model_info: The model index from model_info(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1643 @type model_info: int 1644 @keyword sim_index: The Monte Carlo simulation index. 1645 @type sim_index: int 1646 @return: The vector of parameter values. 1647 @rtype: list of str 1648 """ 1649 1650 # Test if the model-free models have been set up. 1651 for spin in spin_loop(): 1652 # Skip deselected spins. 1653 if not spin.select: 1654 continue 1655 1656 # Not setup. 1657 if not spin.model: 1658 raise RelaxNoModelError 1659 1660 # Determine the model type. 1661 model_type = self._determine_model_type() 1662 1663 # Set the spin container (to None if the model is global). 1664 if model_type == 'mf' or model_type == 'local_tm': 1665 spin = return_spin_from_index(model_info) 1666 else: 1667 spin = None 1668 1669 # Assemble the parameter values and return them. 1670 return self._assemble_param_vector(spin=spin, sim_index=sim_index, model_type=model_type)
1671 1672
1673 - def is_spin_param(self, name):
1674 """Determine whether the given parameter is spin specific. 1675 1676 Unless a diffusion parameter is encountered, this method will return true. 1677 1678 @param name: The name of the parameter. 1679 @type name: str 1680 @return: If the parameter is a diffusion parameter, False I returned. Otherwise True 1681 is returned. 1682 @rtype: bool 1683 """ 1684 1685 # Catch a diffusion parameter. 1686 if diffusion_tensor.return_data_name(name): 1687 return False 1688 1689 # All the rest: 1690 else: 1691 return True
1692 1693
1694 - def map_bounds(self, param, spin_id=None):
1695 """Create bounds for the OpenDX mapping function. 1696 1697 @param param: The name of the parameter to return the lower and upper bounds of. 1698 @type param: str 1699 @param spin_id: The spin identification string. 1700 @type spin_id: str 1701 @return: The upper and lower bounds of the parameter. 1702 @rtype: list of float 1703 """ 1704 1705 # Get the spin. 1706 spin = return_spin(spin_id) 1707 1708 # {s2, s2f, s2s}. 1709 if search('^s2', param): 1710 return [0.0, 1.0] 1711 1712 # {local tm, te, tf, ts}. 1713 elif search('^t', param) or param == 'local_tm': 1714 return [0.0, 1e-8] 1715 1716 # Rex. 1717 elif param == 'rex': 1718 return [0.0, 30.0 / (2.0 * pi * cdp.frq[cdp.ri_ids[0]])**2] 1719 1720 # Interatomic distances. 1721 elif param == 'r': 1722 return [1.0 * 1e-10, 1.1 * 1e-10] 1723 1724 # CSA. 1725 elif param == 'csa': 1726 return [-100 * 1e-6, -300 * 1e-6]
1727 1728
1729 - def model_desc(self, model_info):
1730 """Return a description of the model. 1731 1732 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1733 @type model_info: int 1734 @return: The model description. 1735 @rtype: str 1736 """ 1737 1738 # Determine the model type. 1739 model_type = self._determine_model_type() 1740 1741 # Global models. 1742 if model_type == 'all': 1743 return "Global model - all diffusion tensor parameters and spin specific model-free parameters." 1744 elif model_type == 'diff': 1745 return "Diffusion tensor model." 1746 1747 # Spin specific model. 1748 else: 1749 # Get the spin container. 1750 spin, spin_id = return_spin_from_index(model_info, return_spin_id=True) 1751 1752 # Return the description. 1753 return "Model-free model of spin '%s'." % spin_id
1754 1755
1756 - def model_loop(self):
1757 """Generator method for looping over the models (global or local). 1758 1759 If the model type is 'all' or 'diff', then this yields the single value of zero. Otherwise 1760 the global spin index is yielded. 1761 1762 1763 @return: The model index. This is zero for the global models or equal to the global spin 1764 index (which covers the molecule, residue, and spin indices). 1765 @rtype: int 1766 """ 1767 1768 # Determine the model type. 1769 model_type = self._determine_model_type() 1770 1771 # Global model. 1772 if model_type == 'all' or model_type == 'diff': 1773 yield 0 1774 1775 # Spin specific models. 1776 else: 1777 # Loop over the spins. 1778 global_index = -1 1779 for spin in spin_loop(): 1780 # Increment the global spin index. 1781 global_index = global_index + 1 1782 1783 # Yield the spin index. 1784 yield global_index
1785 1786
1787 - def model_statistics(self, model_info=None, spin_id=None, global_stats=None):
1788 """Return the k, n, and chi2 model statistics. 1789 1790 k - number of parameters. 1791 n - number of data points. 1792 chi2 - the chi-squared value. 1793 1794 1795 @keyword model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 1796 @type model_info: int 1797 @keyword spin_id: The spin identification string. Either this or the instance keyword argument must be supplied. 1798 @type spin_id: None or str 1799 @keyword global_stats: A parameter which determines if global or local statistics are returned. If None, then the appropriateness of global or local statistics is automatically determined. 1800 @type global_stats: None or bool 1801 @return: The optimisation statistics, in tuple format, of the number of parameters (k), the number of data points (n), and the chi-squared value (chi2). 1802 @rtype: tuple of (int, int, float) 1803 """ 1804 1805 # Bad argument combination. 1806 if model_info == None and spin_id == None: 1807 raise RelaxError("Either the model_info or spin_id argument must be supplied.") 1808 elif model_info != None and spin_id != None: 1809 raise RelaxError("The model_info arg " + repr(model_info) + " and spin_id arg " + repr(spin_id) + " clash. Only one should be supplied.") 1810 1811 # Determine the model type. 1812 model_type = self._determine_model_type() 1813 1814 # Determine if local or global statistics will be returned. 1815 if global_stats == None: 1816 if model_type in ['mf', 'local_tm']: 1817 global_stats = False 1818 else: 1819 global_stats = True 1820 1821 # Statistics for a single residue. 1822 if not global_stats: 1823 # Get the SpinContainer. 1824 if spin_id: 1825 spin = return_spin(spin_id) 1826 else: 1827 spin = return_spin_from_index(model_info) 1828 1829 # Skip deselected residues. 1830 if not spin.select: 1831 return None, None, None 1832 1833 # Missing data sets. 1834 if not hasattr(spin, 'ri_data'): 1835 return None, None, None 1836 1837 # Count the number of parameters. 1838 param_vector = self._assemble_param_vector(spin=spin) 1839 k = len(param_vector) 1840 1841 # Count the number of data points. 1842 n = len(spin.ri_data) 1843 1844 # The chi2 value. 1845 chi2 = spin.chi2 1846 1847 # Global stats. 1848 elif global_stats: 1849 # Count the number of parameters. 1850 param_vector = self._assemble_param_vector() 1851 k = len(param_vector) 1852 1853 # Count the number of data points. 1854 n = 0 1855 chi2 = 0 1856 for spin in spin_loop(): 1857 # Skip deselected residues. 1858 if not spin.select: 1859 continue 1860 1861 # Skip residues with no relaxation data. 1862 if not hasattr(spin, 'ri_data') or not len(spin.ri_data): 1863 continue 1864 1865 n = n + len(spin.ri_data) 1866 1867 # Local tm models. 1868 if model_type == 'local_tm': 1869 chi2 = chi2 + spin.chi2 1870 1871 # The chi2 value. 1872 if model_type != 'local_tm': 1873 if not hasattr(cdp, 'chi2'): 1874 raise RelaxError("Global statistics are not available, most likely because the global model has not been optimised.") 1875 chi2 = cdp.chi2 1876 1877 # Return the data. 1878 return k, n, chi2
1879 1880
1881 - def model_type(self):
1882 """Return the type of the model, either being 'local' or 'global'. 1883 1884 @return: The model type, one of 'local' or 'global'. 1885 @rtype: str 1886 """ 1887 1888 # Determine the model type. 1889 model_type = self._determine_model_type() 1890 1891 # Global models. 1892 if model_type in ['all', 'diff']: 1893 return 'global' 1894 1895 # Local models. 1896 else: 1897 return 'local'
1898 1899
1900 - def num_instances(self):
1901 """Function for returning the number of instances. 1902 1903 @return: The number of instances used for optimisation. Either the number of spins if 1904 the local optimisations are setup ('mf' and 'local_tm'), or 1 for the global 1905 models. 1906 @rtype: int 1907 """ 1908 1909 # Test if sequence data exists. 1910 if not exists_mol_res_spin_data(): 1911 return 0 1912 1913 # Determine the model type. 1914 model_type = self._determine_model_type() 1915 1916 # Sequence specific data. 1917 if model_type == 'mf' or model_type == 'local_tm': 1918 return count_spins() 1919 1920 # Other data. 1921 elif model_type == 'diff' or model_type == 'all': 1922 return 1 1923 1924 # Should not be here. 1925 else: 1926 raise RelaxFault
1927 1928
1929 - def overfit_deselect(self, data_check=True, verbose=True):
1930 """Deselect spins which have insufficient data to support minimisation. 1931 1932 @keyword data_check: A flag to signal if the presence of base data is to be checked for. 1933 @type data_check: bool 1934 @keyword verbose: A flag which if True will allow printouts. 1935 @type verbose: bool 1936 """ 1937 1938 # Print out. 1939 if verbose: 1940 print("\nOver-fit spin deselection:") 1941 1942 # Test if sequence data exists. 1943 if not exists_mol_res_spin_data(): 1944 raise RelaxNoSequenceError 1945 1946 # Is structural data required? 1947 need_vect = False 1948 if hasattr(cdp, 'diff_tensor') and (cdp.diff_tensor.type == 'spheroid' or cdp.diff_tensor.type == 'ellipsoid'): 1949 need_vect = True 1950 1951 # Loop over the sequence. 1952 deselect_flag = False 1953 for spin, spin_id in spin_loop(return_id=True): 1954 # Skip deselected spins. 1955 if not spin.select: 1956 continue 1957 1958 # The interatomic data. 1959 interatoms = interatomic.return_interatom_list(spin_id) 1960 1961 # Loop over the interatomic data. 1962 dipole_relax = False 1963 for i in range(len(interatoms)): 1964 # No dipolar relaxation mechanism. 1965 if not interatoms[i].dipole_pair: 1966 continue 1967 1968 # The surrounding spins. 1969 if spin_id != interatoms[i].spin_id1: 1970 spin_id2 = interatoms[i].spin_id1 1971 else: 1972 spin_id2 = interatoms[i].spin_id2 1973 spin2 = return_spin(spin_id2) 1974 1975 # Dipolar relaxation flag. 1976 dipole_relax = False 1977 1978 # No relaxation mechanism. 1979 if not dipole_relax and not hasattr(spin, 'csa') or spin.csa == None: 1980 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms')) 1981 spin.select = False 1982 deselect_flag = True 1983 continue 1984 1985 # Data checks. 1986 if data_check: 1987 # The number of relaxation data points. 1988 data_points = 0 1989 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'): 1990 for id in cdp.ri_ids: 1991 if id in spin.ri_data and spin.ri_data[id] != None: 1992 data_points += 1 1993 1994 # Relaxation data must exist! 1995 if not hasattr(spin, 'ri_data'): 1996 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data')) 1997 spin.select = False 1998 deselect_flag = True 1999 continue 2000 2001 # Require 3 or more relaxation data points. 2002 elif data_points < 3: 2003 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required')) 2004 spin.select = False 2005 deselect_flag = True 2006 continue 2007 2008 # Require at least as many data points as params to prevent over-fitting. 2009 elif hasattr(spin, 'params') and spin.params and len(spin.params) > data_points: 2010 warn(RelaxDeselectWarning(spin_id, 'over-fitting - more parameters than data points')) 2011 spin.select = False 2012 deselect_flag = True 2013 continue 2014 2015 # Test for structural data if required. 2016 for i in range(len(interatoms)): 2017 # No dipolar relaxation mechanism. 2018 if not interatoms[i].dipole_pair: 2019 continue 2020 2021 # Check the unit vectors. 2022 if need_vect: 2023 if not hasattr(interatoms[i], 'vector') or interatoms[i].vector == None: 2024 warn(RelaxDeselectWarning(spin_id, 'missing structural data')) 2025 spin.select = False 2026 deselect_flag = True 2027 continue 2028 2029 # Final printout. 2030 if verbose and not deselect_flag: 2031 print("No spins have been deselected.")
2032 2033 2034 return_data_name_doc = Desc_container("Model-free data type string matching patterns") 2035 _table = uf_tables.add_table(label="table: mf data type patterns", caption="Model-free data type string matching patterns.") 2036 _table.add_headings(["Data type", "Object name"]) 2037 _table.add_row(["Local tm", "'local_tm'"]) 2038 _table.add_row(["Order parameter S2", "'s2'"]) 2039 _table.add_row(["Order parameter S2f", "'s2f'"]) 2040 _table.add_row(["Order parameter S2s", "'s2s'"]) 2041 _table.add_row(["Correlation time te", "'te'"]) 2042 _table.add_row(["Correlation time tf", "'tf'"]) 2043 _table.add_row(["Correlation time ts", "'ts'"]) 2044 _table.add_row(["Chemical exchange", "'rex'"]) 2045 _table.add_row(["CSA", "'csa'"]) 2046 return_data_name_doc.add_table(_table.label) 2047 2048 2049 set_doc = Desc_container("Model-free set details") 2050 set_doc.add_paragraph("Setting a parameter value may have no effect depending on which model-free model is chosen, for example if S2f values and S2s values are set but the run corresponds to model-free model 'm4' then, because these data values are not parameters of the model, they will have no effect.") 2051 set_doc.add_paragraph("Note that the Rex values are scaled quadratically with field strength and should be supplied as a field strength independent value. Use the following formula to get the correct value:") 2052 set_doc.add_verbatim(" value = rex / (2.0 * pi * frequency) ** 2") 2053 set_doc.add_paragraph("where:") 2054 set_doc.add_list_element("rex is the chemical exchange value for the current frequency.") 2055 set_doc.add_list_element("pi is in the namespace of relax, ie just type 'pi'.") 2056 set_doc.add_list_element("frequency is the proton frequency corresponding to the data.") 2057 2058
2059 - def set_error(self, model_info, index, error):
2060 """Set the parameter errors. 2061 2062 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2063 @type model_info: int 2064 @param index: The index of the parameter to set the errors for. 2065 @type index: int 2066 @param error: The error value. 2067 @type error: float 2068 """ 2069 2070 # Parameter increment counter. 2071 inc = 0 2072 2073 # Determine the model type. 2074 model_type = self._determine_model_type() 2075 2076 # Get the parameter object names. 2077 param_names = self.data_names(set='params', scope='spin') 2078 2079 2080 # Diffusion tensor parameter errors. 2081 #################################### 2082 2083 if model_type == 'diff' or model_type == 'all': 2084 # Spherical diffusion. 2085 if cdp.diff_tensor.type == 'sphere': 2086 # Return the parameter array. 2087 if index == 0: 2088 cdp.diff_tensor.set(param='tm', value=error, category='err') 2089 2090 # Increment. 2091 inc = inc + 1 2092 2093 # Spheroidal diffusion. 2094 elif cdp.diff_tensor.type == 'spheroid': 2095 # Return the parameter array. 2096 if index == 0: 2097 cdp.diff_tensor.set(param='tm', value=error, category='err') 2098 elif index == 1: 2099 cdp.diff_tensor.set(param='Da', value=error, category='err') 2100 elif index == 2: 2101 cdp.diff_tensor.set(param='theta', value=error, category='err') 2102 elif index == 3: 2103 cdp.diff_tensor.set(param='phi', value=error, category='err') 2104 2105 # Increment. 2106 inc = inc + 4 2107 2108 # Ellipsoidal diffusion. 2109 elif cdp.diff_tensor.type == 'ellipsoid': 2110 # Return the parameter array. 2111 if index == 0: 2112 cdp.diff_tensor.set(param='tm', value=error, category='err') 2113 elif index == 1: 2114 cdp.diff_tensor.set(param='Da', value=error, category='err') 2115 elif index == 2: 2116 cdp.diff_tensor.set(param='Dr', value=error, category='err') 2117 elif index == 3: 2118 cdp.diff_tensor.set(param='alpha', value=error, category='err') 2119 elif index == 4: 2120 cdp.diff_tensor.set(param='beta', value=error, category='err') 2121 elif index == 5: 2122 cdp.diff_tensor.set(param='gamma', value=error, category='err') 2123 2124 # Increment. 2125 inc = inc + 6 2126 2127 2128 # Model-free parameter errors for the model type 'all'. 2129 ####################################################### 2130 2131 if model_type == 'all': 2132 # Loop over the spins. 2133 for spin in spin_loop(): 2134 # Skip deselected spins. 2135 if not spin.select: 2136 continue 2137 2138 # Loop over the residue specific parameters. 2139 for param in param_names: 2140 # Return the parameter array. 2141 if index == inc: 2142 setattr(spin, param + "_err", error) 2143 2144 # Increment. 2145 inc = inc + 1 2146 2147 2148 # Model-free parameters for the model types 'mf' and 'local_tm'. 2149 ################################################################ 2150 2151 if model_type == 'mf' or model_type == 'local_tm': 2152 # Get the spin container. 2153 spin = return_spin_from_index(model_info) 2154 2155 # Skip deselected residues. 2156 if not spin.select: 2157 return 2158 2159 # Loop over the residue specific parameters. 2160 for param in param_names: 2161 # Return the parameter array. 2162 if index == inc: 2163 setattr(spin, param + "_err", error) 2164 2165 # Increment. 2166 inc = inc + 1
2167 2168
2169 - def set_param_values(self, param=None, value=None, spin_id=None, force=True):
2170 """Set the model-free parameter values. 2171 2172 @keyword param: The parameter name list. 2173 @type param: list of str 2174 @keyword value: The parameter value list. 2175 @type value: list 2176 @keyword spin_id: The spin identification string, only used for spin specific parameters. 2177 @type spin_id: None or str 2178 @keyword force: A flag which if True will cause current values to be overwritten. If False, a RelaxError will raised if the parameter value is already set. 2179 @type force: bool 2180 """ 2181 2182 # Checks. 2183 arg_check.is_str_list(param, 'parameter name') 2184 2185 # Separate out the diffusion tensor parameters from the model-free parameters. 2186 diff_params = [] 2187 diff_vals = [] 2188 mf_params = [] 2189 mf_vals = [] 2190 for i in range(len(param)): 2191 # Diffusion tensor parameter. 2192 diff_obj = diffusion_tensor.return_data_name(param[i]) 2193 if diff_obj: 2194 diff_params.append(param[i]) 2195 diff_vals.append(value[i]) 2196 2197 # Model-free parameter. 2198 else: 2199 mf_params.append(param[i]) 2200 mf_vals.append(value[i]) 2201 2202 # Set the diffusion tensor parameters. 2203 if diff_params: 2204 diffusion_tensor.set(value=diff_vals, param=diff_params) 2205 2206 # Set the model-free parameters. 2207 for i in range(len(mf_params)): 2208 # The object name. 2209 obj_name = self.return_data_name(mf_params[i]) 2210 2211 # Check if it is a model-free parameter. 2212 if obj_name not in self.data_names(set='params', scope='spin') and obj_name not in self.data_names(set='generic', scope='spin'): 2213 raise RelaxError("The parameter '%s' is unknown. It should be one of %s or %s" % (mf_params[i], self.data_names(set='params', scope='spin'), self.data_names(set='generic', scope='spin'))) 2214 2215 # Set the parameter. 2216 for spin in spin_loop(spin_id): 2217 setattr(spin, obj_name, mf_vals[i])
2218 2219
2220 - def set_selected_sim(self, model_info, select_sim):
2221 """Set all simulation selection flags. 2222 2223 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2224 @type model_info: int 2225 @param select_sim: The selection flags. 2226 @type select_sim: bool 2227 """ 2228 2229 # Determine the model type. 2230 model_type = self._determine_model_type() 2231 2232 # Global model. 2233 if model_type == 'all' or model_type == 'diff': 2234 cdp.select_sim = select_sim 2235 2236 # Spin specific model. 2237 else: 2238 # Get the spin container. 2239 spin = return_spin_from_index(model_info) 2240 2241 # Skip if deselected. 2242 if not spin.select: 2243 return 2244 2245 # Set the simulation flags. 2246 spin.select_sim = deepcopy(select_sim)
2247 2248
2249 - def set_update(self, param, spin):
2250 """Function to update the other model-free parameters. 2251 2252 @param param: The name of the parameter which has been changed. 2253 @type param: str 2254 @param spin: The SpinContainer object. 2255 @type spin: SpinContainer 2256 """ 2257 2258 # S2f parameter. 2259 if param == 's2f': 2260 # Update S2 if S2s exists. 2261 if hasattr(spin, 's2s') and spin.s2s != None: 2262 spin.s2 = spin.s2f * spin.s2s 2263 2264 2265 # S2s parameter. 2266 if param == 's2s': 2267 # Update S2 if S2f exists. 2268 if hasattr(spin, 's2f') and spin.s2f != None: 2269 spin.s2 = spin.s2f * spin.s2s
2270 2271
2272 - def sim_init_values(self):
2273 """Initialise the Monte Carlo parameter values.""" 2274 2275 # Determine the model type. 2276 model_type = self._determine_model_type() 2277 2278 # Get the parameter object names. 2279 param_names = self.data_names(set='params', scope='spin') 2280 2281 # Get the minimisation statistic object names. 2282 min_names = self.data_names(set='min', scope='spin') 2283 2284 # List of diffusion tensor parameters. 2285 if model_type == 'diff' or model_type == 'all': 2286 # Spherical diffusion. 2287 if cdp.diff_tensor.type == 'sphere': 2288 diff_params = ['tm'] 2289 2290 # Spheroidal diffusion. 2291 elif cdp.diff_tensor.type == 'spheroid': 2292 diff_params = ['tm', 'Da', 'theta', 'phi'] 2293 2294 # Ellipsoidal diffusion. 2295 elif cdp.diff_tensor.type == 'ellipsoid': 2296 diff_params = ['tm', 'Da', 'Dr', 'alpha', 'beta', 'gamma'] 2297 2298 2299 # Test if Monte Carlo parameter values have already been set. 2300 ############################################################# 2301 2302 # Diffusion tensor parameters and non spin specific minimisation statistics. 2303 if model_type == 'diff' or model_type == 'all': 2304 # Loop over the parameters. 2305 for object_name in diff_params: 2306 # Name for the simulation object. 2307 sim_object_name = object_name + '_sim' 2308 2309 # Test if the simulation object already exists. 2310 if hasattr(cdp.diff_tensor, sim_object_name): 2311 raise RelaxError("Monte Carlo parameter values have already been set.") 2312 2313 # Loop over the minimisation stats objects. 2314 for object_name in min_names: 2315 # Name for the simulation object. 2316 sim_object_name = object_name + '_sim' 2317 2318 # Test if the simulation object already exists. 2319 if hasattr(cdp, sim_object_name): 2320 raise RelaxError("Monte Carlo parameter values have already been set.") 2321 2322 # Spin specific parameters. 2323 if model_type != 'diff': 2324 for spin in spin_loop(): 2325 # Skip deselected spins. 2326 if not spin.select: 2327 continue 2328 2329 # Loop over all the parameter names. 2330 for object_name in param_names: 2331 # Name for the simulation object. 2332 sim_object_name = object_name + '_sim' 2333 2334 # Test if the simulation object already exists. 2335 if hasattr(spin, sim_object_name): 2336 raise RelaxError("Monte Carlo parameter values have already been set.") 2337 2338 2339 # Set the Monte Carlo parameter values. 2340 ####################################### 2341 2342 # Loop over the global minimisation stats objects. 2343 for object_name in min_names: 2344 # Skip non-existent objects. 2345 if not hasattr(cdp, object_name): 2346 continue 2347 2348 # Name for the simulation object. 2349 sim_object_name = object_name + '_sim' 2350 2351 # Create the simulation object. 2352 setattr(cdp, sim_object_name, []) 2353 2354 # Get the simulation object. 2355 sim_object = getattr(cdp, sim_object_name) 2356 2357 # Loop over the simulations. 2358 for j in range(cdp.sim_number): 2359 # Get the object. 2360 object = getattr(cdp, object_name) 2361 2362 # Copy and append the data. 2363 sim_object.append(deepcopy(object)) 2364 2365 # Diffusion tensor parameters and non spin specific minimisation statistics. 2366 if model_type == 'diff' or model_type == 'all': 2367 # Set up the number of simulations. 2368 cdp.diff_tensor.set_sim_num(cdp.sim_number) 2369 2370 # Loop over the parameters, setting the initial simulation values to those of the parameter value. 2371 for object_name in diff_params: 2372 for j in range(cdp.sim_number): 2373 cdp.diff_tensor.set(param=object_name, value=deepcopy(getattr(cdp.diff_tensor, object_name)), category='sim', sim_index=j) 2374 2375 # Spin specific parameters. 2376 if model_type != 'diff': 2377 for spin in spin_loop(): 2378 # Skip deselected spins. 2379 if not spin.select: 2380 continue 2381 2382 # Loop over all the data names. 2383 for object_name in param_names: 2384 # Name for the simulation object. 2385 sim_object_name = object_name + '_sim' 2386 2387 # Create the simulation object. 2388 setattr(spin, sim_object_name, []) 2389 2390 # Get the simulation object. 2391 sim_object = getattr(spin, sim_object_name) 2392 2393 # Loop over the simulations. 2394 for j in range(cdp.sim_number): 2395 # Copy and append the data. 2396 sim_object.append(deepcopy(getattr(spin, object_name))) 2397 2398 # Loop over all the minimisation object names. 2399 for object_name in min_names: 2400 # Name for the simulation object. 2401 sim_object_name = object_name + '_sim' 2402 2403 # Create the simulation object. 2404 setattr(spin, sim_object_name, []) 2405 2406 # Get the simulation object. 2407 sim_object = getattr(spin, sim_object_name) 2408 2409 # Loop over the simulations. 2410 for j in range(cdp.sim_number): 2411 # Copy and append the data. 2412 sim_object.append(deepcopy(getattr(spin, object_name)))
2413 2414
2415 - def sim_return_chi2(self, model_info, index=None):
2416 """Return the simulation chi-squared values. 2417 2418 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2419 @type model_info: int 2420 @keyword index: The optional simulation index. 2421 @type index: int 2422 @return: The list of simulation chi-squared values. If the index is supplied, only a single value will be returned. 2423 @rtype: list of float or float 2424 """ 2425 2426 # Determine the model type. 2427 model_type = self._determine_model_type() 2428 2429 # Single instance. 2430 if model_type == 'all' or model_type == 'diff': 2431 return cdp.chi2_sim 2432 2433 # Multiple instances. 2434 else: 2435 # Get the spin container. 2436 spin = return_spin_from_index(model_info) 2437 2438 # Return the list. 2439 return spin.chi2_sim
2440 2441
2442 - def sim_return_param(self, model_info, index):
2443 """Return the array of simulation parameter values. 2444 2445 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2446 @type model_info: int 2447 @param index: The index of the parameter to return the array of values for. 2448 @type index: int 2449 @return: The array of simulation parameter values. 2450 @rtype: list of float 2451 """ 2452 2453 # Parameter increment counter. 2454 inc = 0 2455 2456 # Determine the model type. 2457 model_type = self._determine_model_type() 2458 2459 # Get the parameter object names. 2460 param_names = self.data_names(set='params', scope='spin') 2461 2462 2463 # Diffusion tensor parameters. 2464 ############################## 2465 2466 if model_type == 'diff' or model_type == 'all': 2467 # Spherical diffusion. 2468 if cdp.diff_tensor.type == 'sphere': 2469 # Return the parameter array. 2470 if index == 0: 2471 return cdp.diff_tensor.tm_sim 2472 2473 # Increment. 2474 inc = inc + 1 2475 2476 # Spheroidal diffusion. 2477 elif cdp.diff_tensor.type == 'spheroid': 2478 # Return the parameter array. 2479 if index == 0: 2480 return cdp.diff_tensor.tm_sim 2481 elif index == 1: 2482 return cdp.diff_tensor.Da_sim 2483 elif index == 2: 2484 return cdp.diff_tensor.theta_sim 2485 elif index == 3: 2486 return cdp.diff_tensor.phi_sim 2487 2488 # Increment. 2489 inc = inc + 4 2490 2491 # Ellipsoidal diffusion. 2492 elif cdp.diff_tensor.type == 'ellipsoid': 2493 # Return the parameter array. 2494 if index == 0: 2495 return cdp.diff_tensor.tm_sim 2496 elif index == 1: 2497 return cdp.diff_tensor.Da_sim 2498 elif index == 2: 2499 return cdp.diff_tensor.Dr_sim 2500 elif index == 3: 2501 return cdp.diff_tensor.alpha_sim 2502 elif index == 4: 2503 return cdp.diff_tensor.beta_sim 2504 elif index == 5: 2505 return cdp.diff_tensor.gamma_sim 2506 2507 # Increment. 2508 inc = inc + 6 2509 2510 2511 # Model-free parameters for the model type 'all'. 2512 ################################################# 2513 2514 if model_type == 'all': 2515 # Loop over the spins. 2516 for spin in spin_loop(): 2517 # Skip deselected spins. 2518 if not spin.select: 2519 continue 2520 2521 # Loop over the spin specific parameters. 2522 for param in param_names: 2523 # Return the parameter array. 2524 if index == inc: 2525 return getattr(spin, param + "_sim") 2526 2527 # Increment. 2528 inc = inc + 1 2529 2530 2531 # Model-free parameters for the model types 'mf' and 'local_tm'. 2532 ################################################################ 2533 2534 if model_type == 'mf' or model_type == 'local_tm': 2535 # Get the spin container. 2536 spin = return_spin_from_index(model_info) 2537 2538 # Skip deselected spins. 2539 if not spin.select: 2540 return 2541 2542 # Loop over the spin specific parameters. 2543 for param in param_names: 2544 # Return the parameter array. 2545 if index == inc: 2546 return getattr(spin, param + "_sim") 2547 2548 # Increment. 2549 inc = inc + 1
2550 2551
2552 - def sim_return_selected(self, model_info):
2553 """Return the array of selected simulation flags for the spin. 2554 2555 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2556 @type model_info: int 2557 @return: The array of selected simulation flags. 2558 @rtype: list of int 2559 """ 2560 2561 # Determine the model type. 2562 model_type = self._determine_model_type() 2563 2564 # Single instance. 2565 if model_type == 'all' or model_type == 'diff': 2566 return cdp.select_sim 2567 2568 # Multiple instances. 2569 else: 2570 # Get the spin container. 2571 spin = return_spin_from_index(model_info) 2572 2573 # Skip if deselected. 2574 if not spin.select: 2575 return 2576 2577 # Return the list. 2578 return spin.select_sim
2579 2580
2581 - def skip_function(self, model_info):
2582 """Skip certain data. 2583 2584 @param model_info: The model index from model_loop(). This is zero for the global models or equal to the global spin index (which covers the molecule, residue, and spin indices). 2585 @type model_info: int 2586 @return: True if the data should be skipped, False otherwise. 2587 @rtype: bool 2588 """ 2589 2590 # Determine the model type. 2591 model_type = self._determine_model_type() 2592 2593 # Sequence specific data. 2594 if (model_type == 'mf' or model_type == 'local_tm') and not return_spin_from_index(model_info).select: 2595 return True 2596 2597 # Don't skip. 2598 return False
2599