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

Source Code for Module generic_fns.rdc

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2012 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 RDC data.""" 
 24   
 25  # Python module imports. 
 26  from copy import deepcopy 
 27  from math import pi, sqrt 
 28  from numpy import float64, ones, zeros 
 29  from numpy.linalg import norm 
 30  import sys 
 31  from warnings import warn 
 32   
 33  # relax module imports. 
 34  from arg_check import is_float 
 35  from float import nan 
 36  from generic_fns import grace, pipes 
 37  from generic_fns.align_tensor import get_tensor_index 
 38  from generic_fns.interatomic import create_interatom, interatomic_loop, return_interatom 
 39  from generic_fns.mol_res_spin import exists_mol_res_spin_data, generate_spin_id, return_spin, spin_loop 
 40  from maths_fns.rdc import ave_rdc_tensor 
 41  from physical_constants import dipolar_constant, return_gyromagnetic_ratio 
 42  from relax_errors import RelaxError, RelaxNoRDCError, RelaxNoSequenceError, RelaxSpinTypeError 
 43  from relax_io import extract_data, open_write_file, strip, write_data 
 44  from relax_warnings import RelaxWarning 
 45   
 46   
47 -def back_calc(align_id=None):
48 """Back calculate the RDC from the alignment tensor and unit bond vectors. 49 50 @keyword align_id: The alignment tensor ID string. 51 @type align_id: str 52 """ 53 54 # Arg check. 55 if align_id and align_id not in cdp.align_ids: 56 raise RelaxError("The alignment ID '%s' is not in the alignment ID list %s." % (align_id, cdp.align_ids)) 57 58 # Convert the align IDs to an array, or take all IDs. 59 if align_id: 60 align_ids = [align_id] 61 else: 62 align_ids = cdp.align_ids 63 64 # Add the ID to the RDC IDs, if needed. 65 for align_id in align_ids: 66 # Init. 67 if not hasattr(cdp, 'rdc_ids'): 68 cdp.rdc_ids = [] 69 70 # Add the ID. 71 if align_id not in cdp.rdc_ids: 72 cdp.rdc_ids.append(align_id) 73 74 # The weights. 75 weights = ones(cdp.N, float64) / cdp.N 76 77 # Unit vector data structure init. 78 unit_vect = zeros((cdp.N, 3), float64) 79 80 # Loop over the interatomic data. 81 for interatom in interatomic_loop(): 82 # Skip containers with no interatomic vectors. 83 if not hasattr(interatom, 'vector'): 84 continue 85 86 # Get the spins. 87 spin1 = return_spin(interatom.spin_id1) 88 spin2 = return_spin(interatom.spin_id2) 89 90 # Checks. 91 if not hasattr(spin1, 'isotope'): 92 raise RelaxSpinTypeError(interatom.spin_id1) 93 if not hasattr(spin2, 'isotope'): 94 raise RelaxSpinTypeError(interatom.spin_id2) 95 96 # Single vector. 97 if is_float(interatom.vector[0], raise_error=False): 98 vectors = [interatom.vector] 99 else: 100 vectors = interatom.vector 101 102 # Gyromagnetic ratios. 103 g1 = return_gyromagnetic_ratio(spin1.isotope) 104 g2 = return_gyromagnetic_ratio(spin2.isotope) 105 106 # Calculate the RDC dipolar constant (in Hertz, and the 3 comes from the alignment tensor), and append it to the list. 107 dj = 3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r) 108 109 # Unit vectors. 110 for c in range(cdp.N): 111 unit_vect[c] = vectors[c] / norm(vectors[c]) 112 113 # Initialise if necessary. 114 if not hasattr(interatom, 'rdc_bc'): 115 interatom.rdc_bc = {} 116 117 # Calculate the RDCs. 118 for id in align_ids: 119 interatom.rdc_bc[id] = ave_rdc_tensor(dj, unit_vect, cdp.N, cdp.align_tensors[get_tensor_index(id)].A, weights=weights)
120 121
122 -def convert(value, align_id, to_intern=False):
123 """Convert the RDC based on the 'D' or '2D' data type. 124 125 @param value: The value or error to convert. 126 @type value: float or None 127 @param align_id: The alignment tensor ID string. 128 @type align_id: str 129 @keyword to_intern: A flag which if True will convert to the internal D notation if needed, or if False will convert from the internal D notation to the external D or 2D format. 130 @type to_intern: bool 131 @return: The converted value. 132 @rtype: float or None 133 """ 134 135 # Handle values of None. 136 if value == None: 137 return None 138 139 # The conversion factor. 140 factor = 1.0 141 if hasattr(cdp, 'rdc_data_types') and align_id in cdp.rdc_data_types and cdp.rdc_data_types[align_id] == '2D': 142 # Convert from 2D to D. 143 if to_intern: 144 factor = 2.0 145 146 # Convert from D to 2D. 147 else: 148 factor = 0.5 149 150 # Return the converted value. 151 return value * factor
152 153
154 -def corr_plot(format=None, file=None, dir=None, force=False):
155 """Generate a correlation plot of the measured vs. back-calculated RDCs. 156 157 @keyword format: The format for the plot file. The following values are accepted: 'grace', a Grace plot; None, a plain text file. 158 @type format: str or None 159 @keyword file: The file name or object to write to. 160 @type file: str or file object 161 @keyword dir: The name of the directory to place the file into (defaults to the current directory). 162 @type dir: str 163 @keyword force: A flag which if True will cause any pre-existing file to be overwritten. 164 @type force: bool 165 """ 166 167 # Test if the current pipe exists. 168 pipes.test() 169 170 # Test if the sequence data is loaded. 171 if not exists_mol_res_spin_data(): 172 raise RelaxNoSequenceError 173 174 # Does RDC data exist? 175 if not hasattr(cdp, 'rdc_ids') or not cdp.rdc_ids: 176 warn(RelaxWarning("No RDC data exists, skipping file creation.")) 177 return 178 179 # Open the file for writing. 180 file = open_write_file(file, dir, force) 181 182 # Init. 183 data = [] 184 185 # The diagonal. 186 data.append([[-100, -100, 0], [100, 100, 0]]) 187 188 # Loop over the RDC data. 189 for align_id in cdp.rdc_ids: 190 # Append a new list for this alignment. 191 data.append([]) 192 193 # Errors present? 194 err_flag = False 195 for interatom in interatomic_loop(): 196 # Error present. 197 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err.keys(): 198 err_flag = True 199 break 200 201 # Loop over the interatomic data. 202 for interatom in interatomic_loop(): 203 # Skip if data is missing. 204 if not hasattr(interatom, 'rdc') or not hasattr(interatom, 'rdc_bc') or not align_id in interatom.rdc.keys() or not align_id in interatom.rdc_bc.keys(): 205 continue 206 207 # Append the data. 208 data[-1].append([convert(interatom.rdc_bc[align_id], align_id), convert(interatom.rdc[align_id], align_id)]) 209 210 # Errors. 211 if err_flag: 212 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err.keys(): 213 data[-1][-1].append(convert(interatom.rdc_err[align_id], align_id)) 214 else: 215 data[-1][-1].append(None) 216 217 # Label. 218 data[-1][-1].append("%s-%s" % (interatom.spin_id1, interatom.spin_id2)) 219 220 # The data size. 221 size = len(data) 222 223 # Only one data set. 224 data = [data] 225 226 # Graph type. 227 if err_flag: 228 graph_type = 'xydy' 229 else: 230 graph_type = 'xy' 231 232 # Grace file. 233 if format == 'grace': 234 # The header. 235 grace.write_xy_header(file=file, title="RDC correlation plot", sets=size, set_names=[None]+cdp.rdc_ids, linestyle=[2]+[0]*size, data_type=['rdc_bc', 'rdc'], axis_min=[-10, -10], axis_max=[10, 10], legend_pos=[1, 0.5]) 236 237 # The main data. 238 grace.write_xy_data(data=data, file=file, graph_type=graph_type)
239 240
241 -def delete(align_id=None):
242 """Delete the RDC data corresponding to the alignment ID. 243 244 @keyword align_id: The alignment tensor ID string. If not specified, all data will be deleted. 245 @type align_id: str or None 246 """ 247 248 # Test if the current data pipe exists. 249 pipes.test() 250 251 # Test if sequence data exists. 252 if not exists_mol_res_spin_data(): 253 raise RelaxNoSequenceError 254 255 # Check that the ID exists. 256 if align_id and not align_id in cdp.rdc_ids: 257 raise RelaxError("The RDC alignment id '%s' does not exist" % align_id) 258 259 # The IDs. 260 if not align_id: 261 ids = deepcopy(cdp.rdc_ids) 262 else: 263 ids = [align_id] 264 265 # Loop over the alignments, removing all the corresponding data. 266 for id in ids: 267 # The RDC ID. 268 cdp.rdc_ids.pop(cdp.rdc_ids.index(id)) 269 270 # The data type. 271 if hasattr(cdp, 'rdc_data_types') and id in cdp.rdc_data_types: 272 cdp.rdc_data_types.pop(id) 273 274 # The interatomic data. 275 for interatom in interatomic_loop(): 276 # The data. 277 if hasattr(interatom, 'rdc') and id in interatom.rdc: 278 interatom.rdc.pop(id) 279 280 # The error. 281 if hasattr(interatom, 'rdc_err') and id in interatom.rdc_err: 282 interatom.rdc_err.pop(id) 283 284 # Clean the global data. 285 if not hasattr(cdp, 'pcs_ids') or id not in cdp.pcs_ids: 286 cdp.align_ids.pop(id)
287 288
289 -def display(align_id=None, bc=False):
290 """Display the RDC data corresponding to the alignment ID. 291 292 @keyword align_id: The alignment tensor ID string. 293 @type align_id: str 294 @keyword bc: The back-calculation flag which if True will cause the back-calculated rather than measured data to be displayed. 295 @type bc: bool 296 """ 297 298 # Call the write method with sys.stdout as the file. 299 write(align_id=align_id, file=sys.stdout, bc=bc)
300 301
302 -def q_factors(spin_id=None):
303 """Calculate the Q-factors for the RDC data. 304 305 @keyword spin_id: The spin ID string used to restrict the Q-factor calculation to a subset of all spins. 306 @type spin_id: None or str 307 """ 308 309 # No RDCs, so no Q factors can be calculated. 310 if not hasattr(cdp, 'rdc_ids') or not len(cdp.rdc_ids): 311 warn(RelaxWarning("No RDC data exists, Q factors cannot be calculated.")) 312 return 313 314 # Q-factor dictonaries. 315 cdp.q_factors_rdc = {} 316 cdp.q_factors_rdc_norm2 = {} 317 318 # Loop over the alignments. 319 for align_id in cdp.rdc_ids: 320 # Init. 321 D2_sum = 0.0 322 sse = 0.0 323 324 # Interatomic data loop. 325 dj = None 326 N = 0 327 interatom_count = 0 328 rdc_data = False 329 rdc_bc_data = False 330 norm2_flag = True 331 for interatom in interatomic_loop(): 332 # Increment the counter. 333 interatom_count += 1 334 335 # Data checks. 336 if hasattr(interatom, 'rdc') and align_id in interatom.rdc: 337 rdc_data = True 338 if hasattr(interatom, 'rdc_bc') and align_id in interatom.rdc_bc: 339 rdc_bc_data = True 340 341 # Skip containers without RDC data. 342 if not hasattr(interatom, 'rdc') or not hasattr(interatom, 'rdc_bc') or not align_id in interatom.rdc or interatom.rdc[align_id] == None or not align_id in interatom.rdc_bc or interatom.rdc_bc[align_id] == None: 343 continue 344 345 # Get the spins. 346 spin1 = return_spin(interatom.spin_id1) 347 spin2 = return_spin(interatom.spin_id2) 348 349 # Sum of squares. 350 sse = sse + (interatom.rdc[align_id] - interatom.rdc_bc[align_id])**2 351 352 # Sum the RDCs squared (for one type of normalisation). 353 D2_sum = D2_sum + interatom.rdc[align_id]**2 354 355 # Gyromagnetic ratios. 356 g1 = return_gyromagnetic_ratio(spin1.isotope) 357 g2 = return_gyromagnetic_ratio(spin2.isotope) 358 359 # Calculate the RDC dipolar constant (in Hertz, and the 3 comes from the alignment tensor), and append it to the list. 360 dj_new = 3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r) 361 if norm2_flag and dj != None and dj_new != dj: 362 warn(RelaxWarning("The dipolar constant is not the same for all RDCs, skipping the Q factor normalised with 2Da^2(4 + 3R)/5.")) 363 norm2_flag = False 364 else: 365 dj = dj_new 366 367 # Increment the number of data sets. 368 N = N + 1 369 370 # Warnings (and then exit). 371 if not interatom_count: 372 warn(RelaxWarning("No interatomic data containers have been used in the calculation.")) 373 return 374 if not rdc_data: 375 warn(RelaxWarning("No RDC data can be found.")) 376 return 377 if not rdc_bc_data: 378 warn(RelaxWarning("No back-calculated RDC data can be found.")) 379 return 380 381 # Normalisation factor of 2Da^2(4 + 3R)/5. 382 if norm2_flag: 383 D = dj * cdp.align_tensors[cdp.align_ids.index(align_id)].A_diag 384 Da = 1.0/3.0 * (D[2, 2] - (D[0, 0]+D[1, 1])/2.0) 385 Dr = 1.0/3.0 * (D[0, 0] - D[1, 1]) 386 if Da == 0: 387 R = nan 388 else: 389 R = Dr / Da 390 norm = 2.0 * (Da)**2 * (4.0 + 3.0*R**2)/5.0 391 if Da == 0.0: 392 norm = 1e-15 393 394 # The Q-factor for the alignment. 395 cdp.q_factors_rdc[align_id] = sqrt(sse / N / norm) 396 397 else: 398 cdp.q_factors_rdc[align_id] = 0.0 399 400 # The second Q-factor definition. 401 cdp.q_factors_rdc_norm2[align_id] = sqrt(sse / D2_sum) 402 403 # The total Q-factor. 404 cdp.q_rdc = 0.0 405 cdp.q_rdc_norm2 = 0.0 406 for id in cdp.q_factors_rdc: 407 cdp.q_rdc = cdp.q_rdc + cdp.q_factors_rdc[id]**2 408 for id in cdp.q_factors_rdc_norm2: 409 cdp.q_rdc_norm2 = cdp.q_rdc_norm2 + cdp.q_factors_rdc_norm2[id]**2 410 cdp.q_rdc = sqrt(cdp.q_rdc / len(cdp.q_factors_rdc)) 411 cdp.q_rdc_norm2 = sqrt(cdp.q_rdc_norm2 / len(cdp.q_factors_rdc_norm2))
412 413
414 -def read(align_id=None, file=None, dir=None, file_data=None, data_type='D', spin_id1_col=None, spin_id2_col=None, data_col=None, error_col=None, sep=None, neg_g_corr=False, absolute=False):
415 """Read the RDC data from file. 416 417 @keyword align_id: The alignment tensor ID string. 418 @type align_id: str 419 @keyword file: The name of the file to open. 420 @type file: str 421 @keyword dir: The directory containing the file (defaults to the current directory if None). 422 @type dir: str or None 423 @keyword file_data: An alternative to 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. 424 @type file_data: list of lists 425 @keyword data_type: A string which is set to 'D' means that the splitting in the aligned sample was assumed to be J + D, or if set to '2D' then the splitting was taken as J + 2D. 426 @keyword spin_id1_col: The column containing the spin ID strings of the first spin. 427 @type spin_id1_col: int 428 @keyword spin_id2_col: The column containing the spin ID strings of the second spin. 429 @type spin_id2_col: int 430 @keyword data_col: The column containing the RDC data in Hz. 431 @type data_col: int or None 432 @keyword error_col: The column containing the RDC errors. 433 @type error_col: int or None 434 @keyword sep: The column separator which, if None, defaults to whitespace. 435 @type sep: str or None 436 @keyword neg_g_corr: A flag which is used to correct for the negative gyromagnetic ratio of 15N. If True, a sign inversion will be applied to all RDC values to be loaded. 437 @type neg_g_corr: bool 438 @keyword absolute: A flag which if True indicates that the RDCs to load are signless. All RDCs will then be converted to positive values. 439 @type absolute: bool 440 """ 441 442 # Test if the current data pipe exists. 443 pipes.test() 444 445 # Test if sequence data exists. 446 if not exists_mol_res_spin_data(): 447 raise RelaxNoSequenceError 448 449 # Either the data or error column must be supplied. 450 if data_col == None and error_col == None: 451 raise RelaxError("One of either the data or error column must be supplied.") 452 453 # Store the data type as global data (need for the conversion of RDC data). 454 if not hasattr(cdp, 'rdc_data_types'): 455 cdp.rdc_data_types = {} 456 if not align_id in cdp.rdc_data_types: 457 cdp.rdc_data_types[align_id] = data_type 458 459 # Spin specific data. 460 ##################### 461 462 # Extract the data from the file. 463 file_data = extract_data(file, dir, sep=sep) 464 465 # Loop over the RDC data. 466 data = [] 467 for line in file_data: 468 # Invalid columns. 469 if spin_id1_col > len(line): 470 warn(RelaxWarning("The data %s is invalid, no first spin ID column can be found." % line)) 471 continue 472 if spin_id2_col > len(line): 473 warn(RelaxWarning("The data %s is invalid, no second spin ID column can be found." % line)) 474 continue 475 if data_col and data_col > len(line): 476 warn(RelaxWarning("The data %s is invalid, no data column can be found." % line)) 477 continue 478 if error_col and error_col > len(line): 479 warn(RelaxWarning("The data %s is invalid, no error column can be found." % line)) 480 continue 481 482 # Unpack. 483 spin_id1 = line[spin_id1_col-1] 484 spin_id2 = line[spin_id2_col-1] 485 value = None 486 if data_col: 487 value = line[data_col-1] 488 error = None 489 if error_col: 490 error = line[error_col-1] 491 492 # Convert the spin IDs. 493 if spin_id1[0] in ["\"", "\'"]: 494 spin_id1 = eval(spin_id1) 495 if spin_id2[0] in ["\"", "\'"]: 496 spin_id2 = eval(spin_id2) 497 498 # Convert and check the value. 499 if value == 'None': 500 value = None 501 if value != None: 502 try: 503 value = float(value) 504 except ValueError: 505 warn(RelaxWarning("The RDC value of the line %s is invalid." % line)) 506 continue 507 508 # Convert and check the error. 509 if error == 'None': 510 error = None 511 if error != None: 512 try: 513 error = float(error) 514 except ValueError: 515 warn(RelaxWarning("The error value of the line %s is invalid." % line)) 516 continue 517 518 # Get the spins. 519 spin1 = return_spin(spin_id1) 520 spin2 = return_spin(spin_id2) 521 522 # Check the spin IDs. 523 if not spin1: 524 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id1, line))) 525 continue 526 if not spin2: 527 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id2, line))) 528 continue 529 530 # Test the error value (cannot be 0.0). 531 if error == 0.0: 532 raise RelaxError("An invalid error value of zero has been encountered.") 533 534 # Remap the spin IDs. 535 spin_id1 = spin1._spin_ids[0] 536 spin_id2 = spin2._spin_ids[0] 537 538 # Get the interatomic data container. 539 interatom = return_interatom(spin_id1, spin_id2) 540 541 # Create the container if needed. 542 if interatom == None: 543 interatom = create_interatom(spin_id1=spin_id1, spin_id2=spin_id2) 544 545 # Convert and add the data. 546 if data_col: 547 # Data conversion. 548 value = convert(value, align_id, to_intern=True) 549 550 # Correction for the negative gyromagnetic ratio of 15N. 551 if neg_g_corr and value != None: 552 value = -value 553 554 # Absolute values. 555 if absolute: 556 # Force the value to be positive. 557 value = abs(value) 558 559 # Initialise. 560 if not hasattr(interatom, 'rdc'): 561 interatom.rdc = {} 562 563 # Add the value. 564 interatom.rdc[align_id] = value 565 566 # Store the absolute value flag. 567 if not hasattr(interatom, 'absolute_rdc'): 568 interatom.absolute_rdc = {} 569 interatom.absolute_rdc[align_id] = absolute 570 571 # Convert and add the error. 572 if error_col: 573 # Data conversion. 574 error = convert(error, align_id, to_intern=True) 575 576 # Initialise. 577 if not hasattr(interatom, 'rdc_err'): 578 interatom.rdc_err = {} 579 580 # Append the error. 581 interatom.rdc_err[align_id] = error 582 583 # Append the data for printout. 584 data.append([spin_id1, spin_id2, repr(value), repr(error)]) 585 586 # No data, so fail hard! 587 if not len(data): 588 raise RelaxError("No RDC data could be extracted.") 589 590 # Print out. 591 print("The following RDCs have been loaded into the relax data store:\n") 592 write_data(out=sys.stdout, headings=["Spin_ID1", "Spin_ID2", "Value", "Error"], data=data) 593 594 # Initialise some global structures. 595 if not hasattr(cdp, 'align_ids'): 596 cdp.align_ids = [] 597 if not hasattr(cdp, 'rdc_ids'): 598 cdp.rdc_ids = [] 599 600 # Add the RDC id string. 601 if align_id not in cdp.align_ids: 602 cdp.align_ids.append(align_id) 603 if align_id not in cdp.rdc_ids: 604 cdp.rdc_ids.append(align_id)
605 606
607 -def weight(align_id=None, spin_id=None, weight=1.0):
608 """Set optimisation weights on the RDC data. 609 610 @keyword align_id: The alignment tensor ID string. 611 @type align_id: str 612 @keyword spin_id: The spin ID string. 613 @type spin_id: None or str 614 @keyword weight: The optimisation weight. The higher the value, the more importance the RDC will have. 615 @type weight: float or int. 616 """ 617 618 # Test if sequence data exists. 619 if not exists_mol_res_spin_data(): 620 raise RelaxNoSequenceError 621 622 # Test if data corresponding to 'align_id' exists. 623 if not hasattr(cdp, 'rdc_ids') or align_id not in cdp.rdc_ids: 624 raise RelaxNoRDCError(align_id) 625 626 # Loop over the interatomic data. 627 for interatom in interatomic_loop(): 628 # No data structure. 629 if not hasattr(interatom, 'rdc_weight'): 630 interatom.rdc_weight = {} 631 632 # Set the weight. 633 interatom.rdc_weight[align_id] = weight
634 635
636 -def write(align_id=None, file=None, dir=None, bc=False, force=False):
637 """Display the RDC data corresponding to the alignment ID. 638 639 @keyword align_id: The alignment tensor ID string. 640 @type align_id: str 641 @keyword file: The file name or object to write to. 642 @type file: str or file object 643 @keyword dir: The name of the directory to place the file into (defaults to the current directory). 644 @type dir: str 645 @keyword bc: The back-calculation flag which if True will cause the back-calculated rather than measured data to be written. 646 @type bc: bool 647 @keyword force: A flag which if True will cause any pre-existing file to be overwritten. 648 @type force: bool 649 """ 650 651 # Test if the current pipe exists. 652 pipes.test() 653 654 # Test if the sequence data is loaded. 655 if not exists_mol_res_spin_data(): 656 raise RelaxNoSequenceError 657 658 # Test if data corresponding to 'align_id' exists. 659 if not hasattr(cdp, 'rdc_ids') or align_id not in cdp.rdc_ids: 660 raise RelaxNoRDCError(align_id) 661 662 # Open the file for writing. 663 file = open_write_file(file, dir, force) 664 665 # Loop over the interatomic data containers and collect the data. 666 data = [] 667 for interatom in interatomic_loop(): 668 # Skip containers with no RDCs. 669 if not bc and (not hasattr(interatom, 'rdc') or align_id not in interatom.rdc.keys()): 670 continue 671 elif bc and (not hasattr(interatom, 'rdc_bc') or align_id not in interatom.rdc_bc.keys()): 672 continue 673 674 # Append the spin data. 675 data.append([]) 676 data[-1].append(interatom.spin_id1) 677 data[-1].append(interatom.spin_id2) 678 679 # The value. 680 if bc: 681 data[-1].append(repr(convert(interatom.rdc_bc[align_id], align_id))) 682 else: 683 data[-1].append(repr(convert(interatom.rdc[align_id], align_id))) 684 685 # The error. 686 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err.keys(): 687 data[-1].append(repr(convert(interatom.rdc_err[align_id], align_id))) 688 else: 689 data[-1].append(repr(None)) 690 691 # Write out. 692 write_data(out=file, headings=["Spin_ID1", "Spin_ID2", "RDCs", "RDC_error"], data=data)
693