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

Source Code for Module specific_analyses.jw_mapping.api

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2004-2014 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  # Module docstring. 
 23  """The reduced spectral density mapping API object.""" 
 24   
 25  # Python module imports. 
 26  from warnings import warn 
 27   
 28  # relax module imports. 
 29  from lib.errors import RelaxError, RelaxNoSequenceError, RelaxNoValueError, RelaxSpinTypeError 
 30  from lib.float import isInf 
 31  from lib.physical_constants import h_bar, mu0, return_gyromagnetic_ratio 
 32  from lib.warnings import RelaxDeselectWarning 
 33  from pipe_control.interatomic import return_interatom_list 
 34  from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop 
 35  from specific_analyses.api_base import API_base 
 36  from specific_analyses.api_common import API_common 
 37  from specific_analyses.jw_mapping.parameter_object import Jw_mapping_params 
 38  from target_functions.jw_mapping import Mapping 
 39   
 40   
41 -class Jw_mapping(API_base, API_common):
42 """Class containing functions specific to reduced spectral density mapping.""" 43 44 # Class variable for storing the class instance (for the singleton design pattern). 45 instance = None 46
47 - def __init__(self):
48 """Initialise the class by placing API_common methods into the API.""" 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 # Place a copy of the parameter list object in the instance namespace. 62 self._PARAMS = Jw_mapping_params()
63 64
65 - def calculate(self, spin_id=None, verbosity=1, sim_index=None):
66 """Calculation of the spectral density values. 67 68 @keyword spin_id: The spin identification string. 69 @type spin_id: None or str 70 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity. 71 @type verbosity: int 72 @keyword sim_index: The optional MC simulation index. 73 @type sim_index: None or int 74 """ 75 76 # Test if the frequency has been set. 77 if not hasattr(cdp, 'jw_frq') or not isinstance(cdp.jw_frq, float): 78 raise RelaxError("The frequency has not been set up.") 79 80 # Test if the sequence data is loaded. 81 if not exists_mol_res_spin_data(): 82 raise RelaxNoSequenceError 83 84 # Test if the spin data has been set. 85 for spin, id in spin_loop(spin_id, return_id=True): 86 # Skip deselected spins. 87 if not spin.select: 88 continue 89 90 # Test if the nuclear isotope type has been set. 91 if not hasattr(spin, 'isotope'): 92 raise RelaxSpinTypeError 93 94 # Test if the CSA value has been set. 95 if not hasattr(spin, 'csa') or spin.csa == None: 96 raise RelaxNoValueError("CSA") 97 98 # Test the interatomic data. 99 interatoms = return_interatom_list(id) 100 for interatom in interatoms: 101 # No relaxation mechanism. 102 if not interatom.dipole_pair: 103 continue 104 105 # The interacting spin. 106 if id != interatom.spin_id1: 107 spin_id2 = interatom.spin_id1 108 else: 109 spin_id2 = interatom.spin_id2 110 spin2 = return_spin(spin_id2) 111 112 # Test if the nuclear isotope type has been set. 113 if not hasattr(spin2, 'isotope'): 114 raise RelaxSpinTypeError 115 116 # Test if the interatomic distance has been set. 117 if not hasattr(interatom, 'r') or interatom.r == None: 118 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2) 119 120 # Frequency index. 121 if cdp.jw_frq not in cdp.spectrometer_frq.values(): 122 raise RelaxError("No relaxation data corresponding to the frequency " + repr(cdp.jw_frq) + " has been loaded.") 123 124 # Reduced spectral density mapping. 125 for spin, id in spin_loop(spin_id, return_id=True): 126 # Skip deselected spins. 127 if not spin.select: 128 continue 129 130 # Set the r1, r2, and NOE to None. 131 r1 = None 132 r2 = None 133 noe = None 134 135 # Get the R1, R2, and NOE values corresponding to the set frequency. 136 for ri_id in cdp.ri_ids: 137 # The frequency does not match. 138 if cdp.spectrometer_frq[ri_id] != cdp.jw_frq: 139 continue 140 141 # R1. 142 if cdp.ri_type[ri_id] == 'R1': 143 if sim_index == None: 144 r1 = spin.ri_data[ri_id] 145 else: 146 r1 = spin.ri_data_sim[ri_id][sim_index] 147 148 # R2. 149 if cdp.ri_type[ri_id] == 'R2': 150 if sim_index == None: 151 r2 = spin.ri_data[ri_id] 152 else: 153 r2 = spin.ri_data_sim[ri_id][sim_index] 154 155 # NOE. 156 if cdp.ri_type[ri_id] == 'NOE': 157 if sim_index == None: 158 noe = spin.ri_data[ri_id] 159 else: 160 noe = spin.ri_data_sim[ri_id][sim_index] 161 162 # Skip the spin if not all of the three value exist. 163 if r1 == None or r2 == None or noe == None: 164 continue 165 166 # Loop over the interatomic data. 167 interatoms = return_interatom_list(id) 168 for i in range(len(interatoms)): 169 # No relaxation mechanism. 170 if not interatoms[i].dipole_pair: 171 continue 172 173 # The surrounding spins. 174 if id != interatoms[i].spin_id1: 175 spin_id2 = interatoms[i].spin_id1 176 else: 177 spin_id2 = interatoms[i].spin_id2 178 spin2 = return_spin(spin_id2) 179 180 # Gyromagnetic ratios. 181 gx = return_gyromagnetic_ratio(spin.isotope) 182 gh = return_gyromagnetic_ratio(spin2.isotope) 183 184 # The interatomic distance. 185 r = interatoms[i].r 186 187 # Initialise the function to calculate. 188 jw = Mapping(frq=cdp.jw_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar) 189 190 # Calculate the spectral density values. 191 j0, jwx, jwh = jw.func(r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe) 192 193 # Reduced spectral density values. 194 if sim_index == None: 195 spin.j0 = j0 196 spin.jwx = jwx 197 spin.jwh = jwh 198 199 # Monte Carlo simulated reduced spectral density values. 200 else: 201 # Initialise the simulation data structures. 202 self.data_init(spin, sim=1) 203 if spin.j0_sim == None: 204 spin.j0_sim = [] 205 spin.jwx_sim = [] 206 spin.jwh_sim = [] 207 208 # Reduced spectral density values. 209 spin.j0_sim.append(j0) 210 spin.jwx_sim.append(jwx) 211 spin.jwh_sim.append(jwh)
212 213
214 - def data_init(self, data_cont, sim=False):
215 """Initialise the data structures. 216 217 @param data_cont: The data container. 218 @type data_cont: instance 219 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure. 220 @type sim: bool 221 """ 222 223 # Get the data names. 224 data_names = self.data_names() 225 226 # Loop over the data structure names. 227 for name in data_names: 228 # Simulation data structures. 229 if sim: 230 # Add '_sim' to the names. 231 name = name + '_sim' 232 233 # If the name is not in 'data_cont', add it. 234 if not hasattr(data_cont, name): 235 # Set the attribute. 236 setattr(data_cont, name, None)
237 238
239 - def overfit_deselect(self, data_check=True, verbose=True):
240 """Deselect spins which have insufficient data to support calculation. 241 242 @keyword data_check: A flag to signal if the presence of base data is to be checked for. 243 @type data_check: bool 244 @keyword verbose: A flag which if True will allow printouts. 245 @type verbose: bool 246 """ 247 248 # Print out. 249 if verbose: 250 print("\nOver-fit spin deselection:") 251 252 # Test if sequence data exists. 253 if not exists_mol_res_spin_data(): 254 raise RelaxNoSequenceError 255 256 # Loop over spin data. 257 deselect_flag = False 258 spin_count = 0 259 for spin, spin_id in spin_loop(return_id=True): 260 # Skip deselected spins. 261 if not spin.select: 262 continue 263 264 # The interatomic data. 265 interatoms = return_interatom_list(spin_id) 266 267 # Loop over the interatomic data. 268 dipole_relax = False 269 for i in range(len(interatoms)): 270 # No dipolar relaxation mechanism. 271 if not interatoms[i].dipole_pair: 272 continue 273 274 # The surrounding spins. 275 if spin_id != interatoms[i].spin_id1: 276 spin_id2 = interatoms[i].spin_id1 277 else: 278 spin_id2 = interatoms[i].spin_id2 279 spin2 = return_spin(spin_id2) 280 281 # Dipolar relaxation flag. 282 dipole_relax = True 283 284 # No relaxation mechanism. 285 if not dipole_relax or not hasattr(spin, 'csa') or spin.csa == None: 286 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms')) 287 spin.select = False 288 deselect_flag = True 289 continue 290 291 # Data checks. 292 if data_check: 293 # The number of relaxation data points (and for infinite data). 294 data_points = 0 295 inf_data = False 296 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'): 297 for id in cdp.ri_ids: 298 if id in spin.ri_data and spin.ri_data[id] != None: 299 data_points += 1 300 301 # Infinite data! 302 if isInf(spin.ri_data[id]): 303 inf_data = True 304 305 # Infinite data. 306 if inf_data: 307 warn(RelaxDeselectWarning(spin_id, 'infinite relaxation data')) 308 spin.select = False 309 deselect_flag = True 310 continue 311 312 # Relaxation data must exist! 313 if not hasattr(spin, 'ri_data'): 314 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data')) 315 spin.select = False 316 deselect_flag = True 317 continue 318 319 # Require 3 or more relaxation data points. 320 if data_points < 3: 321 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required')) 322 spin.select = False 323 deselect_flag = True 324 continue 325 326 # Increment the spin number. 327 spin_count += 1 328 329 # No spins selected, so fail hard to prevent the user from going any further. 330 if spin_count == 0: 331 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed.")) 332 333 # Final printout. 334 if verbose and not deselect_flag: 335 print("No spins have been deselected.")
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