Package generic_fns :: Module relax_data
[hide private]
[frames] | no frames]

Source Code for Module generic_fns.relax_data

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2003-2013 Edward d'Auvergne                                   # 
   4  #                                                                             # 
   5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
   6  #                                                                             # 
   7  # This program is free software: you can redistribute it and/or modify        # 
   8  # it under the terms of the GNU General Public License as published by        # 
   9  # the Free Software Foundation, either version 3 of the License, or           # 
  10  # (at your option) any later version.                                         # 
  11  #                                                                             # 
  12  # This program is distributed in the hope that it will be useful,             # 
  13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  15  # GNU General Public License for more details.                                # 
  16  #                                                                             # 
  17  # You should have received a copy of the GNU General Public License           # 
  18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
  19  #                                                                             # 
  20  ############################################################################### 
  21   
  22  # Module docstring. 
  23  """Module for the manipulation of relaxation data.""" 
  24   
  25  # Python module imports. 
  26  from copy import deepcopy 
  27  from math import modf 
  28  from numpy import array, float64, int32, ones, zeros 
  29  import string 
  30  import sys 
  31  from warnings import warn 
  32   
  33  # relax module imports. 
  34  from data import Relax_data_store; ds = Relax_data_store() 
  35  from data.exp_info import ExpInfo 
  36  from generic_fns import bmrb, dipole_pair 
  37  from generic_fns.interatomic import create_interatom, return_interatom, return_interatom_list 
  38  from generic_fns.mol_res_spin import Selection, create_spin, exists_mol_res_spin_data, find_index, generate_spin_id_unique, get_molecule_names, return_spin, return_spin_from_selection, spin_index_loop, spin_loop 
  39  from generic_fns import pipes 
  40  from generic_fns import value 
  41  from physical_constants import element_from_isotope, number_from_isotope 
  42  from relax_errors import RelaxError, RelaxMultiSpinIDError, RelaxNoRiError, RelaxNoSequenceError, RelaxNoSpinError, RelaxRiError 
  43  from relax_io import read_spin_data, write_data 
  44  from relax_warnings import RelaxWarning 
  45  import specific_fns 
  46   
  47   
  48  # The relaxation data types supported. 
  49  VALID_TYPES = ['R1', 'R2', 'NOE'] 
  50   
  51   
  52   
53 -def back_calc(ri_id=None, ri_type=None, frq=None):
54 """Back calculate the relaxation data. 55 56 If no relaxation data currently exists, then the ri_id, ri_type, and frq args are required. 57 58 59 @keyword ri_id: The relaxation data ID string. If not given, all relaxation data will be back calculated. 60 @type ri_id: None or str 61 @keyword ri_type: The relaxation data type. This should be one of 'R1', 'R2', or 'NOE'. 62 @type ri_type: None or str 63 @keyword frq: The spectrometer proton frequency in Hz. 64 @type frq: None or float 65 """ 66 67 # Test if the current pipe exists. 68 pipes.test() 69 70 # Test if sequence data is loaded. 71 if not exists_mol_res_spin_data(): 72 raise RelaxNoSequenceError 73 74 # Check that ri_type and frq are supplied if no relaxation data exists. 75 if ri_id and (not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids) and (ri_type == None or frq == None): 76 raise RelaxError("The 'ri_type' and 'frq' arguments must be supplied as no relaxation data corresponding to '%s' exists." % ri_id) 77 78 # Check if the type is valid. 79 if ri_type and ri_type not in VALID_TYPES: 80 raise RelaxError("The relaxation data type '%s' must be one of %s." % (ri_type, VALID_TYPES)) 81 82 # Frequency checks. 83 frq_checks(frq) 84 85 # Initialise the global data for the current pipe if necessary. 86 if not hasattr(cdp, 'frq'): 87 cdp.frq = {} 88 if not hasattr(cdp, 'ri_type'): 89 cdp.ri_type = {} 90 if not hasattr(cdp, 'ri_ids'): 91 cdp.ri_ids = [] 92 93 # Update the global data if needed. 94 if ri_id and ri_id not in cdp.ri_ids: 95 cdp.ri_ids.append(ri_id) 96 cdp.ri_type[ri_id] = ri_type 97 cdp.frq[ri_id] = frq 98 99 # Specific Ri back calculate function setup. 100 back_calculate = specific_fns.setup.get_specific_fn('back_calc_ri', pipes.get_type()) 101 102 # The IDs to loop over. 103 if ri_id == None: 104 ri_ids = cdp.ri_ids 105 else: 106 ri_ids = [ri_id] 107 108 # The data types. 109 if ri_type == None: 110 ri_types = cdp.ri_type 111 else: 112 ri_types = {ri_id: ri_type} 113 114 # The frequencies. 115 if frq == None: 116 frqs = cdp.frq 117 else: 118 frqs = {ri_id: frq} 119 120 # Loop over the spins. 121 for spin, spin_id in spin_loop(return_id=True): 122 # Skip deselected spins. 123 if not spin.select: 124 continue 125 126 # The global index. 127 spin_index = find_index(spin_id) 128 129 # Initialise the spin data if necessary. 130 if not hasattr(spin, 'ri_data_bc'): 131 spin.ri_data_bc = {} 132 133 # Back-calculate the relaxation value. 134 for ri_id in ri_ids: 135 spin.ri_data_bc[ri_id] = back_calculate(spin_index=spin_index, ri_id=ri_id, ri_type=ri_types[ri_id], frq=frqs[ri_id])
136 137
138 -def bmrb_read(star, sample_conditions=None):
139 """Read the relaxation data from the NMR-STAR dictionary object. 140 141 @param star: The NMR-STAR dictionary object. 142 @type star: NMR_STAR instance 143 @keyword sample_conditions: The sample condition label to read. Only one sample condition can be read per data pipe. 144 @type sample_conditions: None or str 145 """ 146 147 # Get the relaxation data. 148 for data in star.relaxation.loop(): 149 # Store the keys. 150 keys = list(data.keys()) 151 152 # Sample conditions do not match (remove the $ sign). 153 if 'sample_cond_list_label' in keys and sample_conditions and data['sample_cond_list_label'].replace('$', '') != sample_conditions: 154 continue 155 156 # Create the labels. 157 ri_type = data['data_type'] 158 frq = float(data['frq']) * 1e6 159 160 # Round the label to the nearest factor of 10. 161 frq_label = create_frq_label(float(data['frq']) * 1e6) 162 163 # The ID string. 164 ri_id = "%s_%s" % (ri_type, frq_label) 165 166 # The number of spins. 167 N = bmrb.num_spins(data) 168 169 # No data in the saveframe. 170 if N == 0: 171 continue 172 173 # The molecule names. 174 mol_names = bmrb.molecule_names(data, N) 175 176 # Generate the sequence if needed. 177 bmrb.generate_sequence(N, spin_names=data['atom_names'], res_nums=data['res_nums'], res_names=data['res_names'], mol_names=mol_names, isotopes=data['isotope'], elements=data['atom_types']) 178 179 # The attached protons. 180 if 'atom_names_2' in data: 181 # Generate the proton spins. 182 bmrb.generate_sequence(N, spin_names=data['atom_names_2'], res_nums=data['res_nums'], res_names=data['res_names'], mol_names=mol_names, isotopes=data['isotope_2'], elements=data['atom_types_2']) 183 184 # Define the dipolar interaction. 185 for i in range(len(data['atom_names'])): 186 # The spin IDs. 187 spin_id1 = generate_spin_id_unique(spin_name=data['atom_names'][i], res_num=data['res_nums'][i], res_name=data['res_names'][i], mol_name=mol_names[i]) 188 spin_id2 = generate_spin_id_unique(spin_name=data['atom_names_2'][i], res_num=data['res_nums'][i], res_name=data['res_names'][i], mol_name=mol_names[i]) 189 190 # Check if the container exists. 191 if return_interatom(spin_id1=spin_id1, spin_id2=spin_id2): 192 continue 193 194 # Define. 195 dipole_pair.define(spin_id1=spin_id1, spin_id2=spin_id2, verbose=False) 196 197 # The data and error. 198 vals = data['data'] 199 errors = data['errors'] 200 if vals == None: 201 vals = [None] * N 202 if errors == None: 203 errors = [None] * N 204 205 # Data transformation. 206 if vals != None and 'units' in keys: 207 # Scaling. 208 if data['units'] == 'ms': 209 # Loop over the data. 210 for i in range(N): 211 # The value. 212 if vals[i] != None: 213 vals[i] = vals[i] / 1000 214 215 # The error. 216 if errors[i] != None: 217 errors[i] = errors[i] / 1000 218 219 # Invert. 220 if data['units'] in ['s', 'ms']: 221 # Loop over the data. 222 for i in range(len(vals)): 223 # The value. 224 if vals[i] != None: 225 vals[i] = 1.0 / vals[i] 226 227 # The error. 228 if vals[i] != None and errors[i] != None: 229 errors[i] = errors[i] * vals[i]**2 230 231 # Pack the data. 232 pack_data(ri_id, ri_type, frq, vals, errors, mol_names=mol_names, res_nums=data['res_nums'], res_names=data['res_names'], spin_nums=None, spin_names=data['atom_names'], gen_seq=True, verbose=False) 233 234 # Store the temperature calibration and control. 235 if data['temp_calibration']: 236 temp_calibration(ri_id=ri_id, method=data['temp_calibration']) 237 if data['temp_control']: 238 temp_control(ri_id=ri_id, method=data['temp_control']) 239 240 # Peak intensity type. 241 if data['peak_intensity_type']: 242 peak_intensity_type(ri_id=ri_id, type=data['peak_intensity_type'])
243 244
245 -def bmrb_write(star):
246 """Generate the relaxation data saveframes for the NMR-STAR dictionary object. 247 248 @param star: The NMR-STAR dictionary object. 249 @type star: NMR_STAR instance 250 """ 251 252 # Get the current data pipe. 253 cdp = pipes.get_pipe() 254 255 # Initialise the spin specific data lists. 256 mol_name_list = [] 257 res_num_list = [] 258 res_name_list = [] 259 atom_name_list = [] 260 isotope_list = [] 261 element_list = [] 262 attached_atom_name_list = [] 263 attached_isotope_list = [] 264 attached_element_list = [] 265 ri_data_list = [] 266 ri_data_err_list = [] 267 for i in range(len(cdp.ri_ids)): 268 ri_data_list.append([]) 269 ri_data_err_list.append([]) 270 271 # Relax data labels. 272 labels = cdp.ri_ids 273 exp_label = [] 274 spectro_ids = [] 275 spectro_labels = [] 276 277 # Store the spin specific data in lists for later use. 278 for spin, mol_name, res_num, res_name, spin_id in spin_loop(full_info=True, return_id=True): 279 # Skip spins with no relaxation data. 280 if not hasattr(spin, 'ri_data'): 281 continue 282 283 # Check the data for None (not allowed in BMRB!). 284 if res_num == None: 285 raise RelaxError("For the BMRB, the residue of spin '%s' must be numbered." % spin_id) 286 if res_name == None: 287 raise RelaxError("For the BMRB, the residue of spin '%s' must be named." % spin_id) 288 if spin.name == None: 289 raise RelaxError("For the BMRB, the spin '%s' must be named." % spin_id) 290 if spin.isotope == None: 291 raise RelaxError("For the BMRB, the spin isotope type of '%s' must be specified." % spin_id) 292 293 # The molecule/residue/spin info. 294 mol_name_list.append(mol_name) 295 res_num_list.append(str(res_num)) 296 res_name_list.append(str(res_name)) 297 atom_name_list.append(str(spin.name)) 298 299 # Interatomic info. 300 interatoms = return_interatom_list(spin_id) 301 if len(interatoms) == 0: 302 raise RelaxError("No interatomic interactions are defined for the spin '%s'." % spin_id) 303 if len(interatoms) > 1: 304 raise RelaxError("The BMRB only handles a signal interatomic interaction for the spin '%s'." % spin_id) 305 306 # Get the attached spin. 307 spin_attached = return_spin(interatoms[0].spin_id1) 308 if id(spin_attached) == id(spin): 309 spin_attached = return_spin(interatoms[0].spin_id2) 310 311 # The attached atom info. 312 if hasattr(spin_attached, 'name'): 313 attached_atom_name_list.append(str(spin_attached.name)) 314 else: 315 attached_atom_name_list.append(None) 316 if hasattr(spin_attached, 'isotope'): 317 attached_element_list.append(element_from_isotope(spin_attached.isotope)) 318 attached_isotope_list.append(str(number_from_isotope(spin_attached.isotope))) 319 else: 320 attached_element_list.append(None) 321 attached_isotope_list.append(None) 322 323 # The relaxation data. 324 used_index = -ones(len(cdp.ri_ids)) 325 for i in range(len(cdp.ri_ids)): 326 # Data exists. 327 if cdp.ri_ids[i] in list(spin.ri_data.keys()): 328 ri_data_list[i].append(str(spin.ri_data[cdp.ri_ids[i]])) 329 ri_data_err_list[i].append(str(spin.ri_data_err[cdp.ri_ids[i]])) 330 else: 331 ri_data_list[i].append(None) 332 ri_data_err_list[i].append(None) 333 334 # Other info. 335 isotope_list.append(int(spin.isotope.strip(string.ascii_letters))) 336 element_list.append(spin.element) 337 338 # Convert the molecule names into the entity IDs. 339 entity_ids = zeros(len(mol_name_list), int32) 340 mol_names = get_molecule_names() 341 for i in range(len(mol_name_list)): 342 for j in range(len(mol_names)): 343 if mol_name_list[i] == mol_names[j]: 344 entity_ids[i] = j+1 345 346 # Check the temperature control methods. 347 if not hasattr(cdp, 'exp_info') or not hasattr(cdp.exp_info, 'temp_calibration'): 348 raise RelaxError("The temperature calibration methods have not been specified.") 349 if not hasattr(cdp, 'exp_info') or not hasattr(cdp.exp_info, 'temp_control'): 350 raise RelaxError("The temperature control methods have not been specified.") 351 352 # Check the peak intensity type. 353 if not hasattr(cdp, 'exp_info') or not hasattr(cdp.exp_info, 'peak_intensity_type'): 354 raise RelaxError("The peak intensity types measured for the relaxation data have not been specified.") 355 356 # Loop over the relaxation data. 357 for i in range(len(cdp.ri_ids)): 358 # Alias. 359 ri_id = cdp.ri_ids[i] 360 ri_type = cdp.ri_type[ri_id] 361 362 # Convert to MHz. 363 frq = cdp.frq[ri_id] * 1e-6 364 365 # Get the temperature control methods. 366 temp_calib = cdp.exp_info.temp_calibration[ri_id] 367 temp_control = cdp.exp_info.temp_control[ri_id] 368 369 # Get the peak intensity type. 370 peak_intensity_type = cdp.exp_info.peak_intensity_type[ri_id] 371 372 # Check. 373 if not temp_calib: 374 raise RelaxError("The temperature calibration method for the '%s' relaxation data ID string has not been specified." % ri_id) 375 if not temp_control: 376 raise RelaxError("The temperature control method for the '%s' relaxation data ID string has not been specified." % ri_id) 377 378 # Add the relaxation data. 379 star.relaxation.add(data_type=ri_type, frq=frq, entity_ids=entity_ids, res_nums=res_num_list, res_names=res_name_list, atom_names=atom_name_list, atom_types=element_list, isotope=isotope_list, entity_ids_2=entity_ids, res_nums_2=res_num_list, res_names_2=res_name_list, atom_names_2=attached_atom_name_list, atom_types_2=attached_element_list, isotope_2=attached_isotope_list, data=ri_data_list[i], errors=ri_data_err_list[i], temp_calibration=temp_calib, temp_control=temp_control, peak_intensity_type=peak_intensity_type) 380 381 # The experimental label. 382 if ri_type == 'NOE': 383 exp_name = 'steady-state NOE' 384 else: 385 exp_name = ri_type 386 exp_label.append("%s MHz %s" % (frq, exp_name)) 387 388 # Spectrometer info. 389 frq_num = 1 390 for frq in frq_loop(): 391 if frq == cdp.frq[ri_id]: 392 break 393 frq_num += 1 394 spectro_ids.append(frq_num) 395 spectro_labels.append("$spectrometer_%s" % spectro_ids[-1]) 396 397 # Add the spectrometer info. 398 num = 1 399 for frq in frq_loop(): 400 star.nmr_spectrometer.add(name="$spectrometer_%s" % num, manufacturer=None, model=None, frq=int(frq/1e6)) 401 num += 1 402 403 # Add the experiment saveframe. 404 star.experiment.add(name=exp_label, spectrometer_ids=spectro_ids, spectrometer_labels=spectro_labels)
405 406
407 -def copy(pipe_from=None, pipe_to=None, ri_id=None):
408 """Copy the relaxation data from one data pipe to another. 409 410 @keyword pipe_from: The data pipe to copy the relaxation data from. This defaults to the current data pipe. 411 @type pipe_from: str 412 @keyword pipe_to: The data pipe to copy the relaxation data to. This defaults to the current data pipe. 413 @type pipe_to: str 414 @param ri_id: The relaxation data ID string. 415 @type ri_id: str 416 """ 417 418 # Defaults. 419 if pipe_from == None and pipe_to == None: 420 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.") 421 elif pipe_from == None: 422 pipe_from = pipes.cdp_name() 423 elif pipe_to == None: 424 pipe_to = pipes.cdp_name() 425 426 # Test if the pipe_from and pipe_to data pipes exist. 427 pipes.test(pipe_from) 428 pipes.test(pipe_to) 429 430 # Get the data pipes. 431 dp_from = pipes.get_pipe(pipe_from) 432 dp_to = pipes.get_pipe(pipe_to) 433 434 # Test if pipe_from contains sequence data. 435 if not exists_mol_res_spin_data(pipe_from): 436 raise RelaxNoSequenceError 437 438 # Test if pipe_to contains sequence data. 439 if not exists_mol_res_spin_data(pipe_to): 440 raise RelaxNoSequenceError 441 442 # Test if relaxation data ID string exists for pipe_from. 443 if ri_id and (not hasattr(dp_from, 'ri_ids') or ri_id not in dp_from.ri_ids): 444 raise RelaxNoRiError(ri_id) 445 446 # The IDs. 447 if ri_id == None: 448 ri_ids = dp_from.ri_ids 449 else: 450 ri_ids = [ri_id] 451 452 # Init target pipe global structures. 453 if not hasattr(dp_to, 'ri_ids'): 454 dp_to.ri_ids = [] 455 if not hasattr(dp_to, 'ri_type'): 456 dp_to.ri_type = {} 457 if not hasattr(dp_to, 'frq'): 458 dp_to.frq = {} 459 460 # Loop over the Rx IDs. 461 for ri_id in ri_ids: 462 # Test if relaxation data ID string exists for pipe_to. 463 if ri_id in dp_to.ri_ids: 464 raise RelaxRiError(ri_id) 465 466 # Copy the global data. 467 dp_to.ri_ids.append(ri_id) 468 dp_to.ri_type[ri_id] = dp_from.ri_type[ri_id] 469 dp_to.frq[ri_id] = dp_from.frq[ri_id] 470 471 # Spin loop. 472 for mol_index, res_index, spin_index in spin_index_loop(): 473 # Alias the spin containers. 474 spin_from = dp_from.mol[mol_index].res[res_index].spin[spin_index] 475 spin_to = dp_to.mol[mol_index].res[res_index].spin[spin_index] 476 477 # No data or errors. 478 if not hasattr(spin_from, 'ri_data') and not hasattr(spin_from, 'ri_data_err'): 479 continue 480 481 # Initialise the spin data if necessary. 482 if not hasattr(spin_to, 'ri_data'): 483 spin_to.ri_data = {} 484 if not hasattr(spin_to, 'ri_data_err'): 485 spin_to.ri_data_err = {} 486 487 # Copy the value and error from pipe_from. 488 spin_to.ri_data[ri_id] = spin_from.ri_data[ri_id] 489 spin_to.ri_data_err[ri_id] = spin_from.ri_data_err[ri_id]
490 491
492 -def create_frq_label(frq):
493 """Generate a frequency label in MHz, rounded to the nearest factor of 10. 494 495 @param frq: The frequency in Hz. 496 @type frq: float 497 @return: The MHz frequency label. 498 @rtype: str 499 """ 500 501 # Convert to MHz. 502 label = frq / 1e6 503 504 # Rounding to the nearest factor of 10. 505 label = int(round(label/10)*10) 506 507 # Convert to str and return. 508 return str(label)
509 510
511 -def delete(ri_id=None):
512 """Delete relaxation data corresponding to the relaxation data ID. 513 514 @keyword ri_id: The relaxation data ID string. 515 @type ri_id: str 516 """ 517 518 # Test if the current pipe exists. 519 pipes.test() 520 521 # Test if the sequence data is loaded. 522 if not exists_mol_res_spin_data(): 523 raise RelaxNoSequenceError 524 525 # Check the ID. 526 if ri_id == None: 527 raise RelaxError("The relaxation data ID string must be supplied.") 528 529 # Test if data exists. 530 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 531 raise RelaxNoRiError(ri_id) 532 533 # Pop the ID, and remove it from the frequency and type lists. 534 cdp.ri_ids.pop(cdp.ri_ids.index(ri_id)) 535 del cdp.frq[ri_id] 536 del cdp.ri_type[ri_id] 537 538 # Prune empty structures. 539 if len(cdp.ri_ids) == 0: 540 del cdp.ri_ids 541 if len(cdp.frq) == 0: 542 del cdp.frq 543 if len(cdp.ri_type) == 0: 544 del cdp.ri_type 545 546 # Loop over the spins, deleting the relaxation data and errors when present. 547 for spin in spin_loop(): 548 # Data deletion. 549 if hasattr(spin, 'ri_data') and ri_id in spin.ri_data: 550 del spin.ri_data[ri_id] 551 if hasattr(spin, 'ri_data_err') and ri_id in spin.ri_data_err: 552 del spin.ri_data_err[ri_id] 553 554 # Prune empty structures. 555 if hasattr(spin, 'ri_data') and len(spin.ri_data) == 0: 556 del spin.ri_data 557 if hasattr(spin, 'ri_data_err') and len(spin.ri_data_err) == 0: 558 del spin.ri_data_err 559 560 # Delete the metadata. 561 if hasattr(cdp, 'exp_info') and hasattr(cdp.exp_info, 'temp_calibration') and ri_id in cdp.exp_info.temp_calibration: 562 del cdp.exp_info.temp_calibration[ri_id] 563 if len(cdp.exp_info.temp_calibration) == 0: 564 del cdp.exp_info.temp_calibration 565 if hasattr(cdp, 'exp_info') and hasattr(cdp.exp_info, 'temp_control') and ri_id in cdp.exp_info.temp_control: 566 del cdp.exp_info.temp_control[ri_id] 567 if len(cdp.exp_info.temp_control) == 0: 568 del cdp.exp_info.temp_control 569 if hasattr(cdp, 'exp_info') and hasattr(cdp.exp_info, 'peak_intensity_type') and ri_id in cdp.exp_info.peak_intensity_type: 570 del cdp.exp_info.peak_intensity_type[ri_id] 571 if len(cdp.exp_info.peak_intensity_type) == 0: 572 del cdp.exp_info.peak_intensity_type
573 574
575 -def display(ri_id=None):
576 """Display relaxation data corresponding to the ID. 577 578 @keyword ri_id: The relaxation data ID string. 579 @type ri_id: str 580 """ 581 582 # Test if the current pipe exists. 583 pipes.test() 584 585 # Test if the sequence data is loaded. 586 if not exists_mol_res_spin_data(): 587 raise RelaxNoSequenceError 588 589 # Test if data exists. 590 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 591 raise RelaxNoRiError(ri_id) 592 593 # Print the data. 594 value.write_data(param=ri_id, file=sys.stdout, return_value=return_value, return_data_desc=return_data_desc)
595 596
597 -def frq(ri_id=None, frq=None):
598 """Set or reset the frequency associated with the ID. 599 600 @param ri_id: The relaxation data ID string. 601 @type ri_id: str 602 @param frq: The spectrometer proton frequency in Hz. 603 @type frq: float 604 """ 605 606 # Test if the current data pipe exists. 607 pipes.test() 608 609 # Test if sequence data exists. 610 if not exists_mol_res_spin_data(): 611 raise RelaxNoSequenceError 612 613 # Test if data exists. 614 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 615 raise RelaxNoRiError(ri_id) 616 617 # Frequency checks. 618 frq_checks(frq) 619 620 # Initialise if needed. 621 if not hasattr(cdp, 'frq'): 622 cdp.frq = {} 623 624 # Set the value. 625 cdp.frq[ri_id] = frq
626 627
628 -def frq_checks(frq):
629 """Perform a number of checks on the given frequency. 630 631 @param frq: The proton frequency value. 632 @type frq: float or None 633 """ 634 635 # No frequency given. 636 if frq == None: 637 return 638 639 # Make sure the precise value has been supplied. 640 frac, integer = modf(frq / 1e6) 641 if frac == 0.0 or frac > 0.99999: 642 warn(RelaxWarning("The precise spectrometer frequency should be suppled, a value such as 500000000 or 5e8 for a 500 MHz machine is not acceptable. Please see the 'sfrq' parameter in the Varian procpar file or the 'SFO1' parameter in the Bruker acqus file.")) 643 644 # Check that Hz have been supplied. 645 if frq < 1e6: 646 warn(RelaxWarning("The proton frequency of %s should be in Hz, but it seems to be in MHz." % frq))
647 648
649 -def frq_loop():
650 """Generator function for returning each unique frequency. 651 652 @return: The frequency. 653 @rtype: float 654 """ 655 656 # Init. 657 frq = [] 658 659 # Loop over the Rx data. 660 for ri_id in cdp.ri_ids: 661 # New frequency. 662 if cdp.frq[ri_id] not in frq: 663 # Add the frequency. 664 frq.append(cdp.frq[ri_id]) 665 666 # Yield the value. 667 yield cdp.frq[ri_id]
668 669
670 -def get_data_names(global_flag=False, sim_names=False):
671 """Return a list of names of data structures associated with relaxation data. 672 673 Description 674 =========== 675 676 The names are as follows: 677 678 ri_data: Relaxation data. 679 680 ri_data_err: Relaxation data error. 681 682 ri_data_bc: The back calculated relaxation data. 683 684 ri_type: The relaxation data type, i.e. one of ['NOE', 'R1', 'R2'] 685 686 frq: NMR frequencies in Hz, eg [600.0 * 1e6, 500.0 * 1e6] 687 688 689 @keyword global_flag: A flag which if True corresponds to the pipe specific data structures and if False corresponds to the spin specific data structures. 690 @type global_flag: bool 691 @keyword sim_names: A flag which if True will add the Monte Carlo simulation object names as well. 692 @type sim_names: bool 693 @return: The list of object names. 694 @rtype: list of str 695 """ 696 697 # Initialise. 698 names = [] 699 700 # Global data names. 701 if not sim_names and global_flag: 702 names.append('ri_id') 703 names.append('ri_type') 704 names.append('frq') 705 706 # Spin specific data names. 707 if not sim_names and not global_flag: 708 names.append('ri_data') 709 names.append('ri_data_err') 710 names.append('ri_data_bc') 711 712 # Simulation object names. 713 if sim_names and not global_flag: 714 names.append('ri_data_sim') 715 716 # Return the list of names. 717 return names
718 719
720 -def get_ids():
721 """Return the list of all relaxation data IDs. 722 723 @return: The list of all relaxation data IDs. 724 @rtype: list of str 725 """ 726 727 # No pipe. 728 if cdp == None: 729 return [] 730 731 # No relaxation data. 732 if not hasattr(cdp, 'ri_ids'): 733 return [] 734 735 # The relaxation data IDs. 736 return cdp.ri_ids
737 738
739 -def num_frq():
740 """Determine the number of unique frequencies. 741 742 @return: The number of unique frequencies. 743 @rtype: int 744 """ 745 746 # Init. 747 frq = [] 748 count = 0 749 750 # Loop over the Rx data. 751 for ri_id in cdp.ri_ids: 752 # New frequency. 753 if cdp.frq[ri_id] not in frq: 754 # Add the frequency. 755 frq.append(cdp.frq[ri_id]) 756 757 # Increment the counter. 758 count += 1 759 760 # Return the counter. 761 return count
762 763
764 -def pack_data(ri_id, ri_type, frq, values, errors, spin_ids=None, mol_names=None, res_nums=None, res_names=None, spin_nums=None, spin_names=None, spin_id=None, gen_seq=False, verbose=True):
765 """Pack the relaxation data into the data pipe and spin containers. 766 767 The values, errors, and spin_ids arguments must be lists of equal length or None. Each element i corresponds to a unique spin. 768 769 @param ri_id: The relaxation data ID string. 770 @type ri_id: str 771 @param ri_type: The relaxation data type, ie 'R1', 'R2', or 'NOE'. 772 @type ri_type: str 773 @param frq: The spectrometer proton frequency in Hz. 774 @type frq: float 775 @keyword values: The relaxation data for each spin. 776 @type values: None or list of float or float array 777 @keyword errors: The relaxation data errors for each spin. 778 @type errors: None or list of float or float array 779 @keyword spin_ids: The list of spin ID strings. If the other spin identifiers are given, i.e. mol_names, res_nums, res_names, spin_nums, and/or spin_names, then this argument is not necessary. 780 @type spin_ids: None or list of str 781 @keyword mol_names: The list of molecule names used for creating the spin IDs (if not given) or for generating the sequence data. 782 @type mol_names: None or list of str 783 @keyword res_nums: The list of residue numbers used for creating the spin IDs (if not given) or for generating the sequence data. 784 @type res_nums: None or list of str 785 @keyword res_names: The list of residue names used for creating the spin IDs (if not given) or for generating the sequence data. 786 @type res_names: None or list of str 787 @keyword spin_nums: The list of spin numbers used for creating the spin IDs (if not given) or for generating the sequence data. 788 @type spin_nums: None or list of str 789 @keyword spin_names: The list of spin names used for creating the spin IDs (if not given) or for generating the sequence data. 790 @type spin_names: None or list of str 791 @keyword gen_seq: A flag which if True will cause the molecule, residue, and spin sequence data to be generated. 792 @type gen_seq: bool 793 @keyword verbose: A flag which if True will cause all relaxation data loaded to be printed out. 794 @type verbose: bool 795 """ 796 797 # The number of spins. 798 N = len(values) 799 800 # Test the data. 801 if errors != None and len(errors) != N: 802 raise RelaxError("The length of the errors arg (%s) does not match that of the value arg (%s)." % (len(errors), N)) 803 if spin_ids and len(spin_ids) != N: 804 raise RelaxError("The length of the spin ID strings arg (%s) does not match that of the value arg (%s)." % (len(mol_names), N)) 805 if mol_names and len(mol_names) != N: 806 raise RelaxError("The length of the molecule names arg (%s) does not match that of the value arg (%s)." % (len(mol_names), N)) 807 if res_nums and len(res_nums) != N: 808 raise RelaxError("The length of the residue numbers arg (%s) does not match that of the value arg (%s)." % (len(res_nums), N)) 809 if res_names and len(res_names) != N: 810 raise RelaxError("The length of the residue names arg (%s) does not match that of the value arg (%s)." % (len(res_names), N)) 811 if spin_nums and len(spin_nums) != N: 812 raise RelaxError("The length of the spin numbers arg (%s) does not match that of the value arg (%s)." % (len(spin_nums), N)) 813 if spin_names and len(spin_names) != N: 814 raise RelaxError("The length of the spin names arg (%s) does not match that of the value arg (%s)." % (len(spin_names), N)) 815 816 # Generate some empty lists. 817 if not mol_names: 818 mol_names = [None] * N 819 if not res_nums: 820 res_nums = [None] * N 821 if not res_names: 822 res_names = [None] * N 823 if not spin_nums: 824 spin_nums = [None] * N 825 if not spin_names: 826 spin_names = [None] * N 827 if errors == None: 828 errors = [None] * N 829 830 # Generate the spin IDs. 831 if not spin_ids: 832 spin_ids = [] 833 for i in range(N): 834 spin_ids.append(generate_spin_id_unique(spin_num=spin_nums[i], spin_name=spin_names[i], res_num=res_nums[i], res_name=res_names[i], mol_name=mol_names[i])) 835 836 # Initialise the global data for the current pipe if necessary. 837 if not hasattr(cdp, 'frq'): 838 cdp.frq = {} 839 if not hasattr(cdp, 'ri_type'): 840 cdp.ri_type = {} 841 if not hasattr(cdp, 'ri_ids'): 842 cdp.ri_ids = [] 843 844 # Update the global data. 845 cdp.ri_ids.append(ri_id) 846 cdp.ri_type[ri_id] = ri_type 847 cdp.frq[ri_id] = frq 848 849 # The selection object. 850 select_obj = None 851 if spin_id: 852 select_obj = Selection(spin_id) 853 854 # Loop over the spin data. 855 data = [] 856 for i in range(N): 857 # Get the corresponding spin container. 858 spins = return_spin_from_selection(spin_ids[i], multi=True) 859 if spins in [None, []]: 860 raise RelaxNoSpinError(spin_ids[i]) 861 862 # Remove non-matching spins. 863 if select_obj: 864 new_spins = [] 865 new_ids = [] 866 for j in range(len(spins)): 867 if spins[j] in select_obj: 868 new_spins.append(spins[j]) 869 new_ids.append(generate_spin_id_unique(mol_name=mol_names[i], res_num=res_nums[i], res_name=res_names[i], spin_num=spins[j].num, spin_name=spins[j].name)) 870 new_id = new_ids[0] 871 872 # Aliases for normal operation. 873 else: 874 new_spins = spins 875 new_id = spin_ids[i] 876 new_ids = None 877 878 # Check that only a singe spin is present. 879 if len(new_spins) > 1: 880 if new_ids: 881 raise RelaxMultiSpinIDError(spin_ids[i], new_ids) 882 else: 883 raise RelaxMultiSpinIDError(spin_ids[i], new_ids) 884 if len(new_spins) == 0: 885 raise RelaxNoSpinError(spin_ids[i]) 886 887 # Loop over the spins. 888 for spin in new_spins: 889 # No match to the selection. 890 if select_obj and spin not in select_obj: 891 continue 892 893 # Initialise the spin data if necessary. 894 if not hasattr(spin, 'ri_data') or spin.ri_data == None: 895 spin.ri_data = {} 896 if not hasattr(spin, 'ri_data_err') or spin.ri_data_err == None: 897 spin.ri_data_err = {} 898 899 # Update all data structures. 900 spin.ri_data[ri_id] = values[i] 901 spin.ri_data_err[ri_id] = errors[i] 902 903 # Append the data for printing out. 904 data.append([new_id, repr(values[i]), repr(errors[i])]) 905 906 # Print out. 907 if verbose: 908 print("\nThe following %s MHz %s relaxation data with the ID '%s' has been loaded into the relax data store:\n" % (frq/1e6, ri_type, ri_id)) 909 write_data(out=sys.stdout, headings=["Spin_ID", "Value", "Error"], data=data)
910 911
912 -def peak_intensity_type(ri_id=None, type=None):
913 """Set the type of intensity measured for the peaks. 914 915 @keyword ri_id: The relaxation data ID string. 916 @type ri_id: str 917 @keyword type: The peak intensity type, one of 'height' or 'volume'. 918 @type type: str 919 """ 920 921 # Test if the current pipe exists. 922 pipes.test() 923 924 # Test if sequence data is loaded. 925 if not exists_mol_res_spin_data(): 926 raise RelaxNoSequenceError 927 928 # Test if data exists. 929 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 930 raise RelaxNoRiError(ri_id) 931 932 # Check the values, and warn if not in the list. 933 valid = ['height', 'volume'] 934 if type not in valid: 935 raise RelaxError("The '%s' peak intensity type is unknown. Please select one of %s." % (type, valid)) 936 937 # Set up the experimental info data container, if needed. 938 if not hasattr(cdp, 'exp_info'): 939 cdp.exp_info = ExpInfo() 940 941 # Store the type. 942 cdp.exp_info.setup_peak_intensity_type(ri_id, type)
943 944
945 -def read(ri_id=None, ri_type=None, frq=None, file=None, dir=None, file_data=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, spin_id=None):
946 """Read R1, R2, or NOE relaxation data from a file. 947 948 @param ri_id: The relaxation data ID string. 949 @type ri_id: str 950 @param ri_type: The relaxation data type, ie 'R1', 'R2', or 'NOE'. 951 @type ri_type: str 952 @param frq: The spectrometer proton frequency in Hz. 953 @type frq: float 954 @param file: The name of the file to open. 955 @type file: str 956 @param dir: The directory containing the file (defaults to the current directory if None). 957 @type dir: str or None 958 @param file_data: An alternative opening a file, if the data already exists in the correct format. The format is a list of lists where the first index corresponds to the row and the second the column. 959 @type file_data: list of lists 960 @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. 961 @type spin_id_col: int or None 962 @keyword mol_name_col: The column containing the molecule name information. If supplied, spin_id_col must be None. 963 @type mol_name_col: int or None 964 @keyword res_name_col: The column containing the residue name information. If supplied, spin_id_col must be None. 965 @type res_name_col: int or None 966 @keyword res_num_col: The column containing the residue number information. If supplied, spin_id_col must be None. 967 @type res_num_col: int or None 968 @keyword spin_name_col: The column containing the spin name information. If supplied, spin_id_col must be None. 969 @type spin_name_col: int or None 970 @keyword spin_num_col: The column containing the spin number information. If supplied, spin_id_col must be None. 971 @type spin_num_col: int or None 972 @keyword data_col: The column containing the relaxation data. 973 @type data_col: int or None 974 @keyword error_col: The column containing the relaxation data errors. 975 @type error_col: int or None 976 @keyword sep: The column separator which, if None, defaults to whitespace. 977 @type sep: str or None 978 @keyword spin_id: The spin ID string used to restrict data loading to a subset of all spins. 979 @type spin_id: None or str 980 """ 981 982 # Test if the current data pipe exists. 983 pipes.test() 984 985 # Test if sequence data exists. 986 if not exists_mol_res_spin_data(): 987 raise RelaxNoSequenceError 988 989 # Test if the ri_id already exists. 990 if hasattr(cdp, 'ri_ids') and ri_id in cdp.ri_ids: 991 raise RelaxError("The relaxation ID string '%s' already exists." % ri_id) 992 993 # Check if the type is valid. 994 if ri_type not in VALID_TYPES: 995 raise RelaxError("The relaxation data type '%s' must be one of %s." % (ri_type, VALID_TYPES)) 996 997 # Frequency checks. 998 frq_checks(frq) 999 1000 # Loop over the file data to create the data structures for packing. 1001 values = [] 1002 errors = [] 1003 mol_names = [] 1004 res_nums = [] 1005 res_names = [] 1006 spin_nums = [] 1007 spin_names = [] 1008 for data in read_spin_data(file=file, dir=dir, file_data=file_data, 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): 1009 # Unpack. 1010 if data_col and error_col: 1011 mol_name, res_num, res_name, spin_num, spin_name, value, error = data 1012 elif data_col: 1013 mol_name, res_num, res_name, spin_num, spin_name, value = data 1014 error = None 1015 else: 1016 mol_name, res_num, res_name, spin_num, spin_name, error = data 1017 value = None 1018 1019 # No data. 1020 if value == None and error == None: 1021 continue 1022 1023 # Store all the info. 1024 mol_names.append(mol_name) 1025 res_nums.append(res_num) 1026 res_names.append(res_name) 1027 spin_nums.append(spin_num) 1028 spin_names.append(spin_name) 1029 values.append(value) 1030 errors.append(error) 1031 1032 # Pack the data. 1033 pack_data(ri_id, ri_type, frq, values, errors, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, spin_id=spin_id)
1034 1035
1036 -def return_data_desc(name):
1037 """Return a description of the spin specific object. 1038 1039 @param name: The name of the spin specific object. 1040 @type name: str 1041 """ 1042 1043 if name == 'ri_data': 1044 return 'The relaxation data' 1045 if name == 'ri_data_err': 1046 return 'The relaxation data errors'
1047 1048
1049 -def return_value(spin, data_type, bc=False):
1050 """Return the value and error corresponding to 'data_type'. 1051 1052 @param spin: The spin container. 1053 @type spin: SpinContainer instance 1054 @param data_type: The relaxation data ID string. 1055 @type data_type: str 1056 @keyword bc: A flag which if True will cause the back calculated relaxation data to be written. 1057 @type bc: bool 1058 """ 1059 1060 # Relaxation data. 1061 data = None 1062 if not bc and hasattr(spin, 'ri_data') and spin.ri_data != None and data_type in list(spin.ri_data.keys()): 1063 data = spin.ri_data[data_type] 1064 1065 # Back calculated relaxation data 1066 if bc and hasattr(spin, 'ri_data_bc') and spin.ri_data_bc != None and data_type in list(spin.ri_data_bc.keys()): 1067 data = spin.ri_data_bc[data_type] 1068 1069 # Relaxation errors. 1070 error = None 1071 if hasattr(spin, 'ri_data_err') and spin.ri_data_err != None and data_type in list(spin.ri_data_err.keys()): 1072 error = spin.ri_data_err[data_type] 1073 1074 # Return the data. 1075 return data, error
1076 1077
1078 -def temp_calibration(ri_id=None, method=None):
1079 """Set the temperature calibration method. 1080 1081 @keyword ri_id: The relaxation data type, ie 'R1', 'R2', or 'NOE'. 1082 @type ri_id: str 1083 @keyword method: The temperature calibration method. 1084 @type method: str 1085 """ 1086 1087 # Test if the current pipe exists. 1088 pipes.test() 1089 1090 # Test if sequence data is loaded. 1091 if not exists_mol_res_spin_data(): 1092 raise RelaxNoSequenceError 1093 1094 # Test if data exists. 1095 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 1096 raise RelaxNoRiError(ri_id) 1097 1098 # Check the values, and warn if not in the list. 1099 valid = ['methanol', 'monoethylene glycol', 'no calibration applied'] 1100 if method not in valid: 1101 warn(RelaxWarning("The '%s' method is unknown. Please try to use one of %s." % (method, valid))) 1102 1103 # Set up the experimental info data container, if needed. 1104 if not hasattr(cdp, 'exp_info'): 1105 cdp.exp_info = ExpInfo() 1106 1107 # Store the method. 1108 cdp.exp_info.temp_calibration_setup(ri_id, method)
1109 1110
1111 -def temp_control(ri_id=None, method=None):
1112 """Set the temperature control method. 1113 1114 @keyword ri_id: The relaxation data ID string. 1115 @type ri_id: str 1116 @keyword method: The temperature control method. 1117 @type method: str 1118 """ 1119 1120 # Test if the current pipe exists. 1121 pipes.test() 1122 1123 # Test if sequence data is loaded. 1124 if not exists_mol_res_spin_data(): 1125 raise RelaxNoSequenceError 1126 1127 # Test if data exists. 1128 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 1129 raise RelaxNoRiError(ri_id) 1130 1131 # Check the values, and warn if not in the list. 1132 valid = ['single scan interleaving', 'temperature compensation block', 'single scan interleaving and temperature compensation block', 'single fid interleaving', 'single experiment interleaving', 'no temperature control applied'] 1133 if method not in valid: 1134 raise RelaxError("The '%s' method is unknown. Please select one of %s." % (method, valid)) 1135 1136 # Set up the experimental info data container, if needed. 1137 if not hasattr(cdp, 'exp_info'): 1138 cdp.exp_info = ExpInfo() 1139 1140 # Store the method. 1141 cdp.exp_info.temp_control_setup(ri_id, method)
1142 1143
1144 -def type(ri_id=None, ri_type=None):
1145 """Set or reset the frequency associated with the ID. 1146 1147 @param ri_id: The relaxation data ID string. 1148 @type ri_id: str 1149 @param ri_type: The relaxation data type, ie 'R1', 'R2', or 'NOE'. 1150 @type ri_type: str 1151 """ 1152 1153 # Test if the current data pipe exists. 1154 pipes.test() 1155 1156 # Test if sequence data exists. 1157 if not exists_mol_res_spin_data(): 1158 raise RelaxNoSequenceError 1159 1160 # Test if data exists. 1161 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 1162 raise RelaxNoRiError(ri_id) 1163 1164 # Check if the type is valid. 1165 if ri_type not in VALID_TYPES: 1166 raise RelaxError("The relaxation data type '%s' must be one of %s." % (ri_type, VALID_TYPES)) 1167 1168 # Initialise if needed. 1169 if not hasattr(cdp, 'ri_type'): 1170 cdp.ri_type = {} 1171 1172 # Set the type. 1173 cdp.ri_type[ri_id] = ri_type
1174 1175
1176 -def write(ri_id=None, file=None, dir=None, bc=False, force=False):
1177 """Write relaxation data to a file. 1178 1179 @keyword ri_id: The relaxation data ID string. 1180 @type ri_id: str 1181 @keyword file: The name of the file to create. 1182 @type file: str 1183 @keyword dir: The directory to write to. 1184 @type dir: str or None 1185 @keyword bc: A flag which if True will cause the back calculated relaxation data to be written. 1186 @type bc: bool 1187 @keyword force: A flag which if True will cause any pre-existing file to be overwritten. 1188 @type force: bool 1189 """ 1190 1191 # Test if the current pipe exists. 1192 pipes.test() 1193 1194 # Test if the sequence data is loaded. 1195 if not exists_mol_res_spin_data(): 1196 raise RelaxNoSequenceError 1197 1198 # Test if data exists. 1199 if not hasattr(cdp, 'ri_ids') or ri_id not in cdp.ri_ids: 1200 raise RelaxNoRiError(ri_id) 1201 1202 # Create the file name if none is given. 1203 if file == None: 1204 file = ri_id + ".out" 1205 1206 # Write the data. 1207 value.write(param=ri_id, file=file, dir=dir, bc=bc, force=force, return_value=return_value, return_data_desc=return_data_desc)
1208