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