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

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