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

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