Package specific_analyses :: Package consistency_tests :: Module api
[hide private]
[frames] | no frames]

Source Code for Module specific_analyses.consistency_tests.api

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2002-2005,2007-2014 Edward d'Auvergne                         # 
  4  # Copyright (C) 2006 Chris MacRaild                                           # 
  5  # Copyright (C) 2007-2008 Sebastien Morin                                     # 
  6  #                                                                             # 
  7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  8  #                                                                             # 
  9  # This program is free software: you can redistribute it and/or modify        # 
 10  # it under the terms of the GNU General Public License as published by        # 
 11  # the Free Software Foundation, either version 3 of the License, or           # 
 12  # (at your option) any later version.                                         # 
 13  #                                                                             # 
 14  # This program is distributed in the hope that it will be useful,             # 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 17  # GNU General Public License for more details.                                # 
 18  #                                                                             # 
 19  # You should have received a copy of the GNU General Public License           # 
 20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """The consistency testing analysis API object.""" 
 26   
 27  # Python module imports. 
 28  from warnings import warn 
 29   
 30  # relax module imports. 
 31  from lib.errors import RelaxError, RelaxNoSequenceError, RelaxNoValueError, RelaxSpinTypeError 
 32  from lib.float import isInf 
 33  from lib.periodic_table import periodic_table 
 34  from lib.physical_constants import h_bar, mu0 
 35  from lib.warnings import RelaxWarning, RelaxDeselectWarning 
 36  from pipe_control.interatomic import return_interatom_list 
 37  from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop 
 38  from specific_analyses.api_base import API_base 
 39  from specific_analyses.api_common import API_common 
 40  from specific_analyses.consistency_tests.parameter_object import Consistency_tests_params 
 41  from target_functions.consistency_tests import Consistency 
 42   
 43   
44 -class Consistency_tests(API_base, API_common):
45 """Class containing functions specific to consistency testing.""" 46 47 # Class variable for storing the class instance (for the singleton design pattern). 48 instance = None 49
50 - def __init__(self):
51 """Initialise the class by placing API_common methods into the API.""" 52 53 # Place methods into the API. 54 self.base_data_loop = self._base_data_loop_spin 55 self.create_mc_data = self._create_mc_relax_data 56 self.model_loop = self._model_loop_spin 57 self.print_model_title = self._print_model_title_spin 58 self.return_conversion_factor = self._return_no_conversion_factor 59 self.return_error = self._return_error_relax_data 60 self.return_value = self._return_value_general 61 self.set_param_values = self._set_param_values_spin 62 self.set_selected_sim = self._set_selected_sim_spin 63 self.sim_pack_data = self._sim_pack_relax_data 64 65 # Place a copy of the parameter list object in the instance namespace. 66 self._PARAMS = Consistency_tests_params()
67 68
69 - def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
70 """Calculation of the consistency functions. 71 72 @keyword spin_id: The spin identification string. 73 @type spin_id: None or str 74 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices. 75 @type scaling_matrix: list of numpy rank-2, float64 array or list of None 76 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity. 77 @type verbosity: int 78 @keyword sim_index: The optional MC simulation index. 79 @type sim_index: None or int 80 """ 81 82 # Test if the frequency has been set. 83 if not hasattr(cdp, 'ct_frq') or not isinstance(cdp.ct_frq, float): 84 raise RelaxError("The frequency has not been set up.") 85 86 # Test if the sequence data is loaded. 87 if not exists_mol_res_spin_data(): 88 raise RelaxNoSequenceError 89 90 # Test if the spin data has been set. 91 for spin, id in spin_loop(spin_id, return_id=True): 92 # Skip deselected spins. 93 if not spin.select: 94 continue 95 96 # Test if the nuclear isotope type has been set. 97 if not hasattr(spin, 'isotope'): 98 raise RelaxSpinTypeError 99 100 # Test if the CSA value has been set. 101 if not hasattr(spin, 'csa') or spin.csa == None: 102 raise RelaxNoValueError("CSA") 103 104 # Test if the angle Theta has been set. 105 if not hasattr(spin, 'orientation') or spin.orientation == None: 106 raise RelaxNoValueError("angle Theta") 107 108 # Test if the correlation time has been set. 109 if not hasattr(spin, 'tc') or spin.tc == None: 110 raise RelaxNoValueError("correlation time") 111 112 # Test the interatomic data. 113 interatoms = return_interatom_list(spin_hash=spin._hash) 114 for interatom in interatoms: 115 # No relaxation mechanism. 116 if not interatom.dipole_pair: 117 continue 118 119 # The interacting spin. 120 if id != interatom.spin_id1: 121 spin_id2 = interatom.spin_id1 122 else: 123 spin_id2 = interatom.spin_id2 124 spin2 = return_spin(spin_id=spin_id2) 125 126 # Test if the nuclear isotope type has been set. 127 if not hasattr(spin2, 'isotope'): 128 raise RelaxSpinTypeError 129 130 # Test if the interatomic distance has been set. 131 if not hasattr(interatom, 'r') or interatom.r == None: 132 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2) 133 134 # Frequency index. 135 if cdp.ct_frq not in list(cdp.spectrometer_frq.values()): 136 raise RelaxError("No relaxation data corresponding to the frequency %s has been loaded." % cdp.ct_frq) 137 138 # Consistency testing. 139 for spin, id in spin_loop(spin_id, return_id=True): 140 # Skip deselected spins. 141 if not spin.select: 142 continue 143 144 # Set the r1, r2, and NOE to None. 145 r1 = None 146 r2 = None 147 noe = None 148 149 # Get the R1, R2, and NOE values corresponding to the set frequency. 150 for ri_id in cdp.ri_ids: 151 # The frequency does not match. 152 if cdp.spectrometer_frq[ri_id] != cdp.ct_frq: 153 continue 154 155 # R1. 156 if cdp.ri_type[ri_id] == 'R1': 157 if sim_index == None: 158 r1 = spin.ri_data[ri_id] 159 else: 160 r1 = spin.ri_data_sim[ri_id][sim_index] 161 162 # R2. 163 if cdp.ri_type[ri_id] == 'R2': 164 if sim_index == None: 165 r2 = spin.ri_data[ri_id] 166 else: 167 r2 = spin.ri_data_sim[ri_id][sim_index] 168 169 # NOE. 170 if cdp.ri_type[ri_id] == 'NOE': 171 if sim_index == None: 172 noe = spin.ri_data[ri_id] 173 else: 174 noe = spin.ri_data_sim[ri_id][sim_index] 175 176 # Skip the spin if not all of the three value exist. 177 if r1 == None or r2 == None or noe == None: 178 continue 179 180 # Loop over the interatomic data. 181 interatoms = return_interatom_list(spin_hash=spin._hash) 182 for i in range(len(interatoms)): 183 # No relaxation mechanism. 184 if not interatoms[i].dipole_pair: 185 continue 186 187 # The surrounding spins. 188 if id != interatoms[i].spin_id1: 189 spin_id2 = interatoms[i].spin_id1 190 else: 191 spin_id2 = interatoms[i].spin_id2 192 spin2 = return_spin(spin_id=spin_id2) 193 194 # Gyromagnetic ratios. 195 gx = periodic_table.gyromagnetic_ratio(spin.isotope) 196 gh = periodic_table.gyromagnetic_ratio(spin2.isotope) 197 198 # The interatomic distance. 199 r = interatoms[i].r 200 201 # Initialise the function to calculate. 202 ct = Consistency(frq=cdp.ct_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar) 203 204 # Calculate the consistency tests values. 205 j0, f_eta, f_r2 = ct.func(orientation=spin.orientation, tc=spin.tc, r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe) 206 207 # Consistency tests values. 208 if sim_index == None: 209 spin.j0 = j0 210 spin.f_eta = f_eta 211 spin.f_r2 = f_r2 212 213 # Monte Carlo simulated consistency tests values. 214 else: 215 # Initialise the simulation data structures. 216 self.data_init(id, sim=1) 217 if spin.j0_sim == None: 218 spin.j0_sim = [] 219 spin.f_eta_sim = [] 220 spin.f_r2_sim = [] 221 222 # Consistency tests values. 223 spin.j0_sim.append(j0) 224 spin.f_eta_sim.append(f_eta) 225 spin.f_r2_sim.append(f_r2)
226 227
228 - def data_init(self, data, sim=False):
229 """Initialise the data structures. 230 231 @param data: The spin ID string from the _base_data_loop_spin() method. 232 @type data: str 233 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure. 234 @type sim: bool 235 """ 236 237 # Get the spin container. 238 spin = return_spin(spin_id=data) 239 240 # Get the data names. 241 data_names = self.data_names() 242 243 # Loop over the data structure names. 244 for name in data_names: 245 # Simulation data structures. 246 if sim: 247 # Add '_sim' to the names. 248 name = name + '_sim' 249 250 # If the name is not in the spin container, add it. 251 if not hasattr(spin, name): 252 # Set the attribute. 253 setattr(spin, name, None)
254 255
256 - def get_param_names(self, model_info=None):
257 """Return a vector of parameter names. 258 259 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 260 @type model_info: SpinContainer instance, str 261 @return: The vector of parameter names. 262 @rtype: list of str 263 """ 264 265 # Return the fixed list. 266 return ['j0', 'f_eta', 'f_r2']
267 268
269 - def overfit_deselect(self, data_check=True, verbose=True):
270 """Deselect spins which have insufficient data to support calculation. 271 272 @keyword data_check: A flag to signal if the presence of base data is to be checked for. 273 @type data_check: bool 274 @keyword verbose: A flag which if True will allow printouts. 275 @type verbose: bool 276 """ 277 278 # Print out. 279 if verbose: 280 print("\nOver-fit spin deselection:") 281 282 # Test the sequence data exists. 283 if not exists_mol_res_spin_data(): 284 raise RelaxNoSequenceError 285 286 # Loop over spin data. 287 deselect_flag = False 288 spin_count = 0 289 for spin, spin_id in spin_loop(return_id=True): 290 # Skip deselected spins. 291 if not spin.select: 292 continue 293 294 # The interatomic data. 295 interatoms = return_interatom_list(spin_hash=spin._hash) 296 297 # Loop over the interatomic data. 298 dipole_relax = False 299 for i in range(len(interatoms)): 300 # No dipolar relaxation mechanism. 301 if not interatoms[i].dipole_pair: 302 continue 303 304 # The surrounding spins. 305 if spin_id != interatoms[i].spin_id1: 306 spin_id2 = interatoms[i].spin_id1 307 else: 308 spin_id2 = interatoms[i].spin_id2 309 spin2 = return_spin(spin_id=spin_id2) 310 311 # Dipolar relaxation flag. 312 dipole_relax = True 313 314 # No relaxation mechanism. 315 if not dipole_relax or not hasattr(spin, 'csa') or spin.csa == None: 316 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms')) 317 spin.select = False 318 deselect_flag = True 319 continue 320 321 # Data checks. 322 if data_check: 323 # The number of relaxation data points (and for infinite data). 324 data_points = 0 325 inf_data = False 326 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'): 327 for id in cdp.ri_ids: 328 if id in spin.ri_data and spin.ri_data[id] != None: 329 data_points += 1 330 331 # Infinite data! 332 if isInf(spin.ri_data[id]): 333 inf_data = True 334 335 # Infinite data. 336 if inf_data: 337 warn(RelaxDeselectWarning(spin_id, 'infinite relaxation data')) 338 spin.select = False 339 deselect_flag = True 340 continue 341 342 # Relaxation data must exist! 343 if not hasattr(spin, 'ri_data'): 344 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data')) 345 spin.select = False 346 deselect_flag = True 347 continue 348 349 # Require 3 or more relaxation data points. 350 if data_points < 3: 351 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required')) 352 spin.select = False 353 deselect_flag = True 354 continue 355 356 # Increment the spin number. 357 spin_count += 1 358 359 # No spins selected, so fail hard to prevent the user from going any further. 360 if spin_count == 0: 361 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed.")) 362 363 # Final printout. 364 if verbose and not deselect_flag: 365 print("No spins have been deselected.")
366 367
368 - def set_error(self, index, error, model_info=None):
369 """Set the parameter errors. 370 371 @param index: The index of the parameter to set the errors for. 372 @type index: int 373 @param error: The error value. 374 @type error: float 375 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 376 @type model_info: SpinContainer instance, str 377 """ 378 379 # Unpack the data. 380 spin, spin_id = model_info 381 382 # Return J(0) sim data. 383 if index == 0: 384 spin.j0_err = error 385 386 # Return F_eta sim data. 387 if index == 1: 388 spin.f_eta_err = error 389 390 # Return F_R2 sim data. 391 if index == 2: 392 spin.f_r2_err = error
393 394
395 - def sim_return_param(self, index, model_info=None):
396 """Return the array of simulation parameter values. 397 398 @param index: The index of the parameter to return the array of values for. 399 @type index: int 400 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 401 @type model_info: SpinContainer instance, str 402 @return: The array of simulation parameter values. 403 @rtype: list of float 404 """ 405 406 # Unpack the data. 407 spin, spin_id = model_info 408 409 # Skip deselected spins. 410 if not spin.select: 411 return 412 413 # Return J(0) sim data. 414 if index == 0: 415 return spin.j0_sim 416 417 # Return F_eta sim data. 418 if index == 1: 419 return spin.f_eta_sim 420 421 # Return F_R2 sim data. 422 if index == 2: 423 return spin.f_r2_sim
424 425
426 - def sim_return_selected(self, model_info=None):
427 """Return the array of selected simulation flags. 428 429 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 430 @type model_info: SpinContainer instance, str 431 @return: The array of selected simulation flags. 432 @rtype: list of int 433 """ 434 435 # Unpack the data. 436 spin, spin_id = model_info 437 438 # Multiple spins. 439 return spin.select_sim
440