Package specific_analyses :: Package jw_mapping
[hide private]
[frames] | no frames]

Source Code for Package specific_analyses.jw_mapping

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