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.periodic_table import periodic_table 
 32  from lib.physical_constants import h_bar, mu0 
 33  from lib.warnings import RelaxDeselectWarning 
 34  from pipe_control.interatomic import return_interatom_list 
 35  from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, spin_loop 
 36  from specific_analyses.api_base import API_base 
 37  from specific_analyses.api_common import API_common 
 38  from specific_analyses.jw_mapping.parameter_object import Jw_mapping_params 
 39  from target_functions.jw_mapping import Mapping 
 40   
 41   
42 -class Jw_mapping(API_base, API_common):
43 """Class containing functions specific to reduced spectral density mapping.""" 44 45 # Class variable for storing the class instance (for the singleton design pattern). 46 instance = None 47
48 - def __init__(self):
49 """Initialise the class by placing API_common methods into the API.""" 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.print_model_title = self._print_model_title_spin 56 self.return_conversion_factor = self._return_no_conversion_factor 57 self.return_error = self._return_error_relax_data 58 self.return_value = self._return_value_general 59 self.set_param_values = self._set_param_values_spin 60 self.set_selected_sim = self._set_selected_sim_spin 61 self.sim_pack_data = self._sim_pack_relax_data 62 63 # Place a copy of the parameter list object in the instance namespace. 64 self._PARAMS = Jw_mapping_params()
65 66
67 - def calculate(self, spin_id=None, scaling_matrix=None, verbosity=1, sim_index=None):
68 """Calculation of the spectral density values. 69 70 @keyword spin_id: The spin identification string. 71 @type spin_id: None or str 72 @keyword scaling_matrix: The per-model list of diagonal and square scaling matrices. 73 @type scaling_matrix: list of numpy rank-2, float64 array or list of None 74 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity. 75 @type verbosity: int 76 @keyword sim_index: The optional MC simulation index. 77 @type sim_index: None or int 78 """ 79 80 # Test if the frequency has been set. 81 if not hasattr(cdp, 'jw_frq') or not isinstance(cdp.jw_frq, float): 82 raise RelaxError("The frequency has not been set up.") 83 84 # Test if the sequence data is loaded. 85 if not exists_mol_res_spin_data(): 86 raise RelaxNoSequenceError 87 88 # Test if the spin data has been set. 89 for spin, id in spin_loop(spin_id, return_id=True): 90 # Skip deselected spins. 91 if not spin.select: 92 continue 93 94 # Test if the nuclear isotope type has been set. 95 if not hasattr(spin, 'isotope'): 96 raise RelaxSpinTypeError 97 98 # Test if the CSA value has been set. 99 if not hasattr(spin, 'csa') or spin.csa == None: 100 raise RelaxNoValueError("CSA") 101 102 # Test the interatomic data. 103 interatoms = return_interatom_list(id) 104 for interatom in interatoms: 105 # No relaxation mechanism. 106 if not interatom.dipole_pair: 107 continue 108 109 # The interacting spin. 110 if id != interatom.spin_id1: 111 spin_id2 = interatom.spin_id1 112 else: 113 spin_id2 = interatom.spin_id2 114 spin2 = return_spin(spin_id2) 115 116 # Test if the nuclear isotope type has been set. 117 if not hasattr(spin2, 'isotope'): 118 raise RelaxSpinTypeError 119 120 # Test if the interatomic distance has been set. 121 if not hasattr(interatom, 'r') or interatom.r == None: 122 raise RelaxNoValueError("interatomic distance", spin_id=spin_id, spin_id2=spin_id2) 123 124 # Frequency index. 125 if cdp.jw_frq not in list(cdp.spectrometer_frq.values()): 126 raise RelaxError("No relaxation data corresponding to the frequency " + repr(cdp.jw_frq) + " has been loaded.") 127 128 # Reduced spectral density mapping. 129 for spin, id in spin_loop(spin_id, return_id=True): 130 # Skip deselected spins. 131 if not spin.select: 132 continue 133 134 # Set the r1, r2, and NOE to None. 135 r1 = None 136 r2 = None 137 noe = None 138 139 # Get the R1, R2, and NOE values corresponding to the set frequency. 140 for ri_id in cdp.ri_ids: 141 # The frequency does not match. 142 if cdp.spectrometer_frq[ri_id] != cdp.jw_frq: 143 continue 144 145 # R1. 146 if cdp.ri_type[ri_id] == 'R1': 147 if sim_index == None: 148 r1 = spin.ri_data[ri_id] 149 else: 150 r1 = spin.ri_data_sim[ri_id][sim_index] 151 152 # R2. 153 if cdp.ri_type[ri_id] == 'R2': 154 if sim_index == None: 155 r2 = spin.ri_data[ri_id] 156 else: 157 r2 = spin.ri_data_sim[ri_id][sim_index] 158 159 # NOE. 160 if cdp.ri_type[ri_id] == 'NOE': 161 if sim_index == None: 162 noe = spin.ri_data[ri_id] 163 else: 164 noe = spin.ri_data_sim[ri_id][sim_index] 165 166 # Skip the spin if not all of the three value exist. 167 if r1 == None or r2 == None or noe == None: 168 continue 169 170 # Loop over the interatomic data. 171 interatoms = return_interatom_list(id) 172 for i in range(len(interatoms)): 173 # No relaxation mechanism. 174 if not interatoms[i].dipole_pair: 175 continue 176 177 # The surrounding spins. 178 if id != interatoms[i].spin_id1: 179 spin_id2 = interatoms[i].spin_id1 180 else: 181 spin_id2 = interatoms[i].spin_id2 182 spin2 = return_spin(spin_id2) 183 184 # Gyromagnetic ratios. 185 gx = periodic_table.gyromagnetic_ratio(spin.isotope) 186 gh = periodic_table.gyromagnetic_ratio(spin2.isotope) 187 188 # The interatomic distance. 189 r = interatoms[i].r 190 191 # Initialise the function to calculate. 192 jw = Mapping(frq=cdp.jw_frq, gx=gx, gh=gh, mu0=mu0, h_bar=h_bar) 193 194 # Calculate the spectral density values. 195 j0, jwx, jwh = jw.func(r=r, csa=spin.csa, r1=r1, r2=r2, noe=noe) 196 197 # Reduced spectral density values. 198 if sim_index == None: 199 spin.j0 = j0 200 spin.jwx = jwx 201 spin.jwh = jwh 202 203 # Monte Carlo simulated reduced spectral density values. 204 else: 205 # Initialise the simulation data structures. 206 self.data_init(id, sim=1) 207 if spin.j0_sim == None: 208 spin.j0_sim = [] 209 spin.jwx_sim = [] 210 spin.jwh_sim = [] 211 212 # Reduced spectral density values. 213 spin.j0_sim.append(j0) 214 spin.jwx_sim.append(jwx) 215 spin.jwh_sim.append(jwh)
216 217
218 - def data_init(self, data, sim=False):
219 """Initialise the data structures. 220 221 @param data: The spin ID string from the _base_data_loop_spin() method. 222 @type data: str 223 @keyword sim: The Monte Carlo simulation flag, which if true will initialise the simulation data structure. 224 @type sim: bool 225 """ 226 227 # Get the spin container. 228 spin = return_spin(data) 229 230 # Get the data names. 231 data_names = self.data_names() 232 233 # Loop over the data structure names. 234 for name in data_names: 235 # Simulation data structures. 236 if sim: 237 # Add '_sim' to the names. 238 name = name + '_sim' 239 240 # If the name is not in the spin container, add it. 241 if not hasattr(spin, name): 242 # Set the attribute. 243 setattr(spin, name, None)
244 245
246 - def get_param_names(self, model_info=None):
247 """Return a vector of parameter names. 248 249 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 250 @type model_info: SpinContainer instance, str 251 @return: The vector of parameter names. 252 @rtype: list of str 253 """ 254 255 # Return the fixed list. 256 return ['j0', 'jwx', 'jwh']
257 258
259 - def overfit_deselect(self, data_check=True, verbose=True):
260 """Deselect spins which have insufficient data to support calculation. 261 262 @keyword data_check: A flag to signal if the presence of base data is to be checked for. 263 @type data_check: bool 264 @keyword verbose: A flag which if True will allow printouts. 265 @type verbose: bool 266 """ 267 268 # Print out. 269 if verbose: 270 print("\nOver-fit spin deselection:") 271 272 # Test if sequence data exists. 273 if not exists_mol_res_spin_data(): 274 raise RelaxNoSequenceError 275 276 # Loop over spin data. 277 deselect_flag = False 278 spin_count = 0 279 for spin, spin_id in spin_loop(return_id=True): 280 # Skip deselected spins. 281 if not spin.select: 282 continue 283 284 # The interatomic data. 285 interatoms = return_interatom_list(spin_id) 286 287 # Loop over the interatomic data. 288 dipole_relax = False 289 for i in range(len(interatoms)): 290 # No dipolar relaxation mechanism. 291 if not interatoms[i].dipole_pair: 292 continue 293 294 # The surrounding spins. 295 if spin_id != interatoms[i].spin_id1: 296 spin_id2 = interatoms[i].spin_id1 297 else: 298 spin_id2 = interatoms[i].spin_id2 299 spin2 = return_spin(spin_id2) 300 301 # Dipolar relaxation flag. 302 dipole_relax = True 303 304 # No relaxation mechanism. 305 if not dipole_relax or not hasattr(spin, 'csa') or spin.csa == None: 306 warn(RelaxDeselectWarning(spin_id, 'an absence of relaxation mechanisms')) 307 spin.select = False 308 deselect_flag = True 309 continue 310 311 # Data checks. 312 if data_check: 313 # The number of relaxation data points (and for infinite data). 314 data_points = 0 315 inf_data = False 316 if hasattr(cdp, 'ri_ids') and hasattr(spin, 'ri_data'): 317 for id in cdp.ri_ids: 318 if id in spin.ri_data and spin.ri_data[id] != None: 319 data_points += 1 320 321 # Infinite data! 322 if isInf(spin.ri_data[id]): 323 inf_data = True 324 325 # Infinite data. 326 if inf_data: 327 warn(RelaxDeselectWarning(spin_id, 'infinite relaxation data')) 328 spin.select = False 329 deselect_flag = True 330 continue 331 332 # Relaxation data must exist! 333 if not hasattr(spin, 'ri_data'): 334 warn(RelaxDeselectWarning(spin_id, 'missing relaxation data')) 335 spin.select = False 336 deselect_flag = True 337 continue 338 339 # Require 3 or more relaxation data points. 340 if data_points < 3: 341 warn(RelaxDeselectWarning(spin_id, 'insufficient relaxation data, 3 or more data points are required')) 342 spin.select = False 343 deselect_flag = True 344 continue 345 346 # Increment the spin number. 347 spin_count += 1 348 349 # No spins selected, so fail hard to prevent the user from going any further. 350 if spin_count == 0: 351 warn(RelaxWarning("No spins are selected therefore the optimisation or calculation cannot proceed.")) 352 353 # Final printout. 354 if verbose and not deselect_flag: 355 print("No spins have been deselected.")
356 357
358 - def set_error(self, index, error, model_info=None):
359 """Set the parameter errors. 360 361 @param index: The index of the parameter to set the errors for. 362 @type index: int 363 @param error: The error value. 364 @type error: float 365 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 366 @type model_info: SpinContainer instance, str 367 """ 368 369 # Unpack the data. 370 spin, spin_id = model_info 371 372 # Return J(0) sim data. 373 if index == 0: 374 spin.j0_err = error 375 376 # Return J(wX) sim data. 377 if index == 1: 378 spin.jwx_err = error 379 380 # Return J(wH) sim data. 381 if index == 2: 382 spin.jwh_err = error
383 384
385 - def sim_return_param(self, index, model_info=None):
386 """Return the array of simulation parameter values. 387 388 @param index: The index of the parameter to return the array of values for. 389 @type index: int 390 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 391 @type model_info: SpinContainer instance, str 392 @return: The array of simulation parameter values. 393 @rtype: list of float 394 """ 395 396 # Unpack the data. 397 spin, spin_id = model_info 398 399 # Skip deselected spins. 400 if not spin.select: 401 return 402 403 # Return J(0) sim data. 404 if index == 0: 405 return spin.j0_sim 406 407 # Return J(wX) sim data. 408 if index == 1: 409 return spin.jwx_sim 410 411 # Return J(wH) sim data. 412 if index == 2: 413 return spin.jwh_sim
414 415
416 - def sim_return_selected(self, model_info=None):
417 """Return the array of selected simulation flags. 418 419 @keyword model_info: The spin container and the spin ID string from the _model_loop_spin() method. 420 @type model_info: SpinContainer instance, str 421 @return: The array of selected simulation flags. 422 @rtype: list of int 423 """ 424 425 # Unpack the data. 426 spin, spin_id = model_info 427 428 # Multiple spins. 429 return spin.select_sim
430