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