Package specific_analyses :: Package relax_disp :: Module data
[hide private]
[frames] | no frames]

Source Code for Module specific_analyses.relax_disp.data

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2004-2014 Edward d'Auvergne                                   # 
   4  # Copyright (C) 2009 Sebastien Morin                                          # 
   5  # Copyright (C) 2013-2014 Troels E. Linnet                                    # 
   6  #                                                                             # 
   7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
   8  #                                                                             # 
   9  # This program is free software: you can redistribute it and/or modify        # 
  10  # it under the terms of the GNU General Public License as published by        # 
  11  # the Free Software Foundation, either version 3 of the License, or           # 
  12  # (at your option) any later version.                                         # 
  13  #                                                                             # 
  14  # This program is distributed in the hope that it will be useful,             # 
  15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  17  # GNU General Public License for more details.                                # 
  18  #                                                                             # 
  19  # You should have received a copy of the GNU General Public License           # 
  20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
  21  #                                                                             # 
  22  ############################################################################### 
  23   
  24  # Module docstring. 
  25  """Module for handling relaxation dispersion data within the relax data store. 
  26   
  27  Ordering of data 
  28  ================ 
  29   
  30  The dispersion data model is based on the following concepts, in order of importance: 
  31   
  32      - 'exp', the experiment type, 
  33      - 'spin', the spins of the cluster, 
  34      - 'frq', the spectrometer frequency (if multiple field data is present), 
  35      - 'offset', the spin-lock offsets, 
  36      - 'point', the dispersion point (nu_CPMG value or spin-lock nu1 field strength), 
  37      - 'time', the relaxation time point (if exponential curve data has been collected). 
  38   
  39   
  40  Indices 
  41  ======= 
  42   
  43  The data structures used in this module consist of many different index types which follow the data ordering above.  These are abbreviated as: 
  44   
  45      - Ei or ei:  The index for each experiment type. 
  46      - Si or si:  The index for each spin of the spin cluster. 
  47      - Mi or mi:  The index for each magnetic field strength. 
  48      - Oi or oi:  The index for each spin-lock offset.  In the case of CPMG-type data, this index is always zero. 
  49      - Di or di:  The index for each dispersion point (either the spin-lock field strength or the nu_CPMG frequency). 
  50      - Ti or ti:  The index for each dispersion point (either the spin-lock field strength or the nu_CPMG frequency). 
  51  """ 
  52   
  53  # Python module imports. 
  54  from math import atan2, pi, sqrt 
  55  from numpy import array, float64, int32, ones, zeros 
  56  from os.path import expanduser 
  57  from random import gauss 
  58  from re import search 
  59  import sys 
  60  from warnings import warn 
  61   
  62  # relax module imports. 
  63  from lib.errors import RelaxError, RelaxNoSpectraError, RelaxNoSpinError, RelaxSpinTypeError 
  64  from lib.float import isNaN 
  65  from lib.io import extract_data, get_file_path, open_write_file, strip, write_data 
  66  from lib.nmr import frequency_to_ppm, frequency_to_rad_per_s 
  67  from lib.physical_constants import g1H, return_gyromagnetic_ratio 
  68  from lib.sequence import read_spin_data, write_spin_data 
  69  from lib.software.grace import write_xy_data, write_xy_header, script_grace2images 
  70  from lib.warnings import RelaxWarning, RelaxNoSpinWarning 
  71  from pipe_control import pipes 
  72  from pipe_control.mol_res_spin import check_mol_res_spin_data, exists_mol_res_spin_data, generate_spin_id_unique, return_spin, spin_loop 
  73  from pipe_control.result_files import add_result_file 
  74  from pipe_control.selection import desel_spin 
  75  from pipe_control.sequence import return_attached_protons 
  76  from pipe_control.spectrum import add_spectrum_id 
  77  from pipe_control.spectrometer import check_frequency, get_frequency 
  78  from pipe_control import value 
  79  import specific_analyses 
  80  from specific_analyses.relax_disp.checks import check_exp_type, check_mixed_curve_types 
  81  from specific_analyses.relax_disp.variables import EXP_TYPE_CPMG_DQ, EXP_TYPE_CPMG_MQ, EXP_TYPE_CPMG_PROTON_MQ, EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_SQ, EXP_TYPE_CPMG_ZQ, EXP_TYPE_DESC_CPMG_DQ, EXP_TYPE_DESC_CPMG_MQ, EXP_TYPE_DESC_CPMG_PROTON_MQ, EXP_TYPE_DESC_CPMG_PROTON_SQ, EXP_TYPE_DESC_CPMG_SQ, EXP_TYPE_DESC_CPMG_ZQ, EXP_TYPE_DESC_R1RHO, EXP_TYPE_LIST, EXP_TYPE_LIST_CPMG, EXP_TYPE_LIST_R1RHO, EXP_TYPE_R1RHO, MODEL_B14, MODEL_B14_FULL, MODEL_DPL94, MODEL_LIST_MMQ, MODEL_LIST_NUMERIC_CPMG, MODEL_LIST_R1RHO_FULL, MODEL_MP05, MODEL_NS_R1RHO_2SITE, MODEL_PARAMS, MODEL_R2EFF, MODEL_TAP03, MODEL_TP02, PARAMS_R20 
  82  from stat import S_IRWXU, S_IRGRP, S_IROTH 
  83  from os import chmod, sep 
  84   
  85   
  86  # Module variables. 
  87  R20_KEY_FORMAT = "%s - %.8f MHz" 
  88   
  89   
90 -def average_intensity(spin=None, exp_type=None, frq=None, offset=None, point=None, time=None, sim_index=None, error=False):
91 """Return the average peak intensity for the spectrometer frequency, dispersion point, and relaxation time. 92 93 This is for handling replicate peak intensity data. 94 95 96 @keyword spin: The spin container to average the peak intensities for. 97 @type spin: SpinContainer instance 98 @keyword exp_type: The experiment type. 99 @type exp_type: str 100 @keyword frq: The spectrometer frequency. 101 @type frq: float 102 @keyword offset: The spin-lock or hard pulse offset. 103 @type offset: float 104 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 105 @type point: float 106 @keyword time: The relaxation time period. 107 @type time: float 108 @keyword sim_index: The simulation index. This should be None for the measured intensity values. 109 @type sim_index: None or int 110 @keyword error: A flag which if True will average and return the peak intensity errors. 111 @type error: bool 112 @return: The average peak intensity value. 113 @rtype: float 114 """ 115 116 # The keys. 117 int_keys = find_intensity_keys(exp_type=exp_type, frq=frq, offset=offset, point=point, time=time) 118 119 # Initialise. 120 intensity = 0.0 121 122 # Loop over the replicates. 123 for i in range(len(int_keys)): 124 # Simulation intensity data. 125 if sim_index != None: 126 # Error checking. 127 if not int_keys[i] in spin.peak_intensity_sim: 128 raise RelaxError("The peak intensity simulation data is missing the key '%s'." % int_keys[i]) 129 130 # Sum. 131 intensity += spin.peak_intensity_sim[int_keys[i]][sim_index] 132 133 # Error intensity data. 134 if error: 135 # Error checking. 136 if not int_keys[i] in spin.peak_intensity_err: 137 raise RelaxError("The peak intensity errors are missing the key '%s'." % int_keys[i]) 138 139 # Sum. 140 intensity += spin.peak_intensity_err[int_keys[i]]**2 141 142 # Normal intensity data. 143 else: 144 # Error checking. 145 if not int_keys[i] in spin.peak_intensity: 146 raise RelaxError("The peak intensity data is missing the key '%s'." % int_keys[i]) 147 148 # Sum. 149 intensity += spin.peak_intensity[int_keys[i]] 150 151 # Average. 152 if error: 153 intensity = sqrt(intensity / len(int_keys)) 154 else: 155 intensity /= len(int_keys) 156 157 # Return the value. 158 return intensity
159 160
161 -def calc_rotating_frame_params(spin=None, spin_id=None, fields=None, verbosity=0):
162 """Calculates and rotating frame parameters, calculated from: 163 - The spectrometer frequency. 164 - The spin-lock or hard pulse offset. 165 - The dispersion point data (the spin-lock field strength in Hz). 166 167 The return will be for each spin, 168 - Rotating frame tilt angle ( theta = arctan(w_1 / Omega) ) [rad] 169 - The average resonance offset in the rotating frame ( Domega = w_{pop_ave} - w_rf ) [rad/s] 170 - Effective field in rotating frame ( w_eff = sqrt( Omega^2 + w_1^2 ) ) [rad/s] 171 172 Calculations are mentioned in the U{manual<http://www.nmr-relax.com/manual/Dispersion_model_summary.html>} 173 174 @keyword spin: The spin system specific data container 175 @type spin: SpinContainer instance 176 @keyword spin_id: The spin ID string. 177 @type spin_id: None or str 178 @keyword fields: The spin-lock field strengths to use instead of the user loaded values - to enable interpolation. The dimensions are {Ei, Mi}. 179 @type fields: rank-2 list of floats 180 @keyword verbosity: A flag specifying to print calculations. 181 @type verbosity: int 182 @return: List with dict() of theta, Domega, w_eff and list of dict() keys. 183 @rtype: List of dict() 184 """ 185 186 # If the spin is not selected, return None 187 if not spin.select: 188 return None, None, None, None 189 190 # If the spin does not have isotope, return None 191 if not hasattr(spin, 'isotope'): 192 return None, None, None, None 193 194 # Get the field count 195 field_count = count_frq() 196 197 # Check the experiment type 198 if not has_r1rho_exp_type(): 199 raise RelaxError("The experiment type is not of R1rho type.") 200 201 # Get the spin_lock_field points 202 if fields == None: 203 spin_lock_nu1 = return_spin_lock_nu1(ref_flag=False) 204 else: 205 spin_lock_nu1 = fields 206 207 # The offset and R1 data. 208 chemical_shifts, offsets, tilt_angles, Delta_omega, w_eff = return_offset_data(spins=[spin], spin_ids=[spin_id], field_count=field_count, fields=spin_lock_nu1) 209 210 # Loop over the index of spins, then exp_type, frq, offset 211 if verbosity: 212 print("Printing the following") 213 print("exp_type spin_id frq offset{ppm} offsets[ei][si][mi][oi]{rad/s} ei mi oi si di cur_spin.chemical_shift{ppm} chemical_shifts[ei][si][mi]{rad/s} spin_lock_nu1{Hz} tilt_angles[ei][si][mi][oi]{rad} av_res_offset[ei][si][mi][oi]{rad/s}") 214 215 si = 0 216 theta_spin_dic = dict() 217 Domega_spin_dic = dict() 218 w_eff_spin_dic = dict() 219 dic_key_list = [] 220 221 for exp_type, frq, offset, ei, mi, oi in loop_exp_frq_offset(return_indices=True): 222 # Loop over the dispersion points. 223 spin_lock_fields = spin_lock_nu1[ei][mi][oi] 224 for di in range(len(spin_lock_fields)): 225 if verbosity: 226 print("%-8s %-10s %11.1f %8.4f %12.5f %i %i %i %i %i %7.3f %12.5f %12.5f %12.5f %12.5f"%(exp_type, spin_id, frq, offset, offsets[ei][si][mi][oi], ei, mi, oi, si, di, spin.chemical_shift, chemical_shifts[ei][si][mi], spin_lock_fields[di], tilt_angles[ei][si][mi][oi][di], Delta_omega[ei][si][mi][oi][di])) 227 dic_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=spin_lock_fields[di]) 228 dic_key_list.append(dic_key) 229 theta_spin_dic["%s"%(dic_key)] = tilt_angles[ei][si][mi][oi][di] 230 Domega_spin_dic["%s"%(dic_key)] = Delta_omega[ei][si][mi][oi][di] 231 w_eff_spin_dic["%s"%(dic_key)] = w_eff[ei][si][mi][oi][di] 232 233 # Return the dic and list of keys 234 return [theta_spin_dic, Domega_spin_dic, w_eff_spin_dic, dic_key_list]
235 236
237 -def count_exp():
238 """Count the number of experiments present. 239 240 @return: The experiment count 241 @rtype: int 242 """ 243 244 # The normal count variable. 245 return len(cdp.exp_type_list)
246 247
248 -def count_frq():
249 """Count the number of spectrometer frequencies present. 250 251 @return: The spectrometer frequency count 252 @rtype: int 253 """ 254 255 # Handle missing frequency data. 256 if not hasattr(cdp, 'spectrometer_frq'): 257 return 1 258 259 # The normal count variable. 260 return cdp.spectrometer_frq_count
261 262
263 -def count_relax_times(exp_type=None, frq=None, offset=None, point=None, ei=None):
264 """Count the number of relaxation times present. 265 266 @keyword exp_type: The experiment type. 267 @type exp_type: str 268 @keyword frq: The spectrometer frequency in Hz. 269 @type frq: float 270 @keyword offset: The spin-lock or hard pulse offset value in ppm. 271 @type offset: None or float 272 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 273 @type point: float 274 @keyword ei: The experiment type index. 275 @type ei: str 276 @return: The relaxation time count for the given experiment. 277 @rtype: int 278 """ 279 280 # Loop over the times. 281 count = 0 282 for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point): 283 # Find a matching experiment ID. 284 found = False 285 for id in cdp.exp_type.keys(): 286 # Skip non-matching experiments. 287 if cdp.exp_type[id] != cdp.exp_type_list[ei]: 288 continue 289 290 # Found. 291 found = True 292 break 293 294 # No data. 295 if not found: 296 continue 297 298 # A new time. 299 count += 1 300 301 # Return the count. 302 return count
303 304
305 -def count_spins(spins=None):
306 """Count the number of selected spins in the spin cluster.""" 307 308 # Count the selected spins. 309 spin_num = 0 310 for spin in spins: 311 if spin.select: 312 spin_num += 1 313 314 # Return the count. 315 return spin_num
316 317
318 -def cpmg_setup(spectrum_id=None, cpmg_frq=None, ncyc_even=True):
319 """Set the CPMG frequency associated with a given spectrum. 320 321 @keyword spectrum_id: The spectrum identification string. 322 @type spectrum_id: str 323 @keyword cpmg_frq: The frequency, in Hz, of the CPMG pulse train. 324 @type cpmg_frq: float 325 @keyword ncyc_even: A flag which if True means that the number of CPMG blocks must be even. This is pulse sequence dependant. 326 @type ncyc_even: bool 327 """ 328 329 # Test if the spectrum id exists. 330 if spectrum_id not in cdp.spectrum_ids: 331 raise RelaxNoSpectraError(spectrum_id) 332 333 # Initialise the global data structures if needed. 334 if not hasattr(cdp, 'cpmg_frqs'): 335 cdp.cpmg_frqs = {} 336 if not hasattr(cdp, 'cpmg_frqs_list'): 337 cdp.cpmg_frqs_list = [] 338 if not hasattr(cdp, 'ncyc_even'): 339 cdp.ncyc_even = {} 340 341 # Add the frequency at the correct position, converting to a float if needed. 342 if cpmg_frq == None: 343 cdp.cpmg_frqs[spectrum_id] = cpmg_frq 344 else: 345 cdp.cpmg_frqs[spectrum_id] = float(cpmg_frq) 346 347 # The unique curves for the R2eff fitting (CPMG). 348 if cdp.cpmg_frqs[spectrum_id] not in cdp.cpmg_frqs_list: 349 cdp.cpmg_frqs_list.append(cdp.cpmg_frqs[spectrum_id]) 350 351 # Sort the list (handling None for Python 3). 352 flag = False 353 if None in cdp.cpmg_frqs_list: 354 cdp.cpmg_frqs_list.pop(cdp.cpmg_frqs_list.index(None)) 355 flag = True 356 cdp.cpmg_frqs_list.sort() 357 if flag: 358 cdp.cpmg_frqs_list.insert(0, None) 359 360 # Update the exponential curve count (skipping the reference if present). 361 cdp.dispersion_points = len(cdp.cpmg_frqs_list) 362 if None in cdp.cpmg_frqs_list: 363 cdp.dispersion_points -= 1 364 365 # Add the ncyc flag. 366 cdp.ncyc_even[spectrum_id] = ncyc_even 367 368 # Printout. 369 print("The spectrum ID '%s' CPMG frequency is set to %s Hz." % (spectrum_id, cdp.cpmg_frqs[spectrum_id])) 370 print("The spectrum ID '%s' even number of CPMG blocks flag is set to %s." % (spectrum_id, cdp.ncyc_even[spectrum_id]))
371 372
373 -def decompose_r20_key(key=None):
374 """Decompose the unique R20 key into the experiment type and spectrometer frequency. 375 376 @keyword key: The unique R20 key. 377 @type key: str 378 @return: The experiment and the spectrometer frequency in Hz. 379 @rtype: str, float 380 """ 381 382 # Loop over the experiments and frequencies until the matching key is found. 383 for exp_type, frq in loop_exp_frq(): 384 if key == generate_r20_key(exp_type=exp_type, frq=frq): 385 return exp_type, frq
386 387
388 -def find_intensity_keys(exp_type=None, frq=None, offset=None, point=None, time=None, raise_error=True):
389 """Return the key corresponding to the spectrometer frequency, dispersion point, and relaxation time. 390 391 @keyword exp_type: The experiment type. 392 @type exp_type: str 393 @keyword frq: The spectrometer frequency. 394 @type frq: float 395 @keyword offset: The optional offset value for off-resonance R1rho-type data. 396 @type offset: None or float 397 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 398 @type point: float 399 @keyword time: The relaxation time period. 400 @type time: float 401 @keyword raise_error: A flag which if True will cause a RelaxError to be raised if no keys could be found. 402 @type raise_error: bool 403 @return: The keys corresponding to the spectrometer frequency, dispersion point, and relaxation time. 404 @rtype: list of str 405 """ 406 407 # Check. 408 if exp_type == None: 409 raise RelaxError("The experiment type has not been supplied.") 410 411 # Catch NaNs. 412 if isNaN(point): 413 point = None 414 415 # The dispersion data. 416 if exp_type in EXP_TYPE_LIST_CPMG: 417 disp_data = cdp.cpmg_frqs 418 else: 419 disp_data = cdp.spin_lock_nu1 420 421 # Loop over all spectrum IDs, returning the matching ID. 422 ids = [] 423 for id in cdp.exp_type.keys(): 424 # Skip non-matching experiments. 425 if cdp.exp_type[id] != exp_type: 426 continue 427 428 # Skip non-matching spectrometer frequencies. 429 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 430 continue 431 432 # Skip non-matching offsets. 433 if offset != None and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 434 continue 435 436 # Skip non-matching dispersion points. 437 if disp_data[id] != point: 438 continue 439 440 # The reference point, so checking the time is pointless (and can fail as specifying the time should not be necessary). 441 if point == None or isNaN(point): 442 ids.append(id) 443 444 # Matching time. 445 elif time == None: 446 ids.append(id) 447 elif cdp.relax_times[id] == time: 448 ids.append(id) 449 450 # Check for missing IDs. 451 if raise_error and len(ids) == 0: 452 if point == None or isNaN(point): 453 raise RelaxError("No reference intensity data could be found corresponding to the spectrometer frequency of %s MHz and relaxation time of %s s." % (frq*1e-6, time)) 454 else: 455 raise RelaxError("No intensity data could be found corresponding to the spectrometer frequency of %s MHz, dispersion point of %s and relaxation time of %s s." % (frq*1e-6, point, time)) 456 457 # Return the IDs. 458 return ids
459 460
461 -def generate_r20_key(exp_type=None, frq=None):
462 """Generate the unique R20 key from the experiment type and spectrometer frequency. 463 464 @keyword exp_type: The experiment type. 465 @type exp_type: str 466 @keyword frq: The spectrometer frequency in Hz. 467 @type frq: float 468 @return: The unique R20 key. 469 @rtype: str 470 """ 471 472 # Generate and return the unique key. 473 return R20_KEY_FORMAT % (exp_type, frq/1e6)
474 475
476 -def get_curve_type(id=None):
477 """Return the unique curve type. 478 479 @keyword id: The spectrum ID. If not supplied, then all data will be assumed. 480 @type id: str 481 @return: The curve type - either 'fixed time' or 'exponential'. 482 @rtype: str 483 """ 484 485 # All data. 486 if id == None: 487 # Data checks. 488 check_mixed_curve_types() 489 490 # Determine the curve type. 491 curve_type = 'fixed time' 492 if has_exponential_exp_type(): 493 curve_type = 'exponential' 494 495 # A specific ID. 496 else: 497 # Determine the curve type. 498 curve_type = 'exponential' 499 exp_type = cdp.exp_type[id] 500 frq = cdp.spectrometer_frq[id] 501 if count_relax_times(exp_type = exp_type, frq = frq, ei = cdp.exp_type_list.index(cdp.exp_type[id])) == 1: 502 curve_type = 'fixed time' 503 504 # Return the type. 505 return curve_type
506 507
508 -def get_exp_type(id=None):
509 """Return the experiment type for the given ID. 510 511 @keyword id: The spectrum ID. 512 @type id: str 513 @return: The experiment type corresponding to the ID. 514 @rtype: str 515 """ 516 517 # Data check. 518 check_exp_type(id=id) 519 520 # Return the type. 521 return cdp.exp_type[id]
522 523
524 -def has_cpmg_exp_type():
525 """Determine if the current data pipe contains CPMG experiment types. 526 527 @return: True if CPMG experiment types exist, False otherwise. 528 @rtype: bool 529 """ 530 531 # No experiment types set. 532 if not hasattr(cdp, 'exp_type'): 533 return False 534 535 # Loop over all experiment types. 536 for exp_type in cdp.exp_type_list: 537 if exp_type in EXP_TYPE_LIST_CPMG: 538 return True 539 540 # No CPMG experiment types. 541 return False
542 543
544 -def has_disp_data(spins=None, spin_ids=None, exp_type=None, frq=None, offset=None, point=None):
545 """Determine if dispersion data exists for the given data combination. 546 547 @keyword spins: The list of spin containers in the cluster. 548 @type spins: list of SpinContainer instances 549 @keyword spin_ids: The list of spin IDs for the cluster. 550 @type spin_ids: list of str 551 @keyword exp_type: The experiment type. 552 @type exp_type: str 553 @keyword frq: The spectrometer frequency. 554 @type frq: float 555 @keyword offset: For R1rho-type data, the spin-lock offset value in ppm. 556 @type offset: None or float 557 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 558 @type point: float 559 @return: True if dispersion data exists, False otherwise. 560 @rtype: bool 561 """ 562 563 # Skip reference spectra. 564 if point == None: 565 return False 566 567 # The key. 568 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 569 570 # Loop over the spins. 571 for si in range(len(spins)): 572 # Alias the correct spin. 573 current_spin = spins[si] 574 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 575 current_spin = return_attached_protons(spin_ids[si])[0] 576 577 # The data is present. 578 if key in current_spin.r2eff.keys(): 579 return True 580 581 # No data. 582 return False
583 584
585 -def has_exponential_exp_type():
586 """Determine if the current data pipe contains exponential curves. 587 588 @return: True if spectral data for exponential curves exist, False otherwise. 589 @rtype: bool 590 """ 591 592 # No experiment types set. 593 if not hasattr(cdp, 'exp_type'): 594 return False 595 596 # Loop over all spectra IDs. 597 for id in cdp.exp_type.keys(): 598 if get_curve_type(id) == 'exponential': 599 return True 600 601 # No exponential data. 602 return False
603 604
605 -def has_fixed_time_exp_type():
606 """Determine if the current data pipe contains fixed time data. 607 608 @return: True if spectral data for fixed time data exists, False otherwise. 609 @rtype: bool 610 """ 611 612 # No experiment types set. 613 if not hasattr(cdp, 'exp_type'): 614 return False 615 616 # Loop over all experiment types. 617 for id in cdp.exp_type.keys(): 618 if get_curve_type(id) == 'fixed time': 619 return True 620 621 # No exponential data. 622 return False
623 624
625 -def has_proton_mmq_cpmg():
626 """Determine if the current data pipe contains either proton SQ or MQ (MMQ) CPMG data. 627 628 This is only for the MMQ models. 629 630 631 @return: True if either proton SQ or MQ CPMG data exists, False otherwise. 632 @rtype: bool 633 """ 634 635 # 1H MMQ data exists. 636 if has_proton_sq_cpmg(): 637 return True 638 if has_proton_mq_cpmg(): 639 return True 640 641 # No 1H MMQ CPMG data. 642 return False
643 644
645 -def has_proton_mq_cpmg():
646 """Determine if the current data pipe contains proton MQ CPMG data. 647 648 This is only for the MMQ models. 649 650 651 @return: True if proton MQ CPMG data exists, False otherwise. 652 @rtype: bool 653 """ 654 655 # Proton MQ CPMG data is present. 656 if EXP_TYPE_CPMG_PROTON_MQ in cdp.exp_type_list: 657 return True 658 659 # No 1H MQ CPMG data. 660 return False
661 662
663 -def has_proton_sq_cpmg():
664 """Determine if the current data pipe contains proton SQ CPMG data. 665 666 This is only for the MMQ models. 667 668 669 @return: True if proton SQ CPMG data exists, False otherwise. 670 @rtype: bool 671 """ 672 673 # Proton SQ CPMG data is present. 674 if EXP_TYPE_CPMG_PROTON_SQ in cdp.exp_type_list: 675 return True 676 677 # No 1H SQ CPMG data. 678 return False
679 680
681 -def has_r1rho_exp_type():
682 """Determine if the current data pipe contains R1rho experiment types. 683 684 @return: True if R1rho experiment types exist, False otherwise. 685 @rtype: bool 686 """ 687 688 # No experiment types set. 689 if not hasattr(cdp, 'exp_type'): 690 return False 691 692 # Loop over all experiment types. 693 for exp_type in cdp.exp_type_list: 694 if exp_type in EXP_TYPE_LIST_R1RHO: 695 return True 696 697 # No CPMG experiment types. 698 return False
699 700
701 -def insignificance(level=0.0):
702 """Deselect all spins with insignificant dispersion profiles. 703 704 @keyword level: The R2eff/R1rho value in rad/s by which to judge insignificance. If the maximum difference between two points on all dispersion curves for a spin is less than this value, that spin will be deselected. 705 @type level: float 706 """ 707 708 # Nothing to do. 709 if level == 0.0: 710 return 711 712 # Number of spectrometer fields. 713 fields = [None] 714 field_count = 1 715 if hasattr(cdp, 'spectrometer_frq_count'): 716 fields = cdp.spectrometer_frq_list 717 field_count = cdp.spectrometer_frq_count 718 719 # Loop over all spins. 720 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 721 # Nothing to do (the R2eff model has no dispersion curves). 722 if spin.model == 'R2eff': 723 continue 724 725 # Get all the data. 726 try: 727 values, errors, missing, frqs, frqs_H, exp_types, relax_times = return_r2eff_arrays(spins=[spin], spin_ids=[spin_id], fields=fields, field_count=field_count) 728 729 # No R2eff data, so skip the rest. 730 except RelaxError: 731 continue 732 733 # The flag. 734 desel = True 735 736 # Loop over the experiments, magnetic fields, and offsets. 737 max_diff = 0.0 738 for exp_type, frq, offset, ei, mi, oi in loop_exp_frq_offset(return_indices=True): 739 # No data. 740 if not len(values[ei][0][mi][oi]): 741 continue 742 743 # The difference. 744 diff = values[ei][0][mi][oi].max() - values[ei][0][mi][oi].min() 745 746 # Significance detected. 747 if diff > level: 748 desel = False 749 750 # Store the maximum for the deselection printout. 751 if diff > max_diff: 752 max_diff = diff 753 754 # Deselect the spin. 755 if desel: 756 # Printout. 757 print("Deselecting spin '%s', the maximum dispersion curve difference for all curves is %s rad/s." % (spin_id, max_diff)) 758 759 # Deselection. 760 desel_spin(spin_id)
761 762
763 -def is_cpmg_exp_type(id=None):
764 """Determine if the given spectrum ID corresponds to a CPMG experiment type. 765 766 @keyword id: The spectrum ID string. 767 @type id: str 768 @return: True if the spectrum ID corresponds to a CPMG experiment type, False otherwise. 769 @rtype: bool 770 """ 771 772 # No experiment type set. 773 if not hasattr(cdp, 'exp_type') or id not in cdp.exp_type: 774 return False 775 776 # CPMG experiment type. 777 if cdp.exp_type[id] in EXP_TYPE_LIST_CPMG: 778 return True 779 780 # Not a CPMG experiment type. 781 return False
782 783
784 -def is_r1rho_exp_type(id=None):
785 """Determine if the given spectrum ID corresponds to a R1rho experiment type. 786 787 @keyword id: The spectrum ID string. 788 @type id: str 789 @return: True if the spectrum ID corresponds to a R1rho experiment type, False otherwise. 790 @rtype: bool 791 """ 792 793 # No experiment type set. 794 if not hasattr(cdp, 'exp_type') or id not in cdp.exp_type: 795 return False 796 797 # R1rho experiment type. 798 if cdp.exp_type[id] in EXP_TYPE_LIST_R1RHO: 799 return True 800 801 # Not a R1rho experiment type. 802 return False
803 804
805 -def loop_cluster(skip_desel=True):
806 """Loop over the spin groupings for one model applied to multiple spins. 807 808 @keyword skip_desel: A flag which if True will cause deselected spins or spin clusters to be skipped. 809 @type skip_desel: bool 810 @return: The list of spin IDs per block will be yielded. 811 @rtype: list of str 812 """ 813 814 # No clustering, so loop over the sequence. 815 if not hasattr(cdp, 'clustering'): 816 for spin, spin_id in spin_loop(return_id=True, skip_desel=skip_desel): 817 # Skip protons for MMQ data. 818 if hasattr(spin, 'model') and spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 819 continue 820 821 # Return the spin ID as a list. 822 yield [spin_id] 823 824 # Loop over the clustering. 825 else: 826 # The clusters. 827 for key in cdp.clustering.keys(): 828 # Skip the free spins. 829 if key == 'free spins': 830 continue 831 832 # Create the spin ID lists. 833 spin_id_list = [] 834 for spin_id in cdp.clustering[key]: 835 # Skip deselected spins. 836 spin = return_spin(spin_id) 837 if skip_desel and not spin.select: 838 continue 839 840 # Skip protons for MMQ data. 841 if hasattr(spin, 'model') and spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 842 continue 843 844 # Add the spin ID. 845 spin_id_list.append(spin_id) 846 847 # Yield the cluster. 848 yield spin_id_list 849 850 # The free spins. 851 for spin_id in cdp.clustering['free spins']: 852 # Skip deselected spins. 853 spin = return_spin(spin_id) 854 if skip_desel and not spin.select: 855 continue 856 857 # Skip protons for MMQ data. 858 if hasattr(spin, 'model') and spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 859 continue 860 861 # Yield each spin individually. 862 yield [spin_id]
863 864
865 -def loop_exp(return_indices=False):
866 """Generator method for looping over all experiment types. 867 868 @keyword return_indices: A flag which if True will cause the experiment type index to be returned as well. 869 @type return_indices: bool 870 @return: The experiment type, and the index if asked. 871 @rtype: str, (int) 872 """ 873 874 # Initialise the index. 875 ei = -1 876 877 # Loop over the experiment types. 878 for exp_type in cdp.exp_type_list: 879 # Increment the index. 880 ei += 1 881 882 # Yield each unique experiment type. 883 if return_indices: 884 yield exp_type, ei 885 else: 886 yield exp_type
887 888
889 -def loop_exp_frq(return_indices=False):
890 """Generator method for looping over the exp and frq data. 891 892 These are the experiment types and spectrometer frequencies. 893 894 895 @keyword return_indices: A flag which if True will cause the experiment type and spectrometer frequency indices to be returned as well. 896 @type return_indices: bool 897 @return: The experiment type and spectrometer frequency in Hz, and the indices if asked. 898 @rtype: str, float, (int, int) 899 """ 900 901 # First loop over the experiment types. 902 for exp_type, ei in loop_exp(return_indices=True): 903 # Then loop over the spectrometer frequencies. 904 for frq, mi in loop_frq(return_indices=True): 905 # Yield the data. 906 if return_indices: 907 yield exp_type, frq, ei, mi 908 else: 909 yield exp_type, frq
910 911
912 -def loop_exp_frq_offset(return_indices=False):
913 """Generator method for looping over the exp, frq, and offset data. 914 915 These are the experiment types, spectrometer frequencies and spin-lock offset data. 916 917 918 @keyword return_indices: A flag which if True will cause the experiment type, spectrometer frequency and spin-lock offset indices to be returned as well. 919 @type return_indices: bool 920 @return: The experiment type, spectrometer frequency in Hz and spin-lock offset data, and the indices if asked. 921 @rtype: str, float, float, (int, int, int) 922 """ 923 924 # First loop over the experiment types. 925 for exp_type, ei in loop_exp(return_indices=True): 926 # Then loop over the spectrometer frequencies. 927 for frq, mi in loop_frq(return_indices=True): 928 # And finally the offset data. 929 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 930 # Yield the data. 931 if return_indices: 932 yield exp_type, frq, offset, ei, mi, oi 933 else: 934 yield exp_type, frq, offset
935 936
937 -def loop_exp_frq_offset_point(return_indices=False):
938 """Generator method for looping over the exp, frq, offset, and point data. 939 940 These are the experiment types, spectrometer frequencies, spin-lock offset data, and dispersion points. 941 942 943 @keyword return_indices: A flag which if True will cause the experiment type, spectrometer frequency, spin-lock offset and dispersion point indices to be returned as well. 944 @type return_indices: bool 945 @return: The experiment type, spectrometer frequency in Hz, spin-lock offset data and dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the indices if asked. 946 @rtype: str, float, float, float, (int, int, int, int) 947 """ 948 949 # First loop over the experiment types. 950 for exp_type, ei in loop_exp(return_indices=True): 951 # Then loop over the spectrometer frequencies. 952 for frq, mi in loop_frq(return_indices=True): 953 # Then loop over the offset data. 954 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 955 # And finally the dispersion points. 956 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 957 # Yield the data. 958 if return_indices: 959 yield exp_type, frq, offset, point, ei, mi, oi, di 960 else: 961 yield exp_type, frq, offset, point
962 963
964 -def loop_exp_frq_offset_point_time(return_indices=False):
965 """Generator method for looping over the exp, frq, offset, and point data. 966 967 These are the experiment types, spectrometer frequencies, spin-lock offset data, and dispersion points. 968 969 970 @keyword return_indices: A flag which if True will cause the experiment type, spectrometer frequency, spin-lock offset and dispersion point indices to be returned as well. 971 @type return_indices: bool 972 @return: The experiment type, spectrometer frequency in Hz, spin-lock offset data and dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the indices if asked. 973 @rtype: str, float, float, float, (int, int, int, int) 974 """ 975 976 # First loop over the experiment types. 977 for exp_type, ei in loop_exp(return_indices=True): 978 # Then loop over the spectrometer frequencies. 979 for frq, mi in loop_frq(return_indices=True): 980 # Then loop over the offset data. 981 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 982 # Then the dispersion points. 983 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 984 # Finally the relaxation times. 985 for time, ti in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point, return_indices=True): 986 # Yield the data. 987 if return_indices: 988 yield exp_type, frq, offset, point, time, ei, mi, oi, di, ti 989 else: 990 yield exp_type, frq, offset, point, time
991 992
993 -def loop_exp_frq_point(return_indices=False):
994 """Generator method for looping over the exp, frq, and point data. 995 996 These are the experiment types, spectrometer frequencies and dispersion points. 997 998 999 @keyword return_indices: A flag which if True will cause the experiment type, spectrometer frequency and dispersion point indices to be returned as well. 1000 @type return_indices: bool 1001 @return: The experiment type, spectrometer frequency in Hz and dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the indices if asked. 1002 @rtype: str, float, float, (int, int, int) 1003 """ 1004 1005 # First loop over the experiment types. 1006 for exp_type, ei in loop_exp(return_indices=True): 1007 # Then loop over the spectrometer frequencies. 1008 for frq, mi in loop_frq(return_indices=True): 1009 # And finally the dispersion points. 1010 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=0.0, return_indices=True): 1011 # Yield the data. 1012 if return_indices: 1013 yield exp_type, frq, point, ei, mi, di 1014 else: 1015 yield exp_type, frq, point
1016 1017
1018 -def loop_exp_frq_point_time(return_indices=False):
1019 """Generator method for looping over the exp, frq, point, and time data. 1020 1021 These are the experiment types, spectrometer frequencies, dispersion points, and relaxation times. 1022 1023 1024 @keyword return_indices: A flag which if True will cause the experiment type, spectrometer frequency, dispersion point, and relaxation time indices to be returned as well. 1025 @type return_indices: bool 1026 @return: The experiment type, spectrometer frequency in Hz, dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), the relaxation time, and the indices if asked. 1027 @rtype: str, float, float, float, (int, int, int, int) 1028 """ 1029 1030 # First loop over the experiment types. 1031 for exp_type, ei in loop_exp(return_indices=True): 1032 # Then the spectrometer frequencies. 1033 for frq, mi in loop_frq(return_indices=True): 1034 # Then the dispersion points. 1035 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=0.0, return_indices=True): 1036 # Finally the relaxation times. 1037 for time, ti in loop_time(exp_type=exp_type, frq=frq, point=point, return_indices=True): 1038 # Yield all data. 1039 if return_indices: 1040 yield exp_type, frq, point, time, ei, mi, di, ti 1041 else: 1042 yield exp_type, frq, point, time
1043 1044
1045 -def loop_frq(return_indices=False):
1046 """Generator method for looping over all spectrometer frequencies. 1047 1048 @keyword return_indices: A flag which if True will cause the spectrometer frequency index to be returned as well. 1049 @type return_indices: bool 1050 @return: The spectrometer frequency in Hz, and the index if asked. 1051 @rtype: float, (int) 1052 """ 1053 1054 # Handle missing frequency data. 1055 frqs = [None] 1056 if hasattr(cdp, 'spectrometer_frq_list'): 1057 frqs = cdp.spectrometer_frq_list 1058 1059 # Initialise the index. 1060 mi = -1 1061 1062 # Loop over the spectrometer frequencies. 1063 for field in frqs: 1064 # Increment the index. 1065 mi += 1 1066 1067 # Yield each unique spectrometer field strength. 1068 if return_indices: 1069 yield field, mi 1070 else: 1071 yield field
1072 1073
1074 -def loop_frq_offset(exp_type=None, return_indices=False):
1075 """Generator method for looping over the spectrometer frequencies and dispersion points. 1076 1077 @keyword exp_type: The experiment type. 1078 @type exp_type: str 1079 @keyword return_indices: A flag which if True will cause the spectrometer frequency and dispersion point indices to be returned as well. 1080 @type return_indices: bool 1081 @return: The spectrometer frequency in Hz and dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 1082 @rtype: float, float, (int, int) 1083 """ 1084 1085 # Checks. 1086 if exp_type == None: 1087 raise RelaxError("The experiment type must be supplied.") 1088 1089 # First loop over the spectrometer frequencies. 1090 for frq, mi in loop_frq(return_indices=True): 1091 # Then the offset points. 1092 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 1093 # Yield the data. 1094 if return_indices: 1095 yield frq, offset, mi, oi 1096 else: 1097 yield frq, offset
1098 1099
1100 -def loop_frq_point(exp_type=None, return_indices=False):
1101 """Generator method for looping over the spectrometer frequencies and dispersion points. 1102 1103 @keyword exp_type: The experiment type. 1104 @type exp_type: str 1105 @keyword return_indices: A flag which if True will cause the spectrometer frequency and dispersion point indices to be returned as well. 1106 @type return_indices: bool 1107 @return: The spectrometer frequency in Hz and dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 1108 @rtype: float, float, (int, int) 1109 """ 1110 1111 # First loop over the spectrometer frequencies. 1112 for frq, mi in loop_frq(return_indices=True): 1113 # Then the dispersion points. 1114 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=0.0, return_indices=True): 1115 # Yield the data. 1116 if return_indices: 1117 yield frq, point, mi, di 1118 else: 1119 yield frq, point
1120 1121
1122 -def loop_frq_offset_point_key(exp_type=None):
1123 """Generator method for looping over the spectrometer frequencies, spin-lock offsets and dispersion points (returning the key). 1124 1125 @keyword exp_type: The experiment type. 1126 @type exp_type: str 1127 @return: The key corresponding to the spectrometer frequency, offset and dispersion point. 1128 @rtype: str 1129 """ 1130 1131 # First loop over the spectrometer frequencies, offsets and dispersion points. 1132 for frq, offset, point in loop_frq_offset_point(return_indices=True): 1133 # Generate and yield the key. 1134 yield return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point)
1135 1136
1137 -def loop_frq_point_time(exp_type=None, return_indices=False):
1138 """Generator method for looping over the spectrometer frequencies, dispersion points, and relaxation times. 1139 1140 @keyword exp_type: The experiment type. 1141 @type exp_type: str 1142 @keyword return_indices: A flag which if True will cause the spectrometer frequency, dispersion point, and relaxation time indices to be returned as well. 1143 @type return_indices: bool 1144 @return: The spectrometer frequency in Hz, dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the relaxation time. 1145 @rtype: float, float, float 1146 """ 1147 1148 # First loop over the spectrometer frequencies. 1149 for frq, mi in loop_frq(return_indices=True): 1150 # Then the dispersion points. 1151 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=0.0, return_indices=True): 1152 # Finally the relaxation times. 1153 for time, ti in loop_time(exp_type=exp_type, frq=frq, point=point, return_indices=True): 1154 # Yield all data. 1155 if return_indices: 1156 yield frq, point, time, mi, di, ti 1157 else: 1158 yield frq, point, time
1159 1160
1161 -def loop_offset(exp_type=None, frq=None, return_indices=False):
1162 """Generator method for looping over the spin-lock offset values. 1163 1164 @keyword exp_type: The experiment type. 1165 @type exp_type: str 1166 @keyword frq: The spectrometer frequency. 1167 @type frq: float 1168 @keyword return_indices: A flag which if True will cause the offset index to be returned as well. 1169 @type return_indices: bool 1170 @return: The spin-lock offset value and the index if asked. 1171 @rtype: float, (int) 1172 """ 1173 1174 # Checks. 1175 if exp_type == None: 1176 raise RelaxError("The experiment type must be supplied.") 1177 if frq == None: 1178 raise RelaxError("The spectrometer frequency must be supplied.") 1179 1180 # Initialise the index. 1181 oi = -1 1182 1183 # CPMG-type data. 1184 if exp_type in EXP_TYPE_LIST_CPMG: 1185 # Yield a single set of dummy values until hard pulse offset handling is implemented. 1186 yield 0.0, 0 1187 1188 # R1rho-type data. 1189 if exp_type in EXP_TYPE_LIST_R1RHO: 1190 # No offsets set. 1191 if not hasattr(cdp, 'spin_lock_offset_list'): 1192 yield 0.0, 0 1193 1194 # Loop over the offset data. 1195 else: 1196 for offset in cdp.spin_lock_offset_list: 1197 # Find a matching experiment ID. 1198 found = False 1199 for id in cdp.exp_type.keys(): 1200 # Skip non-matching experiments. 1201 if cdp.exp_type[id] != exp_type: 1202 continue 1203 1204 # Skip non-matching spectrometer frequencies. 1205 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 1206 continue 1207 1208 # Skip non-matching offsets. 1209 if cdp.spin_lock_offset[id] != offset: 1210 continue 1211 1212 # Found. 1213 found = True 1214 break 1215 1216 # No data. 1217 if not found: 1218 continue 1219 1220 # Increment the index. 1221 oi += 1 1222 1223 # Yield each unique field strength or frequency. 1224 if return_indices: 1225 yield offset, oi 1226 else: 1227 yield offset
1228 1229
1230 -def loop_offset_point(exp_type=None, frq=None, skip_ref=True, return_indices=False):
1231 """Generator method for looping over the offsets and dispersion points. 1232 1233 @keyword exp_type: The experiment type. 1234 @type exp_type: str 1235 @keyword frq: The spectrometer frequency. 1236 @type frq: float 1237 @keyword skip_ref: A flag which if True will cause the reference point to be skipped. 1238 @type skip_ref: bool 1239 @keyword return_indices: A flag which if True will cause the offset and dispersion point indices to be returned as well. 1240 @type return_indices: bool 1241 @return: The offsets in ppm and the dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the index if asked. 1242 @rtype: float, float, (int, int) 1243 """ 1244 1245 # First loop over the offsets. 1246 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 1247 # Then the dispersion points. 1248 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 1249 # Yield all data. 1250 if return_indices: 1251 yield offset, point, oi, di 1252 else: 1253 yield offset, point
1254 1255
1256 -def loop_point(exp_type=None, frq=None, offset=None, time=None, skip_ref=True, return_indices=False):
1257 """Generator method for looping over the dispersion points. 1258 1259 @keyword exp_type: The experiment type. 1260 @type exp_type: str 1261 @keyword frq: The spectrometer frequency. 1262 @type frq: float 1263 @keyword offset: The spin-lock or hard pulse offset value in ppm. 1264 @type offset: None or float 1265 @keyword time: The relaxation time period. 1266 @type time: float 1267 @keyword skip_ref: A flag which if True will cause the reference point to be skipped. 1268 @type skip_ref: bool 1269 @keyword return_indices: A flag which if True will cause the experiment type index to be returned as well. 1270 @type return_indices: bool 1271 @return: Dispersion point data for the given indices (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz), and the index if asked. 1272 @rtype: float, (int) 1273 """ 1274 1275 # Checks. 1276 if exp_type == None: 1277 raise RelaxError("The experiment type must be supplied.") 1278 if frq == None: 1279 raise RelaxError("The spectrometer frequency must be supplied.") 1280 if offset == None: 1281 raise RelaxError("The offset must be supplied.") 1282 1283 # Assemble the dispersion data. 1284 ref_flag = not skip_ref 1285 if exp_type in EXP_TYPE_LIST_CPMG: 1286 fields = return_cpmg_frqs_single(exp_type=exp_type, frq=frq, offset=offset, time=time, ref_flag=ref_flag) 1287 elif exp_type in EXP_TYPE_LIST_R1RHO: 1288 fields = return_spin_lock_nu1_single(exp_type=exp_type, frq=frq, offset=offset, ref_flag=ref_flag) 1289 else: 1290 raise RelaxError("The experiment type '%s' is unknown." % exp_type) 1291 1292 # Initialise the index. 1293 di = -1 1294 1295 # Loop over the field data. 1296 for field in fields: 1297 # Skip the reference (the None value will be converted to the numpy nan value). 1298 if skip_ref and isNaN(field): 1299 continue 1300 1301 # Increment the index. 1302 di += 1 1303 1304 # Yield each unique field strength or frequency. 1305 if return_indices: 1306 yield field, di 1307 else: 1308 yield field
1309 1310
1311 -def loop_spectrum_ids(exp_type=None, frq=None, offset=None, point=None, time=None):
1312 """Generator method for selectively looping over the spectrum IDs. 1313 1314 @keyword exp_type: The experiment type. 1315 @type exp_type: str 1316 @keyword frq: The spectrometer frequency. 1317 @type frq: float 1318 @keyword offset: For R1rho-type data, the spin-lock offset value in ppm. 1319 @type offset: None or float 1320 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 1321 @type point: float 1322 @keyword time: The relaxation time period. 1323 @type time: float 1324 @return: The spectrum ID. 1325 @rtype: str 1326 """ 1327 1328 # Loop over all spectrum IDs. 1329 for id in cdp.spectrum_ids: 1330 # Experiment type filter. 1331 if exp_type != None: 1332 # No experiment type set. 1333 if not hasattr(cdp, 'exp_type') or id not in cdp.exp_type: 1334 continue 1335 1336 # No match. 1337 if cdp.exp_type[id] != exp_type: 1338 continue 1339 1340 # The frequency filter. 1341 if frq != None: 1342 # No frequency data set. 1343 if not hasattr(cdp, 'spectrometer_frq') or id not in cdp.spectrometer_frq: 1344 continue 1345 1346 # No match. 1347 if cdp.spectrometer_frq[id] != frq: 1348 continue 1349 1350 # The dispersion point filter. 1351 if point != None: 1352 # No experiment type set. 1353 if not hasattr(cdp, 'exp_type') or id not in cdp.exp_type: 1354 continue 1355 1356 # The experiment type. 1357 exp_type = cdp.exp_type[id] 1358 1359 # The CPMG dispersion data. 1360 if exp_type in EXP_TYPE_LIST_CPMG: 1361 # No dispersion point data set. 1362 if not hasattr(cdp, 'cpmg_frqs') or id not in cdp.cpmg_frqs: 1363 continue 1364 1365 # Alias the structure 1366 disp_data = cdp.cpmg_frqs 1367 1368 # The R1rho dispersion data. 1369 else: 1370 # No dispersion point data set. 1371 if not hasattr(cdp, 'spin_lock_nu1') or id not in cdp.spin_lock_nu1: 1372 continue 1373 1374 # Alias the structure 1375 disp_data = cdp.spin_lock_nu1 1376 1377 # No match. 1378 if disp_data[id] != point: 1379 continue 1380 1381 # The time filter. 1382 if time != None: 1383 # No time data set. 1384 if not hasattr(cdp, 'relax_times') or id not in cdp.relax_times: 1385 continue 1386 1387 # No match. 1388 if cdp.relax_times[id] != time: 1389 continue 1390 1391 # Yield the Id. 1392 yield id
1393 1394
1395 -def loop_time(exp_type=None, frq=None, offset=None, point=None, return_indices=False):
1396 """Generator method for looping over the relaxation times. 1397 1398 @keyword exp_type: The experiment type. 1399 @type exp_type: str 1400 @keyword frq: The spectrometer frequency in Hz. 1401 @type frq: float 1402 @keyword offset: The spin-lock or hard pulse offset value in ppm. 1403 @type offset: None or float 1404 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 1405 @type point: float 1406 @keyword return_indices: A flag which if True will cause the relaxation time index to be returned as well. 1407 @type return_indices: bool 1408 @return: The relaxation time. 1409 @rtype: float 1410 """ 1411 1412 # Initialise the index. 1413 ti = -1 1414 1415 # Loop over the time points. 1416 if hasattr(cdp, 'relax_time_list'): 1417 for time in cdp.relax_time_list: 1418 # Find a matching experiment ID. 1419 found = False 1420 for id in cdp.exp_type.keys(): 1421 # Skip non-matching experiments. 1422 if exp_type != None and cdp.exp_type[id] != exp_type: 1423 continue 1424 1425 # Skip non-matching spectrometer frequencies. 1426 if frq != None and hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 1427 continue 1428 1429 # Skip non-matching offsets. 1430 if offset != None and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 1431 continue 1432 1433 # The dispersion point filter. 1434 if point != None: 1435 # No experiment type set. 1436 if not hasattr(cdp, 'exp_type') or id not in cdp.exp_type: 1437 continue 1438 1439 # The experiment type. 1440 exp_type = cdp.exp_type[id] 1441 1442 # The CPMG dispersion data. 1443 if exp_type in EXP_TYPE_LIST_CPMG: 1444 # No dispersion point data set. 1445 if hasattr(cdp, 'cpmg_frqs') and cdp.cpmg_frqs[id] != point: 1446 continue 1447 1448 # The R1rho data 1449 if exp_type in EXP_TYPE_R1RHO: 1450 if hasattr(cdp, 'spin_lock_nu1') and cdp.spin_lock_nu1[id] != point: 1451 continue 1452 1453 if time != cdp.relax_times[id]: 1454 continue 1455 1456 # Found. 1457 found = True 1458 break 1459 1460 # No data. 1461 if not found: 1462 continue 1463 1464 # Increment the index. 1465 ti += 1 1466 1467 # Yield each unique relaxation time. 1468 if return_indices: 1469 yield time, ti 1470 else: 1471 yield time 1472 1473 # No times set. 1474 else: 1475 if return_indices: 1476 yield None, None 1477 else: 1478 yield None
1479 1480
1481 -def num_exp_types():
1482 """Count the number of experiment types present. 1483 1484 @return: The number of experiment types. 1485 @rtype: int 1486 """ 1487 1488 # The count. 1489 count = len(cdp.exp_type_list) 1490 1491 # Return the count. 1492 return count
1493 1494
1495 -def pack_back_calc_r2eff(spin=None, spin_id=None, si=None, back_calc=None, proton_mmq_flag=False):
1496 """Store the back calculated R2eff data for the given spin. 1497 1498 @keyword spin: The spin data container to store the data in. 1499 @type spin: SpinContainer instance 1500 @keyword spin_id: The spin ID string. 1501 @type spin_id: str 1502 @keyword si: The index of the given spin in the cluster. 1503 @type si: int 1504 @keyword back_calc: The back calculated data. The first index corresponds to the experiment type, the second is the spin of the cluster, the third is the magnetic field strength, and the fourth is the dispersion point. 1505 @type back_calc: list of lists of lists of lists of float 1506 @keyword proton_mmq_flag: The flag specifying if proton SQ or MQ CPMG data exists for the spin. 1507 @type proton_mmq_flag: bool 1508 """ 1509 1510 # Get the attached proton. 1511 proton = None 1512 if proton_mmq_flag: 1513 proton = return_attached_protons(spin_id)[0] 1514 1515 # Loop over the R2eff data. 1516 for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True): 1517 # The R2eff key. 1518 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 1519 1520 # Alias the correct spin. 1521 current_spin = spin 1522 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 1523 current_spin = proton 1524 1525 # Missing data. 1526 if not hasattr(current_spin, 'r2eff') or key not in current_spin.r2eff.keys(): 1527 continue 1528 1529 # Initialise. 1530 if not hasattr(current_spin, 'r2eff_bc'): 1531 current_spin.r2eff_bc = {} 1532 1533 # Store the back-calculated data. 1534 current_spin.r2eff_bc[key] = back_calc[ei][si][mi][oi][di]
1535 1536
1537 -def plot_disp_curves(dir=None, num_points=1000, extend=500.0, force=False):
1538 """Custom 2D Grace plotting function for the dispersion curves. 1539 1540 One file will be created per spin system. 1541 1542 A python "grace to PNG/EPS/SVG..." conversion script is created at the end 1543 1544 @keyword dir: The optional directory to place the file into. 1545 @type dir: str 1546 @keyword num_points: The number of points to generate the interpolated fitted curves with. 1547 @type num_points: int 1548 @keyword extend: How far to extend the interpolated fitted curves to (in Hz). 1549 @type extend: float 1550 @param force: Boolean argument which if True causes the files to be overwritten if it already exists. 1551 @type force: bool 1552 """ 1553 1554 # Checks. 1555 pipes.test() 1556 check_mol_res_spin_data() 1557 1558 # 1H MMQ flag. 1559 proton_mmq_flag = has_proton_mmq_cpmg() 1560 1561 # Default hardcoded colours (one colour for each magnetic field strength). 1562 colour_order = [4, 15, 2, 13, 11, 1, 3, 5, 6, 7, 8, 9, 10, 12, 14] * 1000 1563 1564 # Loop over each spin. 1565 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 1566 # Skip protons for MMQ data. 1567 if spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 1568 continue 1569 1570 # Initialise some data structures. 1571 data = [] 1572 set_labels = [] 1573 x_err_flag = False 1574 y_err_flag = False 1575 axis_labels = [] 1576 set_colours = [] 1577 x_axis_type_zero = [] 1578 symbols = [] 1579 symbol_sizes = [] 1580 linetype = [] 1581 linestyle = [] 1582 1583 # The unique file name. 1584 file_name = "disp%s.agr" % spin_id.replace('#', '_').replace(':', '_').replace('@', '_') 1585 1586 # Open the file for writing. 1587 file_path = get_file_path(file_name, dir) 1588 file = open_write_file(file_name, dir, force) 1589 1590 # Get the attached proton. 1591 proton = None 1592 if proton_mmq_flag: 1593 proton = return_attached_protons(spin_id)[0] 1594 1595 # Set up the interpolated curve data structures. 1596 interpolated_flag = False 1597 if not spin.model in [MODEL_R2EFF]: 1598 # Set the flag. 1599 interpolated_flag = True 1600 1601 # Initialise some structures. 1602 cpmg_frqs_new = None 1603 spin_lock_nu1_new = None 1604 1605 # Interpolate the CPMG frequencies (numeric models). 1606 if spin.model in MODEL_LIST_NUMERIC_CPMG or spin.model in [MODEL_B14, MODEL_B14_FULL]: 1607 cpmg_frqs = return_cpmg_frqs(ref_flag=False) 1608 relax_times = return_relax_times() 1609 if cpmg_frqs != None and len(cpmg_frqs[0][0]): 1610 cpmg_frqs_new = [] 1611 for ei in range(len(cpmg_frqs)): 1612 # Add a new dimension. 1613 cpmg_frqs_new.append([]) 1614 1615 # Then loop over the spectrometer frequencies. 1616 for mi in range(len(cpmg_frqs[ei])): 1617 # Add a new dimension. 1618 cpmg_frqs_new[ei].append([]) 1619 1620 # Finally the offsets. 1621 for oi in range(len(cpmg_frqs[ei][mi])): 1622 # Add a new dimension. 1623 cpmg_frqs_new[ei][mi].append([]) 1624 1625 # No data. 1626 if not len(cpmg_frqs[ei][mi][oi]): 1627 continue 1628 1629 # The minimum frequency unit. 1630 min_frq = 1.0 / relax_times[ei][mi] 1631 max_frq = max(cpmg_frqs[ei][mi][oi]) + round(extend / min_frq) * min_frq 1632 num_points = int(round(max_frq / min_frq)) 1633 1634 # Interpolate (adding the extended amount to the end). 1635 for di in range(num_points): 1636 point = (di + 1) * min_frq 1637 cpmg_frqs_new[ei][mi][oi].append(point) 1638 1639 # Convert to a numpy array. 1640 cpmg_frqs_new[ei][mi][oi] = array(cpmg_frqs_new[ei][mi][oi], float64) 1641 1642 # Interpolate the CPMG frequencies (analytic models). 1643 else: 1644 cpmg_frqs = return_cpmg_frqs(ref_flag=False) 1645 if cpmg_frqs != None and len(cpmg_frqs[0][0]): 1646 cpmg_frqs_new = [] 1647 for ei in range(len(cpmg_frqs)): 1648 # Add a new dimension. 1649 cpmg_frqs_new.append([]) 1650 1651 # Then loop over the spectrometer frequencies. 1652 for mi in range(len(cpmg_frqs[ei])): 1653 # Add a new dimension. 1654 cpmg_frqs_new[ei].append([]) 1655 1656 # Finally the offsets. 1657 for oi in range(len(cpmg_frqs[ei][mi])): 1658 # Add a new dimension. 1659 cpmg_frqs_new[ei][mi].append([]) 1660 1661 # No data. 1662 if not len(cpmg_frqs[ei][mi][oi]): 1663 continue 1664 1665 # Interpolate (adding the extended amount to the end). 1666 for di in range(num_points): 1667 point = (di + 1) * (max(cpmg_frqs[ei][mi][oi])+extend) / num_points 1668 cpmg_frqs_new[ei][mi][oi].append(point) 1669 1670 # Convert to a numpy array. 1671 cpmg_frqs_new[ei][mi][oi] = array(cpmg_frqs_new[ei][mi][oi], float64) 1672 1673 # Interpolate the spin-lock field strengths. 1674 spin_lock_nu1 = return_spin_lock_nu1(ref_flag=False) 1675 if spin_lock_nu1 != None and len(spin_lock_nu1[0][0][0]): 1676 spin_lock_nu1_new = [] 1677 for ei in range(len(spin_lock_nu1)): 1678 # Add a new dimension. 1679 spin_lock_nu1_new.append([]) 1680 1681 # Then loop over the spectrometer frequencies. 1682 for mi in range(len(spin_lock_nu1[ei])): 1683 # Add a new dimension. 1684 spin_lock_nu1_new[ei].append([]) 1685 1686 # Finally the offsets. 1687 for oi in range(len(spin_lock_nu1[ei][mi])): 1688 # Add a new dimension. 1689 spin_lock_nu1_new[ei][mi].append([]) 1690 1691 # No data. 1692 if not len(spin_lock_nu1[ei][mi][oi]): 1693 continue 1694 1695 # Interpolate (adding the extended amount to the end). 1696 for di in range(num_points): 1697 point = (di + 1) * (max(spin_lock_nu1[ei][mi][oi])+extend) / num_points 1698 spin_lock_nu1_new[ei][mi][oi].append(point) 1699 1700 # Convert to a numpy array. 1701 spin_lock_nu1_new[ei][mi][oi] = array(spin_lock_nu1_new[ei][mi][oi], float64) 1702 1703 # Back calculate R2eff data for the second sets of plots. 1704 back_calc = specific_analyses.relax_disp.optimisation.back_calc_r2eff(spin=spin, spin_id=spin_id, cpmg_frqs=cpmg_frqs_new, spin_lock_nu1=spin_lock_nu1_new) 1705 1706 # Loop over each experiment type. 1707 graph_index = 0 1708 for exp_type, ei in loop_exp(return_indices=True): 1709 # Update the structures. 1710 data.append([]) 1711 set_labels.append([]) 1712 set_colours.append([]) 1713 x_axis_type_zero.append([]) 1714 symbols.append([]) 1715 symbol_sizes.append([]) 1716 linetype.append([]) 1717 linestyle.append([]) 1718 1719 # Alias the correct spin. 1720 current_spin = spin 1721 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 1722 current_spin = proton 1723 1724 # Loop over the spectrometer frequencies and offsets. 1725 set_index = 0 1726 err = False 1727 colour_index = 0 1728 for frq, offset, mi, oi in loop_frq_offset(exp_type=exp_type, return_indices=True): 1729 # Add a new set for the data at each frequency and offset. 1730 data[graph_index].append([]) 1731 1732 # Add a new label. 1733 if exp_type in EXP_TYPE_LIST_CPMG: 1734 label = "R\\s2eff\\N" 1735 else: 1736 label = "R\\s1\\xr\\B\\N" 1737 if offset != None and frq != None: 1738 label += " (%.1f MHz, %.3f ppm)" % (frq / 1e6, offset) 1739 elif frq != None: 1740 label += " (%.1f MHz)" % (frq / 1e6) 1741 elif offset != None: 1742 label += " (%.3f ppm)" % (offset) 1743 set_labels[ei].append(label) 1744 1745 # The other settings. 1746 set_colours[graph_index].append(colour_order[colour_index]) 1747 x_axis_type_zero[graph_index].append(True) 1748 symbols[graph_index].append(1) 1749 symbol_sizes[graph_index].append(0.45) 1750 linetype[graph_index].append(0) 1751 linestyle[graph_index].append(0) 1752 1753 # Loop over the dispersion points. 1754 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 1755 # The data key. 1756 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 1757 1758 # No data present. 1759 if key not in current_spin.r2eff: 1760 continue 1761 1762 # Add the data. 1763 data[graph_index][set_index].append([point, current_spin.r2eff[key]]) 1764 1765 # Add the error. 1766 if hasattr(current_spin, 'r2eff_err') and key in current_spin.r2eff_err: 1767 err = True 1768 data[graph_index][set_index][-1].append(current_spin.r2eff_err[key]) 1769 1770 # Increment the graph set index. 1771 set_index += 1 1772 colour_index += 1 1773 1774 # Add the back calculated data. 1775 colour_index = 0 1776 for frq, offset, mi, oi in loop_frq_offset(exp_type=exp_type, return_indices=True): 1777 # Add a new set for the data at each frequency and offset. 1778 data[graph_index].append([]) 1779 1780 # Add a new label. 1781 if exp_type in EXP_TYPE_LIST_CPMG: 1782 label = "Back calculated R\\s2eff\\N" 1783 else: 1784 label = "Back calculated R\\s1\\xr\\B\\N" 1785 if offset != None and frq != None: 1786 label += " (%.1f MHz, %.3f ppm)" % (frq / 1e6, offset) 1787 elif frq != None: 1788 label += " (%.1f MHz)" % (frq / 1e6) 1789 elif offset != None: 1790 label += " (%.3f ppm)" % (offset) 1791 set_labels[ei].append(label) 1792 1793 # The other settings. 1794 set_colours[graph_index].append(colour_order[colour_index]) 1795 x_axis_type_zero[graph_index].append(True) 1796 symbols[graph_index].append(4) 1797 symbol_sizes[graph_index].append(0.45) 1798 linetype[graph_index].append(1) 1799 if interpolated_flag: 1800 linestyle[graph_index].append(2) 1801 else: 1802 linestyle[graph_index].append(1) 1803 1804 # Loop over the dispersion points. 1805 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 1806 # The data key. 1807 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 1808 1809 # No data present. 1810 if not hasattr(current_spin, 'r2eff_bc') or key not in current_spin.r2eff_bc: 1811 continue 1812 1813 # Add the data. 1814 data[graph_index][set_index].append([point, current_spin.r2eff_bc[key]]) 1815 1816 # Handle the errors. 1817 if err: 1818 data[graph_index][set_index][-1].append(None) 1819 1820 # Increment the graph set index. 1821 set_index += 1 1822 colour_index += 1 1823 1824 # Add the interpolated back calculated data. 1825 if interpolated_flag: 1826 colour_index = 0 1827 for frq, offset, mi, oi in loop_frq_offset(exp_type=exp_type, return_indices=True): 1828 # Add a new set for the data at each frequency and offset. 1829 data[graph_index].append([]) 1830 1831 # Add a new label. 1832 if exp_type in EXP_TYPE_LIST_CPMG: 1833 label = "R\\s2eff\\N interpolated curve" 1834 else: 1835 label = "R\\s1\\xr\\B\\N interpolated curve" 1836 if offset != None and frq != None: 1837 label += " (%.1f MHz, %.3f ppm)" % (frq / 1e6, offset) 1838 elif frq != None: 1839 label += " (%.1f MHz)" % (frq / 1e6) 1840 elif offset != None: 1841 label += " (%.3f ppm)" % (offset) 1842 set_labels[ei].append(label) 1843 1844 # The other settings. 1845 set_colours[graph_index].append(colour_order[colour_index]) 1846 x_axis_type_zero[graph_index].append(True) 1847 if spin.model in MODEL_LIST_NUMERIC_CPMG: 1848 symbols[graph_index].append(8) 1849 else: 1850 symbols[graph_index].append(0) 1851 symbol_sizes[graph_index].append(0.20) 1852 linetype[graph_index].append(1) 1853 linestyle[graph_index].append(1) 1854 1855 # Loop over the dispersion points. 1856 for di in range(len(back_calc[ei][0][mi][oi])): 1857 # Skip invalid points (values of 1e100). 1858 if back_calc[ei][0][mi][oi][di] > 1e50: 1859 continue 1860 1861 # The X point. 1862 if exp_type in EXP_TYPE_LIST_CPMG: 1863 point = cpmg_frqs_new[ei][mi][oi][di] 1864 else: 1865 point = spin_lock_nu1_new[ei][mi][oi][di] 1866 1867 # Add the data. 1868 data[graph_index][set_index].append([point, back_calc[ei][0][mi][oi][di]]) 1869 1870 # Handle the errors. 1871 if err: 1872 data[graph_index][set_index][-1].append(None) 1873 1874 # Increment the graph set index. 1875 set_index += 1 1876 colour_index += 1 1877 1878 # Add the residuals for statistical comparison. 1879 colour_index = 0 1880 for frq, offset, mi, oi in loop_frq_offset(exp_type=exp_type, return_indices=True): 1881 # Add a new set for the data at each frequency and offset. 1882 data[graph_index].append([]) 1883 1884 # Add a new label. 1885 label = "Residuals" 1886 if offset != None and frq != None: 1887 label += " (%.1f MHz, %.3f ppm)" % (frq / 1e6, offset) 1888 elif frq != None: 1889 label += " (%.1f MHz)" % (frq / 1e6) 1890 elif offset != None: 1891 label += " (%.3f ppm)" % (offset) 1892 set_labels[ei].append(label) 1893 1894 # The other settings. 1895 set_colours[graph_index].append(colour_order[colour_index]) 1896 x_axis_type_zero[graph_index].append(True) 1897 symbols[graph_index].append(9) 1898 symbol_sizes[graph_index].append(0.45) 1899 linetype[graph_index].append(1) 1900 linestyle[graph_index].append(3) 1901 1902 # Loop over the dispersion points. 1903 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 1904 # The data key. 1905 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 1906 1907 # No data present. 1908 if key not in current_spin.r2eff or not hasattr(current_spin, 'r2eff_bc') or key not in current_spin.r2eff_bc: 1909 continue 1910 1911 # Add the data. 1912 data[graph_index][set_index].append([point, current_spin.r2eff[key] - current_spin.r2eff_bc[key]]) 1913 1914 # Handle the errors. 1915 if err: 1916 err = True 1917 data[graph_index][set_index][-1].append(current_spin.r2eff_err[key]) 1918 1919 # Increment the graph set index. 1920 set_index += 1 1921 colour_index += 1 1922 1923 # Increment the graph index. 1924 graph_index += 1 1925 1926 # The axis labels. 1927 if exp_type in EXP_TYPE_LIST_CPMG: 1928 axis_labels.append(['\\qCPMG pulse train frequency (Hz)\\Q', '%s - \\qR\\s2,eff\\N\\Q (rad.s\\S-1\\N)'%exp_type]) 1929 else: 1930 axis_labels.append(['\\qSpin-lock field strength (Hz)\\Q', '\\qR\\s1\\xr\\B\\N\\Q (rad.s\\S-1\\N)']) 1931 1932 # Remove all NaN values. 1933 for i in range(len(data)): 1934 for j in range(len(data[i])): 1935 for k in range(len(data[i][j])): 1936 for l in range(len(data[i][j][k])): 1937 if isNaN(data[i][j][k][l]): 1938 data[i][j][k][l] = 0.0 1939 1940 # Write the header. 1941 title = "Relaxation dispersion plot" 1942 graph_num = len(data) 1943 sets = [] 1944 legend = [] 1945 for gi in range(len(data)): 1946 sets.append(len(data[gi])) 1947 legend.append(False) 1948 legend[0] = True 1949 write_xy_header(file=file, title=title, graph_num=graph_num, sets=sets, set_names=set_labels, set_colours=set_colours, x_axis_type_zero=x_axis_type_zero, symbols=symbols, symbol_sizes=symbol_sizes, linetype=linetype, linestyle=linestyle, axis_labels=axis_labels, legend=legend, legend_box_fill_pattern=[0]*graph_num, legend_char_size=[0.8]*graph_num) 1950 1951 # Write the data. 1952 graph_type = 'xy' 1953 if err: 1954 graph_type = 'xydy' 1955 write_xy_data(data, file=file, graph_type=graph_type) 1956 1957 # Close the file. 1958 file.close() 1959 1960 # Add the file to the results file list. 1961 add_result_file(type='grace', label='Grace', file=file_path) 1962 1963 # Write a python "grace to PNG/EPS/SVG..." conversion script. 1964 # Open the file for writing. 1965 file_name = "grace2images.py" 1966 file = open_write_file(file_name, dir, force) 1967 1968 # Write the file. 1969 script_grace2images(file=file) 1970 1971 # Close the batch script, then make it executable (expanding any ~ characters). 1972 file.close() 1973 if dir: 1974 dir = expanduser(dir) 1975 chmod(dir + sep + file_name, S_IRWXU|S_IRGRP|S_IROTH) 1976 else: 1977 file_name = expanduser(file_name) 1978 chmod(file_name, S_IRWXU|S_IRGRP|S_IROTH)
1979 1980
1981 -def plot_exp_curves(file=None, dir=None, force=None, norm=None):
1982 """Custom 2D Grace plotting function for the exponential curves. 1983 1984 @keyword file: The name of the Grace file to create. 1985 @type file: str 1986 @keyword dir: The optional directory to place the file into. 1987 @type dir: str 1988 @param force: Boolean argument which if True causes the file to be overwritten if it already exists. 1989 @type force: bool 1990 @keyword norm: The normalisation flag which if set to True will cause all graphs to be normalised to a starting value of 1. 1991 @type norm: bool 1992 """ 1993 1994 # Test if the current pipe exists. 1995 pipes.test() 1996 1997 # Test if the sequence data is loaded. 1998 if not exists_mol_res_spin_data(): 1999 raise RelaxNoSequenceError 2000 2001 # Open the file for writing. 2002 file_path = get_file_path(file, dir) 2003 file = open_write_file(file, dir, force) 2004 2005 # Initialise some data structures. 2006 data = [] 2007 set_labels = [] 2008 x_err_flag = False 2009 y_err_flag = False 2010 2011 # 1H MMQ flag. 2012 proton_mmq_flag = has_proton_mmq_cpmg() 2013 2014 # Loop over the spectrometer frequencies. 2015 graph_index = 0 2016 err = False 2017 for exp_type, frq, offset, ei, mi, oi in loop_exp_frq_offset(return_indices=True): 2018 # Loop over the dispersion points. 2019 for point, di in loop_point(exp_type=exp_type, frq=frq, offset=offset, return_indices=True): 2020 # Create a new graph. 2021 data.append([]) 2022 2023 # Loop over each spin. 2024 for spin, id in spin_loop(return_id=True, skip_desel=True): 2025 # Skip protons for MMQ data. 2026 if spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 2027 continue 2028 2029 # No data present. 2030 if not hasattr(spin, 'peak_intensity'): 2031 continue 2032 2033 # Get the attached proton. 2034 proton = None 2035 if proton_mmq_flag: 2036 proton = return_attached_protons(spin_id)[0] 2037 2038 # Alias the correct spin. 2039 current_spin = spin 2040 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 2041 current_spin = proton 2042 2043 # Append a new set structure and set the name to the spin ID. 2044 data[graph_index].append([]) 2045 if graph_index == 0: 2046 set_labels.append("Spin %s" % id) 2047 2048 # Loop over the relaxation time periods. 2049 for time in loop_time(exp_type=exp_type, frq=frq, offset=offset, point=point): 2050 # The key. 2051 keys = find_intensity_keys(exp_type=exp_type, frq=frq, offset=offset, point=point, time=time) 2052 2053 # Loop over each key. 2054 for key in keys: 2055 # No key present. 2056 if key not in current_spin.peak_intensity: 2057 continue 2058 2059 # Add the data. 2060 if hasattr(current_spin, 'peak_intensity_err'): 2061 data[graph_index][-1].append([time, current_spin.peak_intensity[key], spin.peak_intensity_err[key]]) 2062 err = True 2063 else: 2064 data[graph_index][-1].append([time, current_spin.peak_intensity[key]]) 2065 2066 # Increment the frq index. 2067 graph_index += 1 2068 2069 # The axis labels. 2070 axis_labels = ['Relaxation time period (s)', 'Peak intensities'] 2071 2072 # Write the header. 2073 graph_num = len(data) 2074 sets = [] 2075 for gi in range(graph_num): 2076 sets.append(len(data[gi])) 2077 write_xy_header(file=file, graph_num=graph_num, sets=sets, set_names=[set_labels]*graph_num, axis_labels=[axis_labels]*graph_num, norm=[norm]*graph_num) 2078 2079 # Write the data. 2080 graph_type = 'xy' 2081 if err: 2082 graph_type = 'xydy' 2083 write_xy_data(data, file=file, graph_type=graph_type, norm=[norm]*graph_num) 2084 2085 # Close the file. 2086 file.close() 2087 2088 # Add the file to the results file list. 2089 add_result_file(type='grace', label='Grace', file=file_path)
2090 2091
2092 -def r20_from_min_r2eff(force=True, verbosity=1):
2093 """Set the R20 values to the minimum R2eff values. 2094 2095 For a 2 field cpmg experiment with model CR72, that would drop number of uniform grid search point from gridNr^5 to gridNr^3. 2096 For standard 21 grid Nr, it would make the grid search 441 times faster. 2097 2098 @keyword force: A flag forcing the overwriting of current values. 2099 @type force: bool 2100 @keyword verbosity: A flag specifying to print the setting of values. 2101 @type verbosity: int 2102 """ 2103 2104 # Number of spectrometer fields. 2105 fields = [None] 2106 field_count = 1 2107 if hasattr(cdp, 'spectrometer_frq_count'): 2108 fields = cdp.spectrometer_frq_list 2109 field_count = cdp.spectrometer_frq_count 2110 2111 # Loop over all spins. 2112 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 2113 # Nothing to do (the R2eff model has no dispersion curves). 2114 if spin.model == MODEL_R2EFF: 2115 print("The spin model is %s. The %s model has no dispersion curves, so will not set the grid values."%(spin.model, spin.model)) 2116 continue 2117 2118 # Get all the data. 2119 try: 2120 values, errors, missing, frqs, frqs_H, exp_types, relax_times = return_r2eff_arrays(spins=[spin], spin_ids=[spin_id], fields=fields, field_count=field_count) 2121 2122 # No R2eff data, so skip the rest. 2123 except RelaxError: 2124 continue 2125 2126 # Loop over the experiments, magnetic fields, and offsets. 2127 for exp_type, frq, offset, ei, mi, oi in loop_exp_frq_offset(return_indices=True): 2128 # No data. 2129 if not len(values[ei][0][mi][oi]): 2130 continue 2131 2132 # The minimum 2133 min_val = values[ei][0][mi][oi].min() 2134 2135 # Loop over the parameters for the current model 2136 for param in MODEL_PARAMS[spin.model]: 2137 # Check if the param is r2 2138 if param in PARAMS_R20: 2139 # Set the value 2140 value.set(val=min_val, param=param, index=mi, spin_id=spin_id, force=force) 2141 if verbosity: 2142 print("For %s, frq=%3.1f, offset=%3.1f, for grid search setting initial %s=%3.2f for spin: %s"%(exp_type, frq/1E6, offset, param, min_val, spin_id))
2143 2144
2145 -def r2eff_read(id=None, file=None, dir=None, disp_frq=None, offset=None, spin_id_col=None, mol_name_col=None, res_num_col=None, res_name_col=None, spin_num_col=None, spin_name_col=None, data_col=None, error_col=None, sep=None):
2146 """Read R2eff/R1rho values directly from a file whereby each row corresponds to a different spin. 2147 2148 @keyword id: The experiment ID string to associate the data with. 2149 @type id: str 2150 @keyword file: The name of the file to open. 2151 @type file: str 2152 @keyword dir: The directory containing the file (defaults to the current directory if None). 2153 @type dir: str or None 2154 @keyword disp_frq: For CPMG-type data, the frequency of the CPMG pulse train. For R1rho-type data, the spin-lock field strength (nu1). The units must be Hertz. 2155 @type disp_frq: float 2156 @keyword offset: For R1rho-type data, the spin-lock offset value in ppm. 2157 @type offset: None or float 2158 @keyword spin_id_col: The column containing the spin ID strings. If supplied, the mol_name_col, res_name_col, res_num_col, spin_name_col, and spin_num_col arguments must be none. 2159 @type spin_id_col: int or None 2160 @keyword mol_name_col: The column containing the molecule name information. If supplied, spin_id_col must be None. 2161 @type mol_name_col: int or None 2162 @keyword res_name_col: The column containing the residue name information. If supplied, spin_id_col must be None. 2163 @type res_name_col: int or None 2164 @keyword res_num_col: The column containing the residue number information. If supplied, spin_id_col must be None. 2165 @type res_num_col: int or None 2166 @keyword spin_name_col: The column containing the spin name information. If supplied, spin_id_col must be None. 2167 @type spin_name_col: int or None 2168 @keyword spin_num_col: The column containing the spin number information. If supplied, spin_id_col must be None. 2169 @type spin_num_col: int or None 2170 @keyword data_col: The column containing the R2eff/R1rho data in Hz. 2171 @type data_col: int or None 2172 @keyword error_col: The column containing the R2eff/R1rho errors. 2173 @type error_col: int or None 2174 @keyword sep: The column separator which, if None, defaults to whitespace. 2175 @type sep: str or None 2176 """ 2177 2178 # Data checks. 2179 pipes.test() 2180 check_mol_res_spin_data() 2181 check_frequency(id=id) 2182 check_exp_type(id=id) 2183 2184 # Store the spectrum ID. 2185 add_spectrum_id(id) 2186 2187 # Get the metadata. 2188 frq = get_frequency(id=id) 2189 exp_type = get_exp_type(id=id) 2190 2191 # Loop over the data. 2192 data_flag = False 2193 mol_names = [] 2194 res_nums = [] 2195 res_names = [] 2196 spin_nums = [] 2197 spin_names = [] 2198 values = [] 2199 errors = [] 2200 for data in read_spin_data(file=file, dir=dir, spin_id_col=spin_id_col, mol_name_col=mol_name_col, res_num_col=res_num_col, res_name_col=res_name_col, spin_num_col=spin_num_col, spin_name_col=spin_name_col, data_col=data_col, error_col=error_col, sep=sep): 2201 # Unpack. 2202 if data_col and error_col: 2203 mol_name, res_num, res_name, spin_num, spin_name, value, error = data 2204 elif data_col: 2205 mol_name, res_num, res_name, spin_num, spin_name, value = data 2206 error = None 2207 else: 2208 mol_name, res_num, res_name, spin_num, spin_name, error = data 2209 value = None 2210 2211 # Test the error value (cannot be 0.0). 2212 if error == 0.0: 2213 raise RelaxError("An invalid error value of zero has been encountered.") 2214 2215 # Get the corresponding spin container. 2216 spin_id = generate_spin_id_unique(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name) 2217 spin = return_spin(spin_id) 2218 if spin == None: 2219 warn(RelaxNoSpinWarning(spin_id)) 2220 continue 2221 2222 # The dispersion point key. 2223 point_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=disp_frq) 2224 2225 # Store the R2eff data. 2226 if data_col: 2227 # Initialise if necessary. 2228 if not hasattr(spin, 'r2eff'): 2229 spin.r2eff = {} 2230 2231 # Store. 2232 spin.r2eff[point_key] = value 2233 2234 # Store the R2eff error. 2235 if error_col: 2236 # Initialise if necessary. 2237 if not hasattr(spin, 'r2eff_err'): 2238 spin.r2eff_err = {} 2239 2240 # Store. 2241 spin.r2eff_err[point_key] = error 2242 2243 # Data added. 2244 data_flag = True 2245 2246 # Append the data for printout. 2247 mol_names.append(mol_name) 2248 res_nums.append(res_num) 2249 res_names.append(res_name) 2250 spin_nums.append(spin_num) 2251 spin_names.append(spin_name) 2252 values.append(value) 2253 errors.append(error) 2254 2255 # Print out. 2256 write_spin_data(file=sys.stdout, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, data=values, data_name='R2eff', error=errors, error_name='R2eff_error') 2257 2258 # Update the global structures. 2259 if data_flag: 2260 # Set the dispersion point frequency. 2261 if exp_type in EXP_TYPE_LIST_CPMG: 2262 cpmg_setup(spectrum_id=id, cpmg_frq=disp_frq) 2263 else: 2264 spin_lock_field(spectrum_id=id, field=disp_frq)
2265 2266
2267 -def r2eff_read_spin(id=None, spin_id=None, file=None, dir=None, disp_point_col=None, offset_col=None, data_col=None, error_col=None, sep=None):
2268 """Read R2eff/R1rho values from file whereby each row is a different dispersion point. 2269 2270 @keyword id: The experiment ID string to associate the data with. This will be modified to include the dispersion point data as "%s_%s" % (id, disp_point). 2271 @type id: str 2272 @keyword spin_id: The spin ID string. 2273 @type spin_id: str 2274 @keyword file: The name of the file to open. 2275 @type file: str 2276 @keyword dir: The directory containing the file (defaults to the current directory if None). 2277 @type dir: str or None 2278 @keyword disp_point_col: The column containing the dispersion point information. For CPMG-type data, this is the frequency of the CPMG pulse train. For R1rho-type data, this is the spin-lock field strength (nu1). The units must be Hertz. 2279 @type disp_point_col: int 2280 @keyword offset_col: This is for R1rho data - the dispersion point column can be substituted for the offset values in Hertz. 2281 @type offset_col: None or int 2282 @keyword data_col: The column containing the R2eff/R1rho data in Hz. 2283 @type data_col: int 2284 @keyword error_col: The column containing the R2eff/R1rho errors. 2285 @type error_col: int 2286 @keyword sep: The column separator which, if None, defaults to whitespace. 2287 @type sep: str or None 2288 """ 2289 2290 # Data checks. 2291 pipes.test() 2292 check_mol_res_spin_data() 2293 2294 # Get the spin. 2295 spin = return_spin(spin_id) 2296 if spin == None: 2297 raise RelaxNoSpinError(spin_id) 2298 2299 # Extract the data from the file, removing comments and blank lines. 2300 file_data = extract_data(file, dir, sep=sep) 2301 file_data = strip(file_data) 2302 2303 # Loop over the data. 2304 data = [] 2305 new_ids = [] 2306 for line in file_data: 2307 # Invalid columns. 2308 if disp_point_col != None and disp_point_col > len(line): 2309 warn(RelaxWarning("The data %s is invalid, no dispersion point column can be found." % line)) 2310 continue 2311 if offset_col != None and offset_col > len(line): 2312 warn(RelaxWarning("The data %s is invalid, no offset column can be found." % line)) 2313 continue 2314 if data_col > len(line): 2315 warn(RelaxWarning("The R2eff/R1rho data %s is invalid, no data column can be found." % line)) 2316 continue 2317 if error_col > len(line): 2318 warn(RelaxWarning("The R2eff/R1rho data %s is invalid, no error column can be found." % line)) 2319 continue 2320 2321 # Unpack. 2322 if disp_point_col != None: 2323 ref_data = line[disp_point_col-1] 2324 elif offset_col != None: 2325 ref_data = line[offset_col-1] 2326 value = line[data_col-1] 2327 error = line[error_col-1] 2328 2329 # Convert and check the dispersion point or offset. 2330 try: 2331 ref_data = float(ref_data) 2332 except ValueError: 2333 if disp_point_col != None: 2334 warn(RelaxWarning("The dispersion point data of the line %s is invalid." % line)) 2335 elif offset_col != None: 2336 warn(RelaxWarning("The offset data of the line %s is invalid." % line)) 2337 continue 2338 2339 # Convert and check the value. 2340 if value == 'None': 2341 value = None 2342 if value != None: 2343 try: 2344 value = float(value) 2345 except ValueError: 2346 warn(RelaxWarning("The R2eff/R1rho value of the line %s is invalid." % line)) 2347 continue 2348 2349 # Convert and check the error. 2350 if error == 'None': 2351 error = None 2352 if error != None: 2353 try: 2354 error = float(error) 2355 except ValueError: 2356 warn(RelaxWarning("The R2eff/R1rho error of the line %s is invalid." % line)) 2357 continue 2358 2359 # Test the error value (cannot be 0.0). 2360 if error == 0.0: 2361 raise RelaxError("An invalid error value of zero has been encountered.") 2362 2363 # Find the matching spectrum ID. 2364 new_id = None 2365 for spectrum_id in cdp.spectrum_ids: 2366 # Skip IDs which don't start with the base ID. 2367 if not search("^%s"%id, spectrum_id): 2368 continue 2369 2370 # Find a close enough dispersion point (to one decimal place to allow for user truncation). 2371 if disp_point_col != None: 2372 if hasattr(cdp, 'cpmg_frqs') and spectrum_id in cdp.cpmg_frqs: 2373 if abs(ref_data - cdp.cpmg_frqs[spectrum_id]) < 0.1: 2374 new_id = spectrum_id 2375 break 2376 if hasattr(cdp, 'spin_lock_nu1') and spectrum_id in cdp.spin_lock_nu1: 2377 if abs(ref_data - cdp.spin_lock_nu1[spectrum_id]) < 0.1: 2378 new_id = spectrum_id 2379 break 2380 2381 # Find a close enough offset (to one decimal place to allow for user truncation). 2382 elif offset_col != None: 2383 if hasattr(cdp, 'spin_lock_offset') and spectrum_id in cdp.spin_lock_offset: 2384 # The sign to multiply offsets by. 2385 sign = 1.0 2386 if spin.isotope == '15N': 2387 sign = -1.0 2388 2389 # Convert the data. 2390 data_new = sign * frequency_to_ppm(frq=ref_data, B0=cdp.spectrometer_frq[spectrum_id], isotope=spin.isotope) 2391 2392 # Store the ID. 2393 if abs(data_new - cdp.spin_lock_offset[spectrum_id]) < 0.1: 2394 new_id = spectrum_id 2395 break 2396 2397 # No match. 2398 if new_id == None: 2399 if disp_point_col != None: 2400 raise RelaxError("The experiment ID corresponding to the base ID '%s' and the dispersion point '%s' could not be found." % (id, ref_data)) 2401 if offset_col != None: 2402 raise RelaxError("The experiment ID corresponding to the base ID '%s' and the offset '%s' could not be found." % (id, data_new)) 2403 2404 # Add the ID to the list. 2405 new_ids.append(new_id) 2406 2407 # Data checks. 2408 check_frequency(id=new_id) 2409 check_exp_type(id=new_id) 2410 2411 # Store the spectrum ID. 2412 add_spectrum_id(new_id) 2413 2414 # Get the metadata. 2415 frq = get_frequency(id=new_id) 2416 exp_type = get_exp_type(id=new_id) 2417 2418 # The dispersion point key. 2419 if disp_point_col != None: 2420 disp_point = ref_data 2421 offset = 0.0 2422 elif offset_col != None: 2423 disp_point = cdp.spin_lock_nu1[new_id] 2424 offset = data_new 2425 point_key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=disp_point) 2426 2427 # Store the R2eff data. 2428 if data_col: 2429 # Initialise if necessary. 2430 if not hasattr(spin, 'r2eff'): 2431 spin.r2eff = {} 2432 2433 # Store. 2434 spin.r2eff[point_key] = value 2435 2436 # Store the R2eff error. 2437 if error_col: 2438 # Initialise if necessary. 2439 if not hasattr(spin, 'r2eff_err'): 2440 spin.r2eff_err = {} 2441 2442 # Store. 2443 spin.r2eff_err[point_key] = error 2444 2445 # Append the data for printout. 2446 if disp_point_col != None: 2447 data.append(["%-40s" % point_key, "%20.15f" % disp_point, "%20.15f" % value, "%20.15f" % error]) 2448 else: 2449 data.append(["%-40s" % point_key, "%20.15f" % offset, "%20.15f" % value, "%20.15f" % error]) 2450 2451 # Data added. 2452 data_flag = True 2453 2454 # No data, so fail hard! 2455 if not len(data): 2456 raise RelaxError("No R2eff/R1rho data could be extracted.") 2457 2458 # Print out. 2459 print("The following R2eff/R1rho data has been loaded into the relax data store:\n") 2460 if disp_point_col != None: 2461 write_data(out=sys.stdout, headings=["R2eff_key", "Disp_point", "R2eff", "R2eff_error"], data=data) 2462 else: 2463 write_data(out=sys.stdout, headings=["R2eff_key", "Offset (ppm)", "R2eff", "R2eff_error"], data=data)
2464 2465
2466 -def randomise_R1(spin=None, ri_id=None, N=None):
2467 """Randomise the R1 data for the given spin for use in the Monte Carlo simulations. 2468 2469 @keyword spin: The spin container to randomise the data for. 2470 @type spin: SpinContainer instance 2471 @keyword ri_id: The relaxation data ID string. 2472 @type ri_id: str 2473 @keyword N: The number of randomisations to perform. 2474 @type N: int 2475 """ 2476 2477 # The data already exists. 2478 if hasattr(spin, 'ri_data_sim') and ri_id in spin.ri_data_sim: 2479 return 2480 2481 # Initialise the structure. 2482 if not hasattr(spin, 'ri_data_sim'): 2483 spin.ri_data_sim = {} 2484 spin.ri_data_sim[ri_id] = [] 2485 2486 # Randomise. 2487 for i in range(N): 2488 spin.ri_data_sim[ri_id].append(gauss(spin.ri_data[ri_id], spin.ri_data_err[ri_id]))
2489 2490
2491 -def relax_time(time=0.0, spectrum_id=None):
2492 """Set the relaxation time period associated with a given spectrum. 2493 2494 @keyword time: The time, in seconds, of the relaxation period. 2495 @type time: float 2496 @keyword spectrum_id: The spectrum identification string. 2497 @type spectrum_id: str 2498 """ 2499 2500 # Test if the spectrum id exists. 2501 if spectrum_id not in cdp.spectrum_ids: 2502 raise RelaxNoSpectraError(spectrum_id) 2503 2504 # Initialise the global relaxation time data structures if needed. 2505 if not hasattr(cdp, 'relax_times'): 2506 cdp.relax_times = {} 2507 if not hasattr(cdp, 'relax_time_list'): 2508 cdp.relax_time_list = [] 2509 2510 # Add the time, converting to a float if needed. 2511 cdp.relax_times[spectrum_id] = float(time) 2512 2513 # The unique time points. 2514 if cdp.relax_times[spectrum_id] not in cdp.relax_time_list: 2515 cdp.relax_time_list.append(cdp.relax_times[spectrum_id]) 2516 cdp.relax_time_list.sort() 2517 2518 # Update the exponential time point count. 2519 cdp.num_time_pts = len(cdp.relax_time_list) 2520 2521 # Printout. 2522 print("Setting the '%s' spectrum relaxation time period to %s s." % (spectrum_id, cdp.relax_times[spectrum_id]))
2523 2524
2525 -def return_cpmg_frqs(ref_flag=True):
2526 """Return the list of nu_CPMG frequencies. 2527 2528 @keyword ref_flag: A flag which if False will cause the reference spectrum frequency of None to be removed from the list. 2529 @type ref_flag: bool 2530 @return: The list of nu_CPMG frequencies in Hz. It has the dimensions {Ei, Mi, Oi}. 2531 @rtype: rank-2 list of numpy rank-1 float64 arrays 2532 """ 2533 2534 # No data. 2535 if not hasattr(cdp, 'cpmg_frqs_list'): 2536 return None 2537 2538 # Initialise. 2539 cpmg_frqs = [] 2540 2541 # First loop over the experiment types. 2542 for exp_type, ei in loop_exp(return_indices=True): 2543 # Add a new dimension. 2544 cpmg_frqs.append([]) 2545 2546 # Then loop over the spectrometer frequencies. 2547 for frq, mi in loop_frq(return_indices=True): 2548 # Add a new dimension. 2549 cpmg_frqs[ei].append([]) 2550 2551 # Loop over the offsets. 2552 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 2553 # Add a new dimension. 2554 cpmg_frqs[ei][mi].append([]) 2555 2556 # Loop over the fields. 2557 for point in cdp.cpmg_frqs_list: 2558 # Skip reference points. 2559 if (not ref_flag) and point == None: 2560 continue 2561 2562 # Find a matching experiment ID. 2563 found = False 2564 for id in cdp.exp_type.keys(): 2565 # Skip non-matching experiments. 2566 if cdp.exp_type[id] != exp_type: 2567 continue 2568 2569 # Skip non-matching spectrometer frequencies. 2570 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 2571 continue 2572 2573 # Skip non-matching points. 2574 if cdp.cpmg_frqs[id] != point: 2575 continue 2576 2577 # Found. 2578 found = True 2579 break 2580 2581 # No data. 2582 if not found: 2583 continue 2584 2585 # Add the data. 2586 cpmg_frqs[ei][mi][oi].append(point) 2587 2588 # Convert to a numpy array. 2589 cpmg_frqs[ei][mi][oi] = array(cpmg_frqs[ei][mi][oi], float64) 2590 2591 # Return the data. 2592 return cpmg_frqs
2593 2594
2595 -def return_cpmg_frqs_single(exp_type=None, frq=None, offset=None, time=None, ref_flag=True):
2596 """Return the list of nu_CPMG frequencies. 2597 2598 @keyword exp_type: The experiment type. 2599 @type exp_type: str 2600 @keyword frq: The spectrometer frequency in Hz. 2601 @type frq: float 2602 @keyword offset: The hard pulse offset, if desired. 2603 @type offset: None or float 2604 @keyword time: The relaxation time period. 2605 @type time: float 2606 @keyword ref_flag: A flag which if False will cause the reference spectrum frequency of None to be removed from the list. 2607 @type ref_flag: bool 2608 @return: The list of nu_CPMG frequencies in Hz. 2609 @rtype: numpy rank-1 float64 array 2610 """ 2611 2612 # No data. 2613 if not hasattr(cdp, 'cpmg_frqs_list'): 2614 return None 2615 2616 # Initialise. 2617 cpmg_frqs = [] 2618 2619 # Loop over the points. 2620 for point in cdp.cpmg_frqs_list: 2621 # Skip reference points. 2622 if (not ref_flag) and point == None: 2623 continue 2624 2625 # Find a matching experiment ID. 2626 found = False 2627 for id in cdp.exp_type.keys(): 2628 # Skip non-matching experiments. 2629 if cdp.exp_type[id] != exp_type: 2630 continue 2631 2632 # Skip non-matching spectrometer frequencies. 2633 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 2634 continue 2635 2636 # Skip non-matching offsets. 2637 if offset != None and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 2638 continue 2639 2640 # Skip non-matching time points. 2641 if time != None and hasattr(cdp, 'relax_times') and cdp.relax_times[id] != time: 2642 continue 2643 2644 # Skip non-matching points. 2645 if cdp.cpmg_frqs[id] != point: 2646 continue 2647 2648 # Found. 2649 found = True 2650 break 2651 2652 # No data. 2653 if not found: 2654 continue 2655 2656 # Add the data. 2657 cpmg_frqs.append(point) 2658 2659 # Return the data as a numpy array. 2660 return array(cpmg_frqs, float64)
2661 2662
2663 -def return_index_from_disp_point(value, exp_type=None):
2664 """Convert the dispersion point data into the corresponding index. 2665 2666 @param value: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 2667 @type value: float 2668 @keyword exp_type: The experiment type. 2669 @type exp_type: str 2670 @return: The corresponding index. 2671 @rtype: int 2672 """ 2673 2674 # Check. 2675 if exp_type == None: 2676 raise RelaxError("The experiment type has not been supplied.") 2677 2678 # Initialise. 2679 index = 0 2680 ref_correction = False 2681 2682 # CPMG-type experiments. 2683 if exp_type in EXP_TYPE_LIST_CPMG: 2684 index = cdp.cpmg_frqs_list.index(value) 2685 if None in cdp.cpmg_frqs_list: 2686 ref_correction = True 2687 2688 # R1rho-type experiments. 2689 elif exp_type in EXP_TYPE_LIST_R1RHO: 2690 index = cdp.spin_lock_nu1_list.index(value) 2691 if None in cdp.spin_lock_nu1_list: 2692 ref_correction = True 2693 2694 # Remove the reference point (always at index 0). 2695 for id in loop_spectrum_ids(exp_type=exp_type): 2696 if ref_correction and get_curve_type(id) == 'fixed time': 2697 index -= 1 2698 break 2699 2700 # Return the index. 2701 return index
2702 2703
2704 -def return_index_from_exp_type(exp_type=None):
2705 """Convert the experiment type into the corresponding index. 2706 2707 @keyword exp_type: The experiment type. 2708 @type exp_type: str 2709 @return: The corresponding index. 2710 @rtype: int 2711 """ 2712 2713 # Check. 2714 if exp_type == None: 2715 raise RelaxError("The experiment type has not been supplied.") 2716 2717 # Return the index. 2718 if exp_type in cdp.exp_type_list: 2719 return cdp.exp_type_list.index(exp_type) 2720 2721 # The number of experiments. 2722 num = len(cdp.exp_type_list)
2723 2724
2725 -def return_index_from_frq(value):
2726 """Convert the dispersion point data into the corresponding index. 2727 2728 @param value: The spectrometer frequency in Hz. 2729 @type value: float 2730 @return: The corresponding index. 2731 @rtype: int 2732 """ 2733 2734 # No frequency present. 2735 if value == None: 2736 return 0 2737 2738 # Return the index. 2739 return cdp.spectrometer_frq_list.index(value)
2740 2741
2742 -def return_index_from_disp_point_key(key, exp_type=None):
2743 """Convert the dispersion point key into the corresponding index. 2744 2745 @keyword exp_type: The experiment type. 2746 @type exp_type: str 2747 @param key: The dispersion point or R2eff/R1rho key. 2748 @type key: str 2749 @return: The corresponding index. 2750 @rtype: int 2751 """ 2752 2753 # Check. 2754 if exp_type == None: 2755 raise RelaxError("The experiment type has not been supplied.") 2756 2757 # CPMG-type experiments. 2758 if exp_type in EXP_TYPE_LIST_CPMG: 2759 return return_index_from_disp_point(cdp.cpmg_frqs[key], exp_type=exp_type) 2760 2761 # R1rho-type experiments. 2762 elif exp_type in EXP_TYPE_LIST_R1RHO: 2763 return return_index_from_disp_point(cdp.spin_lock_nu1[key], exp_type=exp_type)
2764 2765
2766 -def return_key_from_di(mi=None, di=None):
2767 """Convert the dispersion point index into the corresponding key. 2768 2769 @keyword mi: The spectrometer frequency index. 2770 @type mi: int 2771 @keyword di: The dispersion point or R2eff/R1rho index. 2772 @type di: int 2773 @return: The corresponding key. 2774 @rtype: str 2775 """ 2776 2777 # Insert the reference point (always at index 0). 2778 if has_fixed_time_exp_type(): 2779 di += 1 2780 2781 # The frequency. 2782 frq = return_value_from_frq_index(mi) 2783 2784 # CPMG data. 2785 if exp_type in EXP_TYPE_LIST_CPMG: 2786 point = cdp.cpmg_frqs_list[di] 2787 points = cdp.cpmg_frqs 2788 2789 # R1rho data. 2790 else: 2791 point = cdp.spin_lock_nu1_list[di] 2792 points = cdp.spin_lock_nu1 2793 2794 # Find the keys matching the dispersion point. 2795 key_list = [] 2796 all_keys = points.keys() 2797 for key in all_keys: 2798 if points[key] == point: 2799 key_list.append(key) 2800 2801 # Return the key. 2802 return key
2803 2804
2805 -def return_offset_data(spins=None, spin_ids=None, field_count=None, fields=None):
2806 """Return numpy arrays of the chemical shifts, offsets and tilt angles. 2807 2808 Indices 2809 ======= 2810 2811 The data structures consist of many different index types. These are: 2812 2813 - Ei: The index for each experiment type. 2814 - Si: The index for each spin of the spin cluster. 2815 - Mi: The index for each magnetic field strength. 2816 - Oi: The index for each spin-lock offset. In the case of CPMG-type data, this index is always zero. 2817 - Di: The index for each dispersion point (either the spin-lock field strength or the nu_CPMG frequency). 2818 2819 2820 @keyword spins: The list of spin containers in the cluster. 2821 @type spins: list of SpinContainer instances 2822 @keyword spin_ids: The list of spin IDs for the cluster. 2823 @type spin_ids: list of str 2824 @keyword field_count: The number of spectrometer field strengths. This may not be equal to the length of the fields list as the user may not have set the field strength. 2825 @type field_count: int 2826 @keyword fields: The spin-lock field strengths to use instead of the user loaded values - to enable interpolation. The dimensions are {Ei, Mi}. 2827 @type fields: rank-2 list of floats 2828 @return: The numpy array structures of the chemical shifts in rad/s {Ei, Si, Mi}, spin-lock offsets in rad/s {Ei, Si, Mi, Oi}, rotating frame tilt angles {Ei, Si, Mi, Oi, Di}, the average resonance offset in the rotating frame in rad/s {Ei, Si, Mi, Oi, Di} and the effective field in rotating frame in rad/s {Ei, Si, Mi, Oi, Di}. 2829 @rtype: rank-3 list of floats, rank-4 list of floats, rank-5 list of floats 2830 """ 2831 2832 # The counts. 2833 exp_num = num_exp_types() 2834 spin_num = 0 2835 for spin in spins: 2836 if spin.select: 2837 spin_num += 1 2838 2839 # Initialise the data structures for the target function. 2840 fields_orig = fields 2841 shifts = [] 2842 offsets = [] 2843 theta = [] 2844 Domega = [] 2845 w_e = [] 2846 for exp_type, ei in loop_exp(return_indices=True): 2847 shifts.append([]) 2848 offsets.append([]) 2849 theta.append([]) 2850 Domega.append([]) 2851 w_e.append([]) 2852 for si in range(spin_num): 2853 shifts[ei].append([]) 2854 offsets[ei].append([]) 2855 theta[ei].append([]) 2856 Domega[ei].append([]) 2857 w_e[ei].append([]) 2858 for frq, mi in loop_frq(return_indices=True): 2859 shifts[ei][si].append(None) 2860 offsets[ei][si].append([]) 2861 theta[ei][si].append([]) 2862 Domega[ei][si].append([]) 2863 w_e[ei][si].append([]) 2864 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 2865 offsets[ei][si][mi].append(None) 2866 theta[ei][si][mi].append([]) 2867 Domega[ei][si][mi].append([]) 2868 w_e[ei][si][mi].append([]) 2869 2870 # Assemble the data. 2871 data_flag = False 2872 si = 0 2873 for spin_index in range(len(spins)): 2874 # Skip deselected spins. 2875 if not spins[spin_index].select: 2876 continue 2877 2878 # Alias the spin. 2879 spin = spins[spin_index] 2880 spin_id = spin_ids[spin_index] 2881 2882 # No data. 2883 shift = 0.0 2884 if hasattr(spin, 'chemical_shift'): 2885 shift = spin.chemical_shift 2886 elif has_r1rho_exp_type(): 2887 warn(RelaxWarning("The chemical shift for the spin '%s' cannot be found. Be careful, it is being set to 0.0 ppm so offset calculations will probably be wrong!" % spin_id)) 2888 2889 # Loop over the experiments and spectrometer frequencies. 2890 data_flag = True 2891 for exp_type, frq, offset, ei, mi, oi in loop_exp_frq_offset(return_indices=True): 2892 # The R1rho and off-resonance R1rho flag. 2893 r1rho_flag = False 2894 if exp_type in EXP_TYPE_LIST_R1RHO: 2895 r1rho_flag = True 2896 r1rho_off_flag = False 2897 if exp_type in [MODEL_DPL94, MODEL_TP02, MODEL_TAP03, MODEL_MP05, MODEL_NS_R1RHO_2SITE]: 2898 r1rho_off_flag = True 2899 2900 # Make sure offset data exists for off-resonance R1rho-type experiments. 2901 if r1rho_off_flag and not hasattr(cdp, 'spin_lock_offset'): 2902 raise RelaxError("The spin-lock offsets have not been set.") 2903 2904 # The spin-lock data. 2905 if fields_orig != None: 2906 fields = fields_orig[ei][mi][oi] 2907 else: 2908 if not r1rho_flag: 2909 fields = return_cpmg_frqs_single(exp_type=exp_type, frq=frq, offset=offset, ref_flag=False) 2910 else: 2911 fields = return_spin_lock_nu1_single(exp_type=exp_type, frq=frq, offset=offset, ref_flag=False) 2912 2913 # Convert the shift from ppm to rad/s and store it. 2914 shifts[ei][si][mi] = frequency_to_rad_per_s(frq=shift, B0=frq, isotope=spin.isotope) 2915 2916 # Find a matching experiment ID. 2917 found = False 2918 for id in cdp.exp_type.keys(): 2919 # Skip non-matching experiments. 2920 if cdp.exp_type[id] != exp_type: 2921 continue 2922 2923 # Skip non-matching spectrometer frequencies. 2924 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 2925 continue 2926 2927 # Skip non-matching offsets. 2928 if r1rho_flag and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 2929 continue 2930 2931 # Found. 2932 found = True 2933 break 2934 2935 # No data. 2936 if not found: 2937 continue 2938 2939 # Store the offset in rad/s. Only once and using the first key. 2940 if offsets[ei][si][mi][oi] == None: 2941 if r1rho_flag and hasattr(cdp, 'spin_lock_offset'): 2942 offsets[ei][si][mi][oi] = frequency_to_rad_per_s(frq=cdp.spin_lock_offset[id], B0=frq, isotope=spin.isotope) 2943 else: 2944 offsets[ei][si][mi][oi] = 0.0 2945 2946 # Loop over the dispersion points. 2947 for di in range(len(fields)): 2948 # Alias the point. 2949 point = fields[di] 2950 2951 # Skip reference spectra. 2952 if point == None: 2953 continue 2954 2955 # Calculate the tilt angle. 2956 omega1 = point * 2.0 * pi 2957 Delta_omega = shifts[ei][si][mi] - offsets[ei][si][mi][oi] 2958 Domega[ei][si][mi][oi].append(Delta_omega) 2959 if Delta_omega == 0.0: 2960 theta[ei][si][mi][oi].append(pi / 2.0) 2961 # Calculate the theta angle describing the tilted rotating frame relative to the laboratory. 2962 # theta = atan(omega1 / Delta_omega). 2963 # If Delta_omega is negative, there follow the symmetry of atan, that atan(-x) = - atan(x). 2964 # Then it should be: theta = pi + atan(-x) = pi - atan(x) = pi - abs(atan( +/- x)). 2965 # This is taken care of with the atan2(y, x) function, which return atan(y / x), in radians, and the result is between -pi and pi. 2966 else: 2967 theta[ei][si][mi][oi].append(atan2(omega1, Delta_omega)) 2968 2969 # Calculate effective field in rotating frame 2970 w_eff = sqrt( Delta_omega*Delta_omega + omega1*omega1 ) 2971 w_e[ei][si][mi][oi].append(w_eff) 2972 2973 # Increment the spin index. 2974 si += 1 2975 2976 # No shift data for the spin cluster. 2977 if not data_flag: 2978 return None, None, None 2979 2980 # Convert to numpy arrays. 2981 #for ei in range(exp_num): 2982 # for si in range(spin_num): 2983 # for mi in range(field_count): 2984 # theta[ei][si][mi] = array(theta[ei][si][mi], float64) 2985 2986 # Return the structures. 2987 return shifts, offsets, theta, Domega, w_e
2988 2989
2990 -def return_param_key_from_data(exp_type=None, frq=0.0, offset=0.0, point=0.0):
2991 """Generate the unique key from the spectrometer frequency and dispersion point. 2992 2993 @keyword exp_type: The experiment type. 2994 @type exp_type: str 2995 @keyword frq: The spectrometer frequency in Hz. 2996 @type frq: float 2997 @keyword offset: The optional offset value for off-resonance R1rho-type data. 2998 @type offset: None or float 2999 @keyword point: The dispersion point data (either the spin-lock field strength in Hz or the nu_CPMG frequency in Hz). 3000 @type point: float 3001 @return: The unique key. 3002 @rtype: str 3003 """ 3004 3005 # Convert the experiment type. 3006 if exp_type == None: 3007 raise RelaxError("The experiment type must be supplied.") 3008 exp_type = exp_type.replace(' ', '_').lower() 3009 3010 # Convert None values. 3011 if frq == None: 3012 frq = 0.0 3013 if offset == None: 3014 offset = 0.0 3015 if point == None: 3016 point = 0.0 3017 3018 # Generate the unique key. 3019 key = "%s_%.8f_%.3f_%.3f" % (exp_type, frq/1e6, offset, point) 3020 3021 # Return the unique key. 3022 return key
3023 3024
3025 -def return_r1_data(spins=None, spin_ids=None, field_count=None, sim_index=None):
3026 """Return the R1 data structures for off-resonance R1rho experiments. 3027 3028 @keyword spins: The list of spin containers in the cluster. 3029 @type spins: list of SpinContainer instances 3030 @keyword spin_ids: The list of spin IDs for the cluster. 3031 @type spin_ids: list of str 3032 @keyword field_count: The number of spectrometer field strengths. This may not be equal to the length of the fields list as the user may not have set the field strength. 3033 @type field_count: int 3034 @keyword sim_index: The index of the simulation to return the R1 data of. This should be None if the normal data is required. 3035 @type sim_index: None or int 3036 @return: The R1 relaxation data. 3037 @rtype: numpy rank-2 float array 3038 """ 3039 3040 # The spin count. 3041 spin_num = count_spins(spins) 3042 3043 # Initialise the data structure. 3044 r1 = -ones((spin_num, field_count), float64) 3045 3046 # Check for the presence of data. 3047 if not hasattr(cdp, 'ri_ids'): 3048 if has_r1rho_exp_type(): 3049 warn(RelaxWarning("No R1 relaxation data has been loaded. This is essential for the proper handling of offsets in off-resonance R1rho experiments.")) 3050 return 0.0 * r1 3051 3052 # Loop over the Rx IDs. 3053 flags = [False]*field_count 3054 for ri_id in cdp.ri_ids: 3055 # Only use R1 data. 3056 if cdp.ri_type[ri_id] != 'R1': 3057 continue 3058 3059 # The frequency. 3060 frq = cdp.spectrometer_frq[ri_id] 3061 mi = return_index_from_frq(frq) 3062 3063 # Flip the flag. 3064 flags[mi] = True 3065 3066 # Spin loop. 3067 for si in range(spin_num): 3068 # FIXME: This is a kludge - the data randomisation needs to be incorporated into the dispersion base_data_loop() method and the standard Monte Carlo simulation pathway used. 3069 # Randomise the R1 data, when required. 3070 if sim_index != None and (not hasattr(spins[si], 'ri_data_sim') or ri_id not in spins[si].ri_data_sim): 3071 randomise_R1(spin=spins[si], ri_id=ri_id, N=cdp.sim_number) 3072 3073 # Store the data. 3074 if sim_index != None: 3075 r1[si, mi] = spins[si].ri_data_sim[ri_id][sim_index] 3076 else: 3077 r1[si, mi] = spins[si].ri_data[ri_id] 3078 3079 # Check the data to prevent user mistakes. 3080 for mi in range(field_count): 3081 # The frequency. 3082 frq = return_value_from_frq_index(mi=mi) 3083 3084 # Check for R1 data for this frequency. 3085 if not flags[mi]: 3086 raise RelaxError("R1 data for the %.1f MHz field strength cannot be found." % (frq/1e6)) 3087 3088 # Check the spin data. 3089 for si in range(spin_num): 3090 if r1[si, mi] == -1.0: 3091 raise RelaxError("R1 data for the '%s' spin at %.1f MHz field strength cannot be found." % (spin_ids[si], frq/1e6)) 3092 3093 # Return the data. 3094 return r1
3095 3096
3097 -def return_r2eff_arrays(spins=None, spin_ids=None, fields=None, field_count=None, sim_index=None):
3098 """Return numpy arrays of the R2eff/R1rho values and errors. 3099 3100 @keyword spins: The list of spin containers in the cluster. 3101 @type spins: list of SpinContainer instances 3102 @keyword spin_ids: The list of spin IDs for the cluster. 3103 @type spin_ids: list of str 3104 @keyword fields: The list of spectrometer field strengths. 3105 @type fields: list of float 3106 @keyword field_count: The number of spectrometer field strengths. This may not be equal to the length of the fields list as the user may not have set the field strength. 3107 @type field_count: int 3108 @keyword sim_index: The index of the simulation to return the data of. This should be None if the normal data is required. 3109 @type sim_index: None or int 3110 @return: The numpy array structures of the R2eff/R1rho values, errors, missing data, and corresponding Larmor frequencies. For each structure, the first dimension corresponds to the experiment types, the second the spins of a spin block, the third to the spectrometer field strength, and the fourth is the dispersion points. For the Larmor frequency structure, the fourth dimension is omitted. For R1rho-type data, an offset dimension is inserted between the spectrometer field strength and the dispersion points. 3111 @rtype: lists of numpy float arrays, lists of numpy float arrays, lists of numpy float arrays, numpy rank-2 int array 3112 """ 3113 3114 # The counts. 3115 exp_num = num_exp_types() 3116 spin_num = count_spins(spins) 3117 3118 # 1H MMQ flag. 3119 proton_mmq_flag = has_proton_mmq_cpmg() 3120 3121 # Initialise the data structures for the target function. 3122 exp_types = [] 3123 values = [] 3124 errors = [] 3125 missing = [] 3126 frqs = [] 3127 frqs_H = [] 3128 relax_times = [] 3129 for exp_type, ei in loop_exp(return_indices=True): 3130 values.append([]) 3131 errors.append([]) 3132 missing.append([]) 3133 frqs.append([]) 3134 frqs_H.append([]) 3135 relax_times.append([]) 3136 for si in range(spin_num): 3137 values[ei].append([]) 3138 errors[ei].append([]) 3139 missing[ei].append([]) 3140 frqs[ei].append([]) 3141 frqs_H[ei].append([]) 3142 for frq, mi in loop_frq(return_indices=True): 3143 values[ei][si].append([]) 3144 errors[ei][si].append([]) 3145 missing[ei][si].append([]) 3146 frqs[ei][si].append(0.0) 3147 frqs_H[ei][si].append(0.0) 3148 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 3149 values[ei][si][mi].append([]) 3150 errors[ei][si][mi].append([]) 3151 missing[ei][si][mi].append([]) 3152 for mi in range(field_count): 3153 relax_times[ei].append(None) 3154 3155 # Pack the R2eff/R1rho data. 3156 data_flag = False 3157 si = 0 3158 for spin_index in range(len(spins)): 3159 # Skip deselected spins. 3160 if not spins[spin_index].select: 3161 continue 3162 3163 # Alias the spin. 3164 spin = spins[spin_index] 3165 spin_id = spin_ids[spin_index] 3166 3167 # Get the attached proton. 3168 proton = None 3169 if proton_mmq_flag: 3170 # Get all protons. 3171 proton_spins = return_attached_protons(spin_id) 3172 3173 # Only one allowed. 3174 if len(proton_spins) > 1: 3175 raise RelaxError("Only one attached proton is supported for the MMQ-type models.") 3176 3177 # Missing proton. 3178 if not len(proton_spins): 3179 raise RelaxError("No proton attached to the spin '%s' could be found. This is required for the MMQ-type models." % spin_id) 3180 3181 # Alias the single proton. 3182 proton = proton_spins[0] 3183 3184 # No data. 3185 if not hasattr(spin, 'r2eff') and not hasattr(proton, 'r2eff'): 3186 continue 3187 data_flag = True 3188 3189 # No isotope information. 3190 if not hasattr(spin, 'isotope'): 3191 raise RelaxSpinTypeError(spin_id=spin_ids[si]) 3192 3193 # Loop over the R2eff data. 3194 for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True): 3195 3196 # Alias the correct spin. 3197 current_spin = spin 3198 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 3199 current_spin = proton 3200 3201 # Add the experiment type. 3202 if exp_type not in exp_types: 3203 exp_types.append(exp_type) 3204 3205 # The key. 3206 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 3207 if mi == 0: 3208 fact = 60.83831274541046 3209 else: 3210 fact = 81.11775032721394 3211 3212 # The Larmor frequency for this spin (and that of an attached proton for the MMQ models) and field strength (in MHz*2pi to speed up the ppm to rad/s conversion). 3213 if frq != None: 3214 frqs[ei][si][mi] = 2.0 * pi * frq / g1H * return_gyromagnetic_ratio(spin.isotope) * 1e-6 3215 frqs_H[ei][si][mi] = 2.0 * pi * frq * 1e-6 3216 3217 # Missing data. 3218 if key not in current_spin.r2eff.keys(): 3219 values[ei][si][mi][oi].append(0.0) 3220 errors[ei][si][mi][oi].append(1.0) 3221 missing[ei][si][mi][oi].append(1) 3222 continue 3223 else: 3224 missing[ei][si][mi][oi].append(0) 3225 3226 # The values. 3227 if sim_index == None: 3228 values[ei][si][mi][oi].append(current_spin.r2eff[key]) 3229 else: 3230 values[ei][si][mi][oi].append(current_spin.r2eff_sim[sim_index][key]) 3231 3232 # The errors. 3233 errors[ei][si][mi][oi].append(current_spin.r2eff_err[key]) 3234 3235 # The relaxation times. 3236 for id in cdp.spectrum_ids: 3237 # Non-matching data. 3238 if cdp.spectrometer_frq[id] != frq: 3239 continue 3240 if cdp.exp_type[id] != exp_type: 3241 continue 3242 if exp_type in EXP_TYPE_LIST_CPMG: 3243 if id not in cdp.cpmg_frqs.keys() or cdp.cpmg_frqs[id] != point: 3244 continue 3245 else: 3246 if id not in cdp.spin_lock_nu1.keys() or cdp.spin_lock_nu1[id] != point: 3247 continue 3248 3249 # Found. 3250 relax_time = cdp.relax_times[id] 3251 break 3252 3253 # Check the value if already set. 3254 if relax_times[ei][mi] != None: 3255 if relax_times[ei][mi] != relax_time: 3256 raise RelaxError("The relaxation times do not match for all experiments.") 3257 continue 3258 3259 # Store the time. 3260 relax_times[ei][mi] = relax_time 3261 3262 # Increment the spin index. 3263 si += 1 3264 3265 # No R2eff/R1rho data for the spin cluster. 3266 if not data_flag: 3267 raise RelaxError("No R2eff/R1rho data could be found for the spin cluster %s." % spin_ids) 3268 3269 # Convert to numpy arrays. 3270 relax_times = array(relax_times, float64) 3271 for exp_type, ei in loop_exp(return_indices=True): 3272 for si in range(spin_num): 3273 for frq, mi in loop_frq(return_indices=True): 3274 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 3275 values[ei][si][mi][oi] = array(values[ei][si][mi][oi], float64) 3276 errors[ei][si][mi][oi] = array(errors[ei][si][mi][oi], float64) 3277 missing[ei][si][mi][oi] = array(missing[ei][si][mi][oi], int32) 3278 3279 # Return the structures. 3280 return values, errors, missing, frqs, frqs_H, exp_types, relax_times
3281 3282
3283 -def return_relax_times():
3284 """Return the list of relaxation times. 3285 3286 @return: The list of relaxation times in s. 3287 @rtype: numpy rank-2 float64 array 3288 """ 3289 3290 # No data. 3291 if not hasattr(cdp, 'relax_times'): 3292 return None 3293 3294 # Initialise. 3295 relax_times = zeros((count_exp(), count_frq()), float64) 3296 3297 # Loop over the experiment types. 3298 for exp_type, frq, point, time, ei, mi, di, ti in loop_exp_frq_point_time(return_indices=True): 3299 # Fetch all of the matching intensity keys. 3300 keys = find_intensity_keys(exp_type=exp_type, frq=frq, point=point, time=time, raise_error=False) 3301 3302 # No data. 3303 if not len(keys): 3304 continue 3305 3306 # Add the data. 3307 relax_times[ei][mi] = cdp.relax_times[keys[0]] 3308 3309 # Return the data. 3310 return relax_times
3311 3312
3313 -def return_spin_lock_nu1(ref_flag=True):
3314 """Return the list of spin-lock field strengths. 3315 3316 @keyword ref_flag: A flag which if False will cause the reference spectrum frequency of None to be removed from the list. 3317 @type ref_flag: bool 3318 @return: The list of spin-lock field strengths in Hz. It has the dimensions {Ei, Mi, Oi}. 3319 @rtype: rank-2 list of numpy rank-1 float64 arrays 3320 """ 3321 3322 # No data. 3323 if not hasattr(cdp, 'spin_lock_nu1_list'): 3324 return None 3325 3326 # Initialise. 3327 nu1 = [] 3328 3329 # First loop over the experiment types. 3330 for exp_type, ei in loop_exp(return_indices=True): 3331 # Add a new dimension. 3332 nu1.append([]) 3333 3334 # Then loop over the spectrometer frequencies. 3335 for frq, mi in loop_frq(return_indices=True): 3336 # Add a new dimension. 3337 nu1[ei].append([]) 3338 3339 # Loop over the offsets. 3340 for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True): 3341 # Add a new dimension. 3342 nu1[ei][mi].append([]) 3343 3344 # Loop over the fields. 3345 for point in cdp.spin_lock_nu1_list: 3346 # Skip reference points. 3347 if (not ref_flag) and point == None: 3348 continue 3349 3350 # Find a matching experiment ID. 3351 found = False 3352 for id in cdp.exp_type.keys(): 3353 # Skip non-matching experiments. 3354 if cdp.exp_type[id] != exp_type: 3355 continue 3356 3357 # Skip non-matching spectrometer frequencies. 3358 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 3359 continue 3360 3361 # Skip non-matching offsets. 3362 if offset != None and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 3363 continue 3364 3365 # Skip non-matching points. 3366 if cdp.spin_lock_nu1[id] != point: 3367 continue 3368 3369 # Found. 3370 found = True 3371 break 3372 3373 # No data. 3374 if not found: 3375 continue 3376 3377 # Add the data. 3378 nu1[ei][mi][oi].append(point) 3379 3380 # Convert to a numpy array. 3381 nu1[ei][mi][oi] = array(nu1[ei][mi][oi], float64) 3382 3383 # Return the data. 3384 return nu1
3385 3386
3387 -def return_spin_lock_nu1_single(exp_type=None, frq=None, offset=None, ref_flag=True):
3388 """Return the list of spin-lock field strengths. 3389 3390 @keyword exp_type: The experiment type. 3391 @type exp_type: str 3392 @keyword frq: The spectrometer frequency in Hz. 3393 @type frq: float 3394 @keyword offset: The spin-lock offset. 3395 @type offset: None or float 3396 @keyword ref_flag: A flag which if False will cause the reference spectrum frequency of None to be removed from the list. 3397 @type ref_flag: bool 3398 @return: The list of spin-lock field strengths in Hz. 3399 @rtype: numpy rank-1 float64 array 3400 """ 3401 3402 # No data. 3403 if not hasattr(cdp, 'spin_lock_nu1_list'): 3404 return None 3405 3406 # Initialise. 3407 nu1 = [] 3408 3409 # Loop over the points. 3410 for point in cdp.spin_lock_nu1_list: 3411 # Skip reference points. 3412 if (not ref_flag) and point == None: 3413 continue 3414 3415 # Find a matching experiment ID. 3416 found = False 3417 for id in cdp.exp_type.keys(): 3418 # Skip non-matching experiments. 3419 if cdp.exp_type[id] != exp_type: 3420 continue 3421 3422 # Skip non-matching spectrometer frequencies. 3423 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 3424 continue 3425 3426 # Skip non-matching offsets. 3427 if offset != None and hasattr(cdp, 'spin_lock_offset') and cdp.spin_lock_offset[id] != offset: 3428 continue 3429 3430 # Skip non-matching points. 3431 if cdp.spin_lock_nu1[id] != point: 3432 continue 3433 3434 # Found. 3435 found = True 3436 break 3437 3438 # No data. 3439 if not found: 3440 continue 3441 3442 # Add the data. 3443 nu1.append(point) 3444 3445 # Return the data as a numpy array. 3446 return array(nu1, float64)
3447 3448
3449 -def return_value_from_frq_index(mi=None):
3450 """Return the spectrometer frequency corresponding to the frequency index. 3451 3452 @keyword mi: The spectrometer frequency index. 3453 @type mi: int 3454 @return: The spectrometer frequency in Hertz or None if no information is present. 3455 @rtype: float 3456 """ 3457 3458 # No data. 3459 if not hasattr(cdp, 'spectrometer_frq_list'): 3460 return None 3461 3462 # Return the field. 3463 return cdp.spectrometer_frq_list[mi]
3464 3465
3466 -def return_value_from_offset_index(ei=None, mi=None, oi=None):
3467 """Return the offset corresponding to the offset index. 3468 3469 @keyword ei: The experiment type index. 3470 @type ei: int 3471 @keyword mi: The spectrometer frequency index. 3472 @type mi: int 3473 @keyword oi: The offset index. 3474 @type oi: int 3475 @return: The offset in Hertz or None if no information is present. 3476 @rtype: float 3477 """ 3478 3479 # Checks. 3480 if ei == None: 3481 raise RelaxError("The experiment type index must be supplied.") 3482 if mi == None: 3483 raise RelaxError("The spectrometer frequency index must be supplied.") 3484 3485 # Initialise the index. 3486 new_oi = -1 3487 3488 # The experiment type and frequency. 3489 exp_type = cdp.exp_type_list[ei] 3490 frq = return_value_from_frq_index(mi) 3491 3492 # CPMG-type data. 3493 if exp_type in EXP_TYPE_LIST_CPMG: 3494 # Return zero until hard pulse offset handling is implemented. 3495 return 0.0 3496 3497 # R1rho-type data. 3498 if exp_type in EXP_TYPE_LIST_R1RHO: 3499 # No offsets. 3500 if not hasattr(cdp, 'spin_lock_offset'): 3501 return None 3502 3503 # Loop over the offset data. 3504 for offset in cdp.spin_lock_offset_list: 3505 # Increment the index. 3506 new_oi += 1 3507 3508 # Find a matching experiment ID. 3509 found = False 3510 for id in cdp.exp_type.keys(): 3511 # Skip non-matching experiments. 3512 if cdp.exp_type[id] != exp_type: 3513 continue 3514 3515 # Skip non-matching spectrometer frequencies. 3516 if hasattr(cdp, 'spectrometer_frq') and cdp.spectrometer_frq[id] != frq: 3517 continue 3518 3519 # Skip non-matching offsets. 3520 if new_oi != oi: 3521 continue 3522 3523 # Found. 3524 found = True 3525 break 3526 3527 # No data. 3528 if not found: 3529 continue 3530 3531 # Return the offset. 3532 return offset
3533 3534
3535 -def set_exp_type(spectrum_id=None, exp_type=None):
3536 """Select the relaxation dispersion experiment type performed. 3537 3538 @keyword spectrum_id: The spectrum ID string. 3539 @type spectrum_id: str 3540 @keyword exp: The relaxation dispersion experiment type. 3541 @type exp: str 3542 """ 3543 3544 # Data checks. 3545 pipes.test() 3546 3547 # Add the spectrum ID to the data store if needed. 3548 add_spectrum_id(spectrum_id) 3549 3550 # Check the experiment type. 3551 if exp_type not in EXP_TYPE_LIST: 3552 raise RelaxError("The relaxation dispersion experiment '%s' is invalid, it must be one of %s." % (exp_type, EXP_TYPE_LIST)) 3553 3554 # Initialise the experiment type data structures if needed. 3555 if not hasattr(cdp, 'exp_type'): 3556 cdp.exp_type = {} 3557 if not hasattr(cdp, 'exp_type_list'): 3558 cdp.exp_type_list = [] 3559 3560 # Store the value. 3561 cdp.exp_type[spectrum_id] = exp_type 3562 3563 # Unique experiments. 3564 if cdp.exp_type[spectrum_id] not in cdp.exp_type_list: 3565 cdp.exp_type_list.append(cdp.exp_type[spectrum_id]) 3566 3567 # Printout. 3568 text = "The spectrum ID '%s' is now set to " % spectrum_id 3569 if exp_type == EXP_TYPE_CPMG_SQ: 3570 text += EXP_TYPE_DESC_CPMG_SQ + "." 3571 elif exp_type == EXP_TYPE_CPMG_MQ: 3572 text += EXP_TYPE_DESC_CPMG_MQ + "." 3573 elif exp_type == EXP_TYPE_CPMG_DQ: 3574 text += EXP_TYPE_DESC_CPMG_DQ + "." 3575 elif exp_type == EXP_TYPE_CPMG_ZQ: 3576 text += EXP_TYPE_DESC_CPMG_ZQ + "." 3577 elif exp_type == EXP_TYPE_CPMG_PROTON_SQ: 3578 text += EXP_TYPE_DESC_CPMG_PROTON_SQ + "." 3579 elif exp_type == EXP_TYPE_CPMG_PROTON_MQ: 3580 text += EXP_TYPE_DESC_CPMG_PROTON_MQ + "." 3581 elif exp_type == EXP_TYPE_R1RHO: 3582 text += EXP_TYPE_DESC_R1RHO + "." 3583 print(text)
3584 3585
3586 -def spin_has_frq_data(spin=None, frq=None):
3587 """Determine if the spin has intensity data for the given spectrometer frequency. 3588 3589 @keyword spin: The specific spin data container. 3590 @type spin: SpinContainer instance 3591 @keyword frq: The spectrometer frequency. 3592 @type frq: float 3593 @return: True if data for that spectrometer frequency is present, False otherwise. 3594 @rtype: bool 3595 """ 3596 3597 # Loop over the intensity data. 3598 for key in spin.peak_intensity.keys(): 3599 if key in cdp.spectrometer_frq and cdp.spectrometer_frq[key] == frq: 3600 return True 3601 3602 # No data. 3603 return False
3604 3605
3606 -def spin_ids_to_containers(spin_ids):
3607 """Take the list of spin IDs and return the corresponding spin containers. 3608 3609 This is useful for handling the data from the model_loop() method. 3610 3611 3612 @param spin_ids: The list of spin ID strings. 3613 @type spin_ids: list of str 3614 @return: The list of spin containers. 3615 @rtype: list of SpinContainer instances 3616 """ 3617 3618 # Loop over the IDs and fetch the container. 3619 spins = [] 3620 for id in spin_ids: 3621 spins.append(return_spin(id)) 3622 3623 # Return the containers. 3624 return spins
3625 3626
3627 -def spin_lock_field(spectrum_id=None, field=None):
3628 """Set the spin-lock field strength (nu1) for the given spectrum. 3629 3630 @keyword spectrum_id: The spectrum ID string. 3631 @type spectrum_id: str 3632 @keyword field: The spin-lock field strength (nu1) in Hz. 3633 @type field: int or float 3634 """ 3635 3636 # Test if the spectrum ID exists. 3637 if spectrum_id not in cdp.spectrum_ids: 3638 raise RelaxNoSpectraError(spectrum_id) 3639 3640 # Initialise the global nu1 data structures if needed. 3641 if not hasattr(cdp, 'spin_lock_nu1'): 3642 cdp.spin_lock_nu1 = {} 3643 if not hasattr(cdp, 'spin_lock_nu1_list'): 3644 cdp.spin_lock_nu1_list = [] 3645 3646 # Add the frequency, converting to a float if needed. 3647 if field == None: 3648 cdp.spin_lock_nu1[spectrum_id] = field 3649 else: 3650 cdp.spin_lock_nu1[spectrum_id] = float(field) 3651 3652 # The unique curves for the R2eff fitting (R1rho). 3653 if cdp.spin_lock_nu1[spectrum_id] not in cdp.spin_lock_nu1_list: 3654 cdp.spin_lock_nu1_list.append(cdp.spin_lock_nu1[spectrum_id]) 3655 3656 # Sort the list (handling None for Python 3). 3657 flag = False 3658 if None in cdp.spin_lock_nu1_list: 3659 cdp.spin_lock_nu1_list.pop(cdp.spin_lock_nu1_list.index(None)) 3660 flag = True 3661 cdp.spin_lock_nu1_list.sort() 3662 if flag: 3663 cdp.spin_lock_nu1_list.insert(0, None) 3664 3665 # Update the exponential curve count (skipping the reference if present). 3666 cdp.dispersion_points = len(cdp.spin_lock_nu1_list) 3667 if None in cdp.spin_lock_nu1_list: 3668 cdp.dispersion_points -= 1 3669 3670 # Printout. 3671 if field == None: 3672 print("The spectrum ID '%s' is set to the reference." % spectrum_id) 3673 else: 3674 print("The spectrum ID '%s' spin-lock field strength is set to %s kHz." % (spectrum_id, cdp.spin_lock_nu1[spectrum_id]/1000.0))
3675 3676
3677 -def spin_lock_offset(spectrum_id=None, offset=None):
3678 """Set the spin-lock offset (omega_rf) for the given spectrum. 3679 3680 @keyword spectrum_id: The spectrum ID string. 3681 @type spectrum_id: str 3682 @keyword offset: The spin-lock offset (omega_rf) in ppm. 3683 @type offset: int or float 3684 """ 3685 3686 # Test if the spectrum ID exists. 3687 if spectrum_id not in cdp.spectrum_ids: 3688 raise RelaxNoSpectraError(spectrum_id) 3689 3690 # Initialise the global offset data structures if needed. 3691 if not hasattr(cdp, 'spin_lock_offset'): 3692 cdp.spin_lock_offset = {} 3693 if not hasattr(cdp, 'spin_lock_offset_list'): 3694 cdp.spin_lock_offset_list = [] 3695 3696 # Add the offset, converting to a float if needed. 3697 if offset == None: 3698 raise RelaxError("The offset value must be provided.") 3699 cdp.spin_lock_offset[spectrum_id] = float(offset) 3700 3701 # The unique curves for the R2eff fitting (R1rho). 3702 if cdp.spin_lock_offset[spectrum_id] not in cdp.spin_lock_offset_list: 3703 cdp.spin_lock_offset_list.append(cdp.spin_lock_offset[spectrum_id]) 3704 3705 # Sort the list. 3706 cdp.spin_lock_offset_list.sort() 3707 3708 # Printout. 3709 print("Setting the '%s' spectrum spin-lock offset to %s ppm." % (spectrum_id, cdp.spin_lock_offset[spectrum_id]))
3710 3711
3712 -def write_disp_curves(dir=None, force=None):
3713 """Write out the dispersion curves to text files. 3714 3715 One file will be created per spin system. 3716 3717 3718 @keyword dir: The optional directory to place the file into. 3719 @type dir: str 3720 @param force: If True, the files will be overwritten if they already exists. 3721 @type force: bool 3722 """ 3723 3724 # Checks. 3725 pipes.test() 3726 check_mol_res_spin_data() 3727 3728 # The formatting strings. 3729 format_head = "# %-18s %-20s %-20s %-20s %-20s %-20s\n" 3730 format = "%-20s %20s %20s %20s %20s %20s\n" 3731 3732 # 1H MMQ flag. 3733 proton_mmq_flag = has_proton_mmq_cpmg() 3734 3735 # Loop over each spin. 3736 for spin, spin_id in spin_loop(return_id=True, skip_desel=True): 3737 # Skip protons for MMQ data. 3738 if spin.model in MODEL_LIST_MMQ and spin.isotope == '1H': 3739 continue 3740 3741 # Define writing variables. 3742 writing_vars = [['disp', ("Experiment_name", "Field_strength_(MHz)", "Disp_point_(Hz)", "R2eff_(measured)", "R2eff_(back_calc)", "R2eff_errors")]] 3743 3744 # If the model is of R1rho type, then also write as R2eff as function of theta. 3745 if spin.model in MODEL_LIST_R1RHO_FULL and has_r1rho_exp_type() and hasattr(spin, 'isotope'): 3746 # Add additonal looping over writing parameters. 3747 writing_vars.append(['disp_theta', ("Experiment_name", "Field_strength_(MHz)", "Tilt_angle_(rad)", "R2eff_(measured)", "R2eff_(back_calc)", "R2eff_errors")]) 3748 #writing_vars.append(['disp_w_eff',("Experiment_name", "Field_strength_(MHz)", "Effective_field_(rad_s-1))", "R2eff_(measured)", "R2eff_(back_calc)", "R2eff_errors")]) 3749 3750 # Loop over writing vars 3751 for wvar in writing_vars: 3752 # Get the attached proton. 3753 proton = None 3754 if proton_mmq_flag: 3755 proton = return_attached_protons(spin_id)[0] 3756 3757 # The unique file name. 3758 file_name = "%s%s.out" % (wvar[0], spin_id.replace('#', '_').replace(':', '_').replace('@', '_')) 3759 3760 # Open the file for writing. 3761 file_path = get_file_path(file_name, dir) 3762 file = open_write_file(file_name, dir, force) 3763 3764 # Write a header. 3765 file.write(format_head % wvar[1]) 3766 3767 # Loop over the dispersion points. 3768 for exp_type, frq, offset, point, ei, mi, oi, di in loop_exp_frq_offset_point(return_indices=True): 3769 # Alias the correct spin. 3770 current_spin = spin 3771 if exp_type in [EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_CPMG_PROTON_MQ]: 3772 current_spin = proton 3773 3774 # The data key. 3775 key = return_param_key_from_data(exp_type=exp_type, frq=frq, offset=offset, point=point) 3776 3777 # Format the R2eff data. 3778 r2eff = "-" 3779 if hasattr(current_spin, 'r2eff') and key in current_spin.r2eff: 3780 r2eff = "%.15f" % current_spin.r2eff[key] 3781 3782 # Format the R2eff back calc data. 3783 r2eff_bc = "-" 3784 if hasattr(current_spin, 'r2eff_bc') and key in current_spin.r2eff_bc: 3785 r2eff_bc = "%.15f" % current_spin.r2eff_bc[key] 3786 3787 # Format the R2eff errors. 3788 r2eff_err = "-" 3789 if hasattr(current_spin, 'r2eff_err') and key in current_spin.r2eff_err: 3790 r2eff_err = "%.15f" % current_spin.r2eff_err[key] 3791 3792 # Define value to be written. 3793 if wvar[0] == 'disp_theta': 3794 theta_spin_dic, Domega_spin_dic, w_eff_spin_dic, dic_key_list = calc_rotating_frame_params(spin=spin) 3795 value = theta_spin_dic[key] 3796 elif wvar[0] == 'disp_w_eff': 3797 theta_spin_dic, Domega_spin_dic, w_eff_spin_dic, dic_key_list = calc_rotating_frame_params(spin=spin) 3798 value = w_eff_spin_dic[key] 3799 # Else use the standard dispersion point data. 3800 else: 3801 value = point 3802 3803 # Write out the data. 3804 frq_text = "%.9f" % (frq/1e6) 3805 value_text = "%.6f" % value 3806 file.write(format % (repr(exp_type), frq_text, value_text, r2eff, r2eff_bc, r2eff_err)) 3807 3808 # Close the file. 3809 file.close() 3810 3811 # Add the file to the results file list. 3812 add_result_file(type='text', label='Text', file=file_path)
3813