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