Package specific_fns :: Module consistency_tests
[hide private]
[frames] | no frames]

Source Code for Module specific_fns.consistency_tests

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2004-2013 Edward d'Auvergne                                   # 
  4  # Copyright (C) 2007-2009 Sebastien Morin                                     # 
  5  #                                                                             # 
  6  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  7  #                                                                             # 
  8  # This program is free software: you can redistribute it and/or modify        # 
  9  # it under the terms of the GNU General Public License as published by        # 
 10  # the Free Software Foundation, either version 3 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # This program is distributed in the hope that it will be useful,             # 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 16  # GNU General Public License for more details.                                # 
 17  #                                                                             # 
 18  # You should have received a copy of the GNU General Public License           # 
 19  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """Analysis specific code for the consistency testing of multi-field relaxation data.""" 
 25   
 26  # Python module imports. 
 27  from re import search 
 28  from warnings import warn 
 29   
 30  # relax module imports. 
 31  from generic_fns.interatomic import return_interatom_list 
 32  from generic_fns.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop 
 33  from generic_fns import pipes 
 34  from maths_fns.consistency_tests import Consistency 
 35  from physical_constants import N15_CSA, NH_BOND_LENGTH, h_bar, mu0, return_gyromagnetic_ratio 
 36  from relax_errors import RelaxError, RelaxFuncSetupError, RelaxNoSequenceError, RelaxNoValueError, RelaxSpinTypeError 
 37  from relax_warnings import RelaxDeselectWarning 
 38  import specific_fns 
 39  from specific_fns.api_base import API_base 
 40  from specific_fns.api_common import API_common 
 41  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 42  from user_functions.objects import Desc_container 
 43   
 44   
45 -class Consistency_tests(API_base, API_common):
46 """Class containing functions specific to consistency testing.""" 47
48 - def __init__(self):
49 """Initialise the class by placing API_common methods into the API.""" 50 51 # Execute the base class __init__ method. 52 super(Consistency_tests, self).__init__() 53 54 # Place methods into the API. 55 self.base_data_loop = self._base_data_loop_spin 56 self.create_mc_data = self._create_mc_relax_data 57 self.model_loop = self._model_loop_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 # Set up the spin parameters. 66 self.PARAMS.add('j0', scope='spin', desc='Spectral density value at 0 MHz (from Farrow et al. (1995) JBNMR, 6: 153-162)', py_type=float, grace_string='\\qJ(0)\\Q', err=True, sim=True) 67 self.PARAMS.add('f_eta', scope='spin', desc='Eta-test (from Fushman et al. (1998) JACS, 120: 10947-10952)', py_type=float, grace_string='\\qF\\s\\xh\\Q', err=True, sim=True) 68 self.PARAMS.add('f_r2', scope='spin', desc='R2-test (from Fushman et al. (1998) JACS, 120: 10947-10952)', py_type=float, grace_string='\\qF\\sR2\\Q', err=True, sim=True) 69 self.PARAMS.add('csa', scope='spin', default=N15_CSA, units='ppm', desc='CSA value', py_type=float, grace_string='\\qCSA\\Q') 70 self.PARAMS.add('orientation', scope='spin', default=15.7, units='degrees', desc="Angle between the 15N-1H vector and the principal axis of the 15N chemical shift tensor", py_type=float, grace_string='\\q\\xq\\Q') 71 self.PARAMS.add('tc', scope='spin', default=13 * 1e-9, units='ns', desc="Correlation time", py_type=float, grace_string='\\q\\xt\\f{}c\\Q')
72 73
74 - def _set_frq(self, frq=None):
75 """Function for selecting which relaxation data to use in the consistency tests.""" 76 77 # Test if the current pipe exists. 78 pipes.test() 79 80 # Test if the pipe type is set to 'ct'. 81 function_type = cdp.pipe_type 82 if function_type != 'ct': 83 raise RelaxFuncSetupError(specific_fns.setup.get_string(function_type)) 84 85 # Test if the frequency has been set. 86 if hasattr(cdp, 'ct_frq'): 87 raise RelaxError("The frequency for the run has already been set.") 88 89 # Create the data structure if it doesn't exist. 90 if not hasattr(cdp, 'ct_frq'): 91 cdp.ct_frq = {} 92 93 # Set the frequency. 94 cdp.ct_frq = frq
95 96
97 - def calculate(self, spin_id=None, verbosity=1, sim_index=None):
98 """Calculation of the consistency functions. 99 100 @keyword spin_id: The spin identification string. 101 @type spin_id: None or str 102 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity. 103 @type verbosity: int 104 @keyword sim_index: The optional MC simulation index. 105 @type sim_index: None or int 106 """ 107 108 # Test if the frequency has been set. 109 if not hasattr(cdp, 'ct_frq') or not isinstance(cdp.ct_frq, float): 110 raise RelaxError("The frequency has not been set up.") 111 112 # Test if the sequence data is loaded. 113 if not exists_mol_res_spin_data(): 114 raise RelaxNoSequenceError 115 116 # Test if the spin data has been set. 117 for spin, id in spin_loop(spin_id, return_id=True): 118 # Skip deselected spins. 119 if not spin.select: 120 continue 121 122 # Test if the nuclear isotope type has been set. 123 if not hasattr(spin, 'isotope'): 124 raise RelaxSpinTypeError 125 126 # Test if the CSA value has been set. 127 if not hasattr(spin, 'csa') or spin.csa == None: 128 raise RelaxNoValueError("CSA") 129 130 # Test if the angle Theta has been set. 131 if not hasattr(spin, 'orientation') or spin.orientation == None: 132 raise RelaxNoValueError("angle Theta") 133 134 # Test if the correlation time has been set. 135 if not hasattr(spin, 'tc') or spin.tc == None: 136 raise RelaxNoValueError("correlation time") 137 138 # Test the interatomic data. 139 interatoms = return_interatom_list(id) 140 for interatom in interatoms: 141 # No relaxation mechanism. 142 if not interatom.dipole_pair: 143 continue 144 145 # The interacting spin. 146 if id != interatom.spin_id1: 147 spin_id2 = interatom.spin_id1 148 else: 149 spin_id2 = interatom.spin_id2 150 spin2 = return_spin(spin_id2) 151 152 # Test if the nuclear isotope type has been set. 153 if not hasattr(spin2, 'isotope'): 154 raise RelaxSpinTypeError 155 156 # Test if the interatomic distance has been set. 157 if not hasattr(interatom, 'r') or interatom.r == None: 158 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2) 159 160 # Frequency index. 161 if cdp.ct_frq not in cdp.frq.values(): 162 raise RelaxError("No relaxation data corresponding to the frequency %s has been loaded." % cdp.ct_frq) 163 164 # Consistency testing. 165 for spin, id in spin_loop(spin_id, return_id=True): 166 # Skip deselected spins. 167 if not spin.select: 168 continue 169 170 # Set the r1, r2, and NOE to None. 171 r1 = None 172 r2 = None 173 noe = None 174 175 # Get the R1, R2, and NOE values corresponding to the set frequency. 176 for ri_id in cdp.ri_ids: 177 # The frequency does not match. 178 if cdp.frq[ri_id] != cdp.ct_frq: 179 continue 180 181 # R1. 182 if cdp.ri_type[ri_id] == 'R1': 183 if sim_index == None: 184 r1 = spin.ri_data[ri_id] 185 else: 186 r1 = spin.ri_data_sim[ri_id][sim_index] 187 188 # R2. 189 if cdp.ri_type[ri_id] == 'R2': 190 if sim_index == None: 191 r2 = spin.ri_data[ri_id] 192 else: 193 r2 = spin.ri_data_sim[ri_id][sim_index] 194 195 # NOE. 196 if cdp.ri_type[ri_id] == 'NOE': 197 if sim_index == None: 198 noe = spin.ri_data[ri_id] 199 else: 200 noe = spin.ri_data_sim[ri_id][sim_index] 201 202 # Skip the spin if not all of the three value exist. 203 if r1 == None or r2 == None or noe == None: 204 continue 205 206 # Loop over the interatomic data. 207 interatoms = return_interatom_list(id) 208 for i in range(len(interatoms)): 209 # No relaxation mechanism. 210 if not interatoms[i].dipole_pair: 211 continue 212 213 # The surrounding spins. 214 if id != interatoms[i].spin_id1: 215 spin_id2 = interatoms[i].spin_id1 216 else: 217 spin_id2 = interatoms[i].spin_id2 218 spin2 = return_spin(spin_id2) 219 220 # Gyromagnetic ratios. 221 gx = return_gyromagnetic_ratio(spin.isotope) 222 gh = return_gyromagnetic_ratio(spin2.isotope) 223 224 # The interatomic distance. 225 r = interatoms[i].r 226 227 # Initialise the function to calculate. 228 self.ct = Consistency(frq=cdp.ct_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar) 229 230 # Calculate the consistency tests values. 231 j0, f_eta, f_r2 = self.ct.func(orientation=spin.orientation, tc=spin.tc, r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe) 232 233 # Consistency tests values. 234 if sim_index == None: 235 spin.j0 = j0 236 spin.f_eta = f_eta 237 spin.f_r2 = f_r2 238 239 # Monte Carlo simulated consistency tests values. 240 else: 241 # Initialise the simulation data structures. 242 self.data_init(spin, sim=1) 243 if spin.j0_sim == None: 244 spin.j0_sim = [] 245 spin.f_eta_sim = [] 246 spin.f_r2_sim = [] 247 248 # Consistency tests values. 249 spin.j0_sim.append(j0) 250 spin.f_eta_sim.append(f_eta) 251 spin.f_r2_sim.append(f_r2)
252 253
254 - def data_init(self, data_cont, sim=False):
255 """Initialise the data structures. 256 257 @param data_cont: The data container. 258 @type data_cont: instance 259 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure. 260 @type sim: bool 261 """ 262 263 # Get the data names. 264 data_names = self.data_names() 265 266 # Loop over the data structure names. 267 for name in data_names: 268 # Simulation data structures. 269 if sim: 270 # Add '_sim' to the names. 271 name = name + '_sim' 272 273 # If the name is not in 'data_cont', add it. 274 if not hasattr(data_cont, name): 275 # Set the attribute. 276 setattr(data_cont, name, None)
277 278 279 default_value_doc = Desc_container("Consistency testing default values") 280 default_value_doc.add_paragraph("These default values are found in the file 'physical_constants.py'.") 281 _table = uf_tables.add_table(label="table: consistency testing default values", caption="Consistency testing default values.") 282 _table.add_headings(["Data type", "Object name", "Value"]) 283 _table.add_row(["Bond length", "'r'", "1.02 * 1e-10"]) 284 _table.add_row(["CSA", "'csa'", "-172 * 1e-6"]) 285 _table.add_row(["Heteronucleus type", "'heteronuc_type'", "'15N'"]) 286 _table.add_row(["Angle theta", "'proton_type'", "'1H'"]) 287 _table.add_row(["Proton type", "'orientation'", "15.7"]) 288 _table.add_row(["Correlation time", "'tc'", "13 * 1e-9"]) 289 default_value_doc.add_table(_table.label) 290 291
292 - def overfit_deselect(self, data_check=True, verbose=True):
293 """Deselect spins which have insufficient data to support calculation. 294 295 @keyword data_check: A flag to signal if the presence of base data is to be checked for. 296 @type data_check: bool 297 @keyword verbose: A flag which if True will allow printouts. 298 @type verbose: bool 299 """ 300 301 # Print out. 302 if verbose: 303 print("\nOver-fit spin deselection:") 304 305 # Test the sequence data exists. 306 if not exists_mol_res_spin_data(): 307 raise RelaxNoSequenceError 308 309 # Loop over spin data. 310 deselect_flag = False 311 for spin, spin_id in spin_loop(return_id=True): 312 # Skip deselected spins. 313 if not spin.select: 314 continue 315 316 # Check if data exists. 317 if not hasattr(spin, 'ri_data'): 318 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data')) 319 spin.select = False 320 deselect_flag = True 321 continue 322 323 # Require 3 or more data points. 324 else: 325 # Count the points. 326 data_points = 0 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 # Not enough. 332 if data_points < 3: 333 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required')) 334 spin.select = False 335 deselect_flag = True 336 continue 337 338 # Final printout. 339 if verbose and not deselect_flag: 340 print("No spins have been deselected.")
341 342 343 return_data_name_doc = Desc_container("Consistency testing data type string matching patterns") 344 _table = uf_tables.add_table(label="table: Consistency testing data types", caption="Consistency testing data type string matching patterns.") 345 _table.add_headings(["Data type", "Object name"]) 346 _table.add_row(["J(0)", "'j0'"]) 347 _table.add_row(["F_eta", "'f_eta'"]) 348 _table.add_row(["F_R2", "'f_r2'"]) 349 _table.add_row(["Bond length", "'r'"]) 350 _table.add_row(["CSA", "'csa'"]) 351 _table.add_row(["Heteronucleus type", "'heteronuc_type'"]) 352 _table.add_row(["Proton type", "'proton_type'"]) 353 _table.add_row(["Angle theta", "'orientation'"]) 354 _table.add_row(["Correlation time", "'tc'"]) 355 return_data_name_doc.add_table(_table.label) 356 357 358 set_doc = Desc_container("Consistency testing set details") 359 set_doc.add_paragraph("In consistency testing, only four values can be set, the bond length, CSA, angle Theta ('orientation') and correlation time values. These must be set prior to the calculation of consistency functions.") 360 361
362 - def set_error(self, model_info, index, error):
363 """Set the parameter errors. 364 365 @param model_info: The spin container originating from model_loop(). 366 @type model_info: SpinContainer instance 367 @param index: The index of the parameter to set the errors for. 368 @type index: int 369 @param error: The error value. 370 @type error: float 371 """ 372 373 # Alias. 374 spin = model_info 375 376 # Return J(0) sim data. 377 if index == 0: 378 spin.j0_err = error 379 380 # Return F_eta sim data. 381 if index == 1: 382 spin.f_eta_err = error 383 384 # Return F_R2 sim data. 385 if index == 2: 386 spin.f_r2_err = error
387 388
389 - def sim_return_param(self, model_info, index):
390 """Return the array of simulation parameter values. 391 392 @param model_info: The spin container originating from model_loop(). 393 @type model_info: SpinContainer instance 394 @param index: The index of the parameter to return the array of values for. 395 @type index: int 396 @return: The array of simulation parameter values. 397 @rtype: list of float 398 """ 399 400 # Alias. 401 spin = model_info 402 403 # Skip deselected spins. 404 if not spin.select: 405 return 406 407 # Return J(0) sim data. 408 if index == 0: 409 return spin.j0_sim 410 411 # Return F_eta sim data. 412 if index == 1: 413 return spin.f_eta_sim 414 415 # Return F_R2 sim data. 416 if index == 2: 417 return spin.f_r2_sim
418 419
420 - def sim_return_selected(self, model_info):
421 """Return the array of selected simulation flags. 422 423 @param model_info: The spin container originating from model_loop(). 424 @type model_info: SpinContainer instance 425 @return: The array of selected simulation flags. 426 @rtype: list of int 427 """ 428 429 # Alias. 430 spin = model_info 431 432 # Multiple spins. 433 return spin.select_sim
434