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

Source Code for Module specific_fns.jw_mapping

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