1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for the manipulation of RDC data."""
24
25
26 from copy import deepcopy
27 from math import ceil, floor, pi, sqrt
28 from numpy import array, int32, float64, ones, transpose, zeros
29 from numpy.linalg import norm
30 import sys
31 from warnings import warn
32
33
34 from lib.check_types import is_float
35 from lib.float import nan
36 from lib.alignment.rdc import ave_rdc_tensor
37 from lib.errors import RelaxError, RelaxNoAlignError, RelaxNoJError, RelaxNoRDCError, RelaxNoSequenceError, RelaxSpinTypeError
38 from lib.io import extract_data, open_write_file, strip, write_data
39 from lib.periodic_table import periodic_table
40 from lib.physical_constants import dipolar_constant
41 from lib.plotting.api import write_xy_data, write_xy_header
42 from lib.warnings import RelaxWarning, RelaxSpinTypeWarning
43 from pipe_control import pipes
44 from pipe_control.align_tensor import get_tensor_index, get_tensor_object, opt_uses_align_data, opt_uses_tensor
45 from pipe_control.interatomic import consistent_interatomic_data, create_interatom, interatomic_loop, return_interatom
46 from pipe_control.mol_res_spin import exists_mol_res_spin_data, is_pseudoatom, pseudoatom_loop, return_spin
47 from pipe_control.pipes import check_pipe
48
49
51 """Back calculate the RDC from the alignment tensor and unit bond vectors.
52
53 @keyword align_id: The alignment tensor ID string.
54 @type align_id: str
55 """
56
57
58 check_pipe_setup(rdc_id=align_id, sequence=True, N=True, tensors=True)
59
60
61 if align_id:
62 align_ids = [align_id]
63 else:
64 align_ids = cdp.align_ids
65
66
67 for align_id in align_ids:
68
69 if not hasattr(cdp, 'rdc_ids'):
70 cdp.rdc_ids = []
71
72
73 if align_id not in cdp.rdc_ids:
74 cdp.rdc_ids.append(align_id)
75
76
77 weights = ones(cdp.N, float64) / cdp.N
78
79
80 unit_vect = zeros((cdp.N, 3), float64)
81
82
83 count = 0
84 for interatom in interatomic_loop():
85
86 if not hasattr(interatom, 'vector'):
87 continue
88
89
90 spin1 = return_spin(interatom.spin_id1)
91 spin2 = return_spin(interatom.spin_id2)
92
93
94 if not hasattr(spin1, 'isotope'):
95 raise RelaxSpinTypeError(interatom.spin_id1)
96 if not hasattr(spin2, 'isotope'):
97 raise RelaxSpinTypeError(interatom.spin_id2)
98
99
100 if is_float(interatom.vector[0]):
101 vectors = [interatom.vector]
102 else:
103 vectors = interatom.vector
104
105
106 g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
107 g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)
108
109
110 dj = 3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r)
111
112
113 for c in range(cdp.N):
114 unit_vect[c] = vectors[c] / norm(vectors[c])
115
116
117 if not hasattr(interatom, 'rdc_bc'):
118 interatom.rdc_bc = {}
119
120
121 for id in align_ids:
122
123 interatom.rdc_bc[id] = ave_rdc_tensor(dj, unit_vect, cdp.N, cdp.align_tensors[get_tensor_index(align_id=id)].A, weights=weights)
124
125
126 if hasattr(interatom, 'rdc_data_types') and align_id in interatom.rdc_data_types and interatom.rdc_data_types[align_id] == 'T':
127 if not hasattr(interatom, 'j_coupling'):
128 raise RelaxNoJError
129
130 interatom.rdc_bc[id] += interatom.j_coupling
131
132
133 if hasattr(interatom, 'absolute_rdc') and id in interatom.absolute_rdc and interatom.absolute_rdc[id]:
134 interatom.rdc_bc[id] = abs(interatom.rdc_bc[id])
135
136
137 count += 1
138
139
140 if not count:
141 warn(RelaxWarning("No RDCs have been back calculated, probably due to missing bond vector information."))
142
143
144 -def check_pipe_setup(pipe=None, rdc_id=None, sequence=False, N=False, tensors=False, rdc=False):
145 """Check that the current data pipe has been setup sufficiently.
146
147 @keyword pipe: The data pipe to check, defaulting to the current pipe.
148 @type pipe: None or str
149 @keyword rdc_id: The RDC ID string to check for in cdp.rdc_ids.
150 @type rdc_id: None or str
151 @keyword sequence: A flag which when True will invoke the sequence data check.
152 @type sequence: bool
153 @keyword N: A flag which if True will check that cdp.N is set.
154 @type N: bool
155 @keyword tensors: A flag which if True will check that alignment tensors exist.
156 @type tensors: bool
157 @keyword rdc: A flag which if True will check that RDCs exist.
158 @type rdc: bool
159 """
160
161
162 if pipe == None:
163 pipe = pipes.cdp_name()
164
165
166 dp = pipes.get_pipe(pipe)
167
168
169 check_pipe(pipe)
170
171
172 if sequence and not exists_mol_res_spin_data(pipe):
173 raise RelaxNoSequenceError(pipe)
174
175
176 if N and not hasattr(dp, 'N'):
177 raise RelaxError("The number of states N has not been set.")
178
179
180 if tensors and (not hasattr(dp, 'align_tensors') or len(dp.align_tensors) == 0):
181 raise RelaxNoTensorError('alignment')
182
183
184 if rdc_id and (not hasattr(dp, 'align_ids') or rdc_id not in dp.align_ids):
185 raise RelaxNoAlignError(rdc_id, pipe)
186
187
188 if rdc and not hasattr(dp, 'align_ids'):
189 raise RelaxNoAlignError()
190 if rdc and not hasattr(dp, 'rdc_ids'):
191 raise RelaxNoRDCError()
192 elif rdc and rdc_id and rdc_id not in dp.rdc_ids:
193 raise RelaxNoRDCError(rdc_id)
194
195
197 """Check if all data required for calculating the RDC is present.
198
199 @param interatom: The interatomic data container.
200 @type interatom: InteratomContainer instance
201 @return: True if all data required for calculating the RDC is present, False otherwise.
202 @rtype: bool
203 """
204
205
206 if not interatom.select:
207 return False
208
209
210 if not hasattr(interatom, 'rdc'):
211 return False
212
213
214 if opt_uses_j_couplings() and not hasattr(interatom, 'j_coupling'):
215 return False
216
217
218 spin1 = return_spin(interatom.spin_id1)
219 spin2 = return_spin(interatom.spin_id2)
220
221
222 if not hasattr(spin1, 'isotope'):
223 warn(RelaxSpinTypeWarning(interatom.spin_id1))
224 return False
225 if not hasattr(spin2, 'isotope'):
226 warn(RelaxSpinTypeWarning(interatom.spin_id2))
227 return False
228 if is_pseudoatom(spin1) and is_pseudoatom(spin2):
229 warn(RelaxWarning("Support for both spins being in a dipole pair being pseudo-atoms is not implemented yet."))
230 return False
231
232
233 if is_pseudoatom(spin1) or is_pseudoatom(spin2):
234
235 pseudospin = spin1
236 base_spin_id = interatom.spin_id2
237 pseudospin_id = interatom.spin_id1
238 if is_pseudoatom(spin2):
239 pseudospin = spin2
240 base_spin_id = interatom.spin_id1
241 pseudospin_id = interatom.spin_id2
242
243
244 for spin, spin_id in pseudoatom_loop(pseudospin, return_id=True):
245
246 pseudo_interatom = return_interatom(spin_id1=spin_id, spin_id2=base_spin_id)
247
248
249 if not hasattr(pseudo_interatom, 'vector'):
250 warn(RelaxWarning("The interatomic vector is missing for the spin pair '%s' and '%s' of the pseudo-atom '%s', skipping the RDC for the spin pair '%s' and '%s'." % (pseudo_interatom.spin_id1, pseudo_interatom.spin_id2, pseudospin_id, base_spin_id, pseudospin_id)))
251 return False
252
253
254 if not hasattr(pseudo_interatom, 'r'):
255 warn(RelaxWarning("The averaged interatomic distance between spins '%s' and '%s' for the pseudo-atom '%s' has not been set yet." % (spin_id, base_spin_id, pseudospin_id)))
256 return False
257
258
259 else:
260
261 if not hasattr(interatom, 'vector'):
262 warn(RelaxWarning("The interatomic vector is missing, skipping the spin pair '%s' and '%s'." % (interatom.spin_id1, interatom.spin_id2)))
263 return False
264
265
266 if not hasattr(interatom, 'r'):
267 warn(RelaxWarning("The averaged interatomic distance between spins '%s' and '%s' has not been set yet." % (interatom.spin_id1, interatom.spin_id2)))
268 return False
269
270
271 return True
272
273
274 -def convert(value, data_type, align_id, to_intern=False):
275 """Convert the RDC based on the 'D' or '2D' data type.
276
277 @param value: The value or error to convert.
278 @type value: float or None
279 @param data_type: The RDC data type. Either 'D', '2D' or 'T'.
280 @type data_type: str
281 @param align_id: The alignment tensor ID string.
282 @type align_id: str
283 @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.
284 @type to_intern: bool
285 @return: The converted value.
286 @rtype: float or None
287 """
288
289
290 if value == None:
291 return None
292
293
294 factor = 1.0
295 if data_type == '2D':
296
297 if to_intern:
298 factor = 2.0
299
300
301 else:
302 factor = 0.5
303
304
305 return value * factor
306
307
308 -def copy(pipe_from=None, pipe_to=None, align_id=None, back_calc=True):
309 """Copy the RDC data from one data pipe to another.
310
311 @keyword pipe_from: The data pipe to copy the RDC data from. This defaults to the current data pipe.
312 @type pipe_from: str
313 @keyword pipe_to: The data pipe to copy the RDC data to. This defaults to the current data pipe.
314 @type pipe_to: str
315 @keyword align_id: The alignment ID string.
316 @type align_id: str
317 @keyword back_calc: A flag which if True will cause any back-calculated RDCs present to also be copied with the real values and errors.
318 @type back_calc: bool
319 """
320
321
322 if pipe_from == None and pipe_to == None:
323 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.")
324 elif pipe_from == None:
325 pipe_from = pipes.cdp_name()
326 elif pipe_to == None:
327 pipe_to = pipes.cdp_name()
328
329
330 check_pipe_setup(pipe=pipe_from, rdc_id=align_id, sequence=True, rdc=True)
331 check_pipe_setup(pipe=pipe_to, sequence=True)
332
333
334 dp_from = pipes.get_pipe(pipe_from)
335 dp_to = pipes.get_pipe(pipe_to)
336
337
338 if align_id == None:
339 align_ids = dp_from.align_ids
340 else:
341 align_ids = [align_id]
342
343
344 if not hasattr(dp_to, 'align_ids'):
345 dp_to.align_ids = []
346 if not hasattr(dp_to, 'rdc_ids'):
347 dp_to.rdc_ids = []
348
349
350 for align_id in align_ids:
351
352 print("\nCoping RDCs for the alignment ID '%s'." % align_id)
353
354
355 if align_id not in dp_to.align_ids and align_id not in dp_to.align_ids:
356 dp_to.align_ids.append(align_id)
357 if align_id in dp_from.rdc_ids and align_id not in dp_to.rdc_ids:
358 dp_to.rdc_ids.append(align_id)
359
360
361 data = []
362 for interatom_from in interatomic_loop(pipe=pipe_from):
363
364 interatom_to = []
365 for interatom in interatomic_loop(selection1=interatom_from.spin_id1, selection2=interatom_from.spin_id2, pipe=pipe_to, skip_desel=False):
366 interatom_to.append(interatom)
367
368
369 if interatom_to == []:
370 warn(RelaxWarning("The interatomic data container between the spins '%s' and '%s' cannot be found in the target data pipe." % (interatom_from.spin_id1, interatom_from.spin_id2)))
371 continue
372
373
374 elif len(interatom_to) != 1:
375 raise RelaxError("Too many interatomic data containers between the spins '%s' and '%s' exist in the target data pipe." % (interatom_from.spin_id1, interatom_from.spin_id2))
376
377
378 interatom_to = interatom_to[0]
379
380
381 if (not hasattr(interatom_from, 'rdc') or not align_id in interatom_from.rdc) and (not hasattr(interatom_from, 'rdc_err') or not align_id in interatom_from.rdc_err):
382 continue
383
384
385 if hasattr(interatom_from, 'rdc') and not hasattr(interatom_to, 'rdc'):
386 interatom_to.rdc = {}
387 if back_calc and hasattr(interatom_from, 'rdc_bc') and not hasattr(interatom_to, 'rdc_bc'):
388 interatom_to.rdc_bc = {}
389 if hasattr(interatom_from, 'rdc_err') and not hasattr(interatom_to, 'rdc_err'):
390 interatom_to.rdc_err = {}
391 if hasattr(interatom_from, 'rdc_data_types') and not hasattr(interatom_to, 'rdc_data_types'):
392 interatom_to.rdc_data_types = {}
393 if hasattr(interatom_from, 'absolute_rdc') and not hasattr(interatom_to, 'absolute_rdc'):
394 interatom_to.absolute_rdc = {}
395
396
397 value = None
398 error = None
399 value_bc = None
400 data_type = None
401 absolute_rdc = None
402 if hasattr(interatom_from, 'rdc'):
403 value = interatom_from.rdc[align_id]
404 interatom_to.rdc[align_id] = value
405 if back_calc and hasattr(interatom_from, 'rdc_bc'):
406 value_bc = interatom_from.rdc_bc[align_id]
407 interatom_to.rdc_bc[align_id] = value_bc
408 if hasattr(interatom_from, 'rdc_err'):
409 error = interatom_from.rdc_err[align_id]
410 interatom_to.rdc_err[align_id] = error
411 if hasattr(interatom_from, 'rdc_data_types'):
412 data_type = interatom_from.rdc_data_types[align_id]
413 interatom_to.rdc_data_types[align_id] = data_type
414 if hasattr(interatom_from, 'absolute_rdc'):
415 absolute_rdc = interatom_from.absolute_rdc[align_id]
416 interatom_to.absolute_rdc[align_id] = absolute_rdc
417
418
419 data.append([interatom_from.spin_id1, interatom_from.spin_id2])
420 if is_float(value):
421 data[-1].append("%20.15f" % value)
422 else:
423 data[-1].append("%20s" % value)
424 if back_calc:
425 if is_float(value_bc):
426 data[-1].append("%20.15f" % value_bc)
427 else:
428 data[-1].append("%20s" % value_bc)
429 if is_float(error):
430 data[-1].append("%20.15f" % error)
431 else:
432 data[-1].append("%20s" % error)
433 data[-1].append("%20s" % data_type)
434 data[-1].append("%20s" % absolute_rdc)
435
436
437 print("The following RDCs have been copied:\n")
438 if back_calc:
439 write_data(out=sys.stdout, headings=["Spin_ID1", "Spin_ID2", "Value", "Back-calculated", "Error", "Data_type", "Absolute_RDC"], data=data)
440 else:
441 write_data(out=sys.stdout, headings=["Spin_ID1", "Spin_ID2", "Value", "Error", "Data_type", "Absolute_RDC"], data=data)
442
443
444 -def corr_plot(format=None, title=None, subtitle=None, file=None, dir=None, force=False):
445 """Generate a correlation plot of the measured vs. back-calculated RDCs.
446
447 @keyword format: The format for the plot file. The following values are accepted: 'grace', a Grace plot; None, a plain text file.
448 @type format: str or None
449 @keyword title: The title for the plot, overriding the default.
450 @type title: None or str
451 @keyword subtitle: The subtitle for the plot, overriding the default.
452 @type subtitle: None or str
453 @keyword file: The file name or object to write to.
454 @type file: str or file object
455 @keyword dir: The name of the directory to place the file into (defaults to the current directory).
456 @type dir: str
457 @keyword force: A flag which if True will cause any pre-existing file to be overwritten.
458 @type force: bool
459 """
460
461
462 check_pipe_setup(sequence=True)
463
464
465 if not hasattr(cdp, 'rdc_ids') or not cdp.rdc_ids:
466 warn(RelaxWarning("No RDC data exists, skipping file creation."))
467 return
468
469
470 file = open_write_file(file, dir, force)
471
472
473 data = []
474 orig_title = title
475 if orig_title == None:
476 title = "RDC correlation plot"
477 axis_labels = ["Back-calculated RDC (Hz)", "Measured RDC (Hz)"]
478
479
480 data.append([[-100, -100, 0], [100, 100, 0]])
481
482
483 min_rdc = 1e100
484 max_rdc = -1e100
485 for align_id in cdp.rdc_ids:
486
487 data.append([])
488
489
490 err_flag = False
491 for interatom in interatomic_loop():
492
493 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err:
494 err_flag = True
495 break
496
497
498 for interatom in interatomic_loop(skip_desel=True):
499
500 if not hasattr(interatom, 'rdc') or not hasattr(interatom, 'rdc_bc') or not align_id in interatom.rdc or not align_id in interatom.rdc_bc:
501 continue
502 if interatom.rdc[align_id] == None or interatom.rdc_bc[align_id] == None:
503 continue
504
505
506 rdc_bc = convert(interatom.rdc_bc[align_id], interatom.rdc_data_types[align_id], align_id)
507 rdc = convert(interatom.rdc[align_id], interatom.rdc_data_types[align_id], align_id)
508
509
510 if hasattr(interatom, 'rdc_data_types') and align_id in interatom.rdc_data_types and interatom.rdc_data_types[align_id] == 'T':
511
512 if not interatom.absolute_rdc[align_id]:
513 rdc_bc -= interatom.j_coupling
514 rdc -= interatom.j_coupling
515
516
517 else:
518 if orig_title == None:
519 title = "T = J+D correlation plot"
520 axis_labels = ["Measured T = J+D (Hz)", "Back-calculated T = J+D (Hz)"]
521
522
523 data[-1].append([rdc_bc, rdc])
524
525
526 if rdc < min_rdc:
527 min_rdc = rdc
528 if rdc_bc < min_rdc:
529 min_rdc = rdc_bc
530
531
532 if rdc > max_rdc:
533 max_rdc = rdc
534 if rdc_bc > max_rdc:
535 max_rdc = rdc_bc
536
537
538 if err_flag:
539 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err:
540 data[-1][-1].append(convert(interatom.rdc_err[align_id], interatom.rdc_data_types[align_id], align_id))
541 else:
542 data[-1][-1].append(None)
543
544
545 data[-1][-1].append("%s-%s" % (interatom.spin_id1, interatom.spin_id2))
546
547
548 size = len(data)
549
550
551 max_rdc = float(ceil(max_rdc))
552 min_rdc = float(floor(min_rdc))
553
554
555 data = [data]
556
557
558 if err_flag:
559 graph_type = 'xydy'
560 else:
561 graph_type = 'xy'
562
563
564 write_xy_header(format=format, file=file, title=title, subtitle=subtitle, world=[[min_rdc, min_rdc, max_rdc, max_rdc]], sets=[size], set_names=[[None]+cdp.rdc_ids], linestyle=[[2]+[0]*size], data_type=['rdc', 'rdc_bc'], axis_labels=[axis_labels], tick_major_spacing=[[10, 10]], tick_minor_count=[[9, 9]], legend_pos=[[1, 0.5]])
565
566
567 write_xy_data(format=format, data=data, file=file, graph_type=graph_type, autoscale=False)
568
569
571 """Delete the RDC data corresponding to the alignment ID.
572
573 @keyword align_id: The alignment tensor ID string. If not specified, all data will be deleted.
574 @type align_id: str or None
575 """
576
577
578 check_pipe_setup(sequence=True, rdc_id=align_id, rdc=True)
579
580
581 if not align_id:
582 ids = deepcopy(cdp.rdc_ids)
583 else:
584 ids = [align_id]
585
586
587 for id in ids:
588
589 cdp.rdc_ids.pop(cdp.rdc_ids.index(id))
590
591
592 for interatom in interatomic_loop():
593
594 if hasattr(interatom, 'rdc') and id in interatom.rdc:
595 interatom.rdc.pop(id)
596
597
598 if hasattr(interatom, 'rdc_err') and id in interatom.rdc_err:
599 interatom.rdc_err.pop(id)
600
601
602 if hasattr(interatom, 'rdc_data_types') and id in interatom.rdc_data_types:
603 interatom.rdc_data_types.pop(id)
604
605
606 if not hasattr(cdp, 'pcs_ids') or id not in cdp.pcs_ids:
607 cdp.align_ids.pop(cdp.align_ids.index(id))
608
609
610 -def display(align_id=None, bc=False):
611 """Display the RDC data corresponding to the alignment ID.
612
613 @keyword align_id: The alignment tensor ID string.
614 @type align_id: str
615 @keyword bc: The back-calculation flag which if True will cause the back-calculated rather than measured data to be displayed.
616 @type bc: bool
617 """
618
619
620 check_pipe_setup(sequence=True, rdc_id=align_id, rdc=True)
621
622
623 write(align_id=align_id, file=sys.stdout, bc=bc)
624
625
627 """Determine of J couplings are needed for optimisation.
628
629 @return: True if J couplings are required, False otherwise.
630 @rtype: bool
631 """
632
633
634 for align_id in cdp.align_ids:
635 for interatom in interatomic_loop():
636 if hasattr(interatom, 'rdc_data_types') and align_id in interatom.rdc_data_types and interatom.rdc_data_types[align_id] == 'T':
637 return True
638
639
640 return False
641
642
644 """Determine if the RDC data for the given alignment ID is needed for optimisation.
645
646 @param align_id: The alignment ID string.
647 @type align_id: str
648 @return: True if the RDC data is to be used for optimisation, False otherwise.
649 @rtype: bool
650 """
651
652
653 if not hasattr(cdp, 'rdc_ids'):
654 return False
655
656
657 if align_id not in cdp.rdc_ids:
658 return False
659
660
661 tensor_flag = opt_uses_tensor(get_tensor_object(align_id))
662
663
664 pos_flag = False
665 if hasattr(cdp, 'paramag_centre_fixed') and not cdp.paramag_centre_fixed:
666 pos_flag = True
667
668
669 prob_flag = False
670 if cdp.model == 'population':
671 prob_flag = True
672
673
674 if not tensor_flag and not pos_flag and not prob_flag:
675 return False
676
677
678 return True
679
680
681 -def q_factors(spin_id=None, sim_index=None, verbosity=1):
682 """Calculate the Q factors for the RDC data.
683
684 @keyword spin_id: The spin ID string used to restrict the Q factor calculation to a subset of all spins.
685 @type spin_id: None or str
686 @keyword sim_index: The optional Monte Carlo simulation index.
687 @type sim_index: None or int
688 @keyword verbosity: A flag specifying the amount of information to print. The higher the value, the greater the verbosity.
689 @type verbosity: int
690 """
691
692
693 check_pipe_setup(sequence=True)
694
695
696 sim_flag = (sim_index != None)
697
698
699 if not hasattr(cdp, 'rdc_ids') or not len(cdp.rdc_ids):
700 warn(RelaxWarning("No RDC data exists, Q factors cannot be calculated."))
701 return
702
703
704 if not sim_flag:
705 cdp.q_factors_rdc_norm_tensor_size = {}
706 cdp.q_factors_rdc_norm_squared_sum = {}
707 else:
708 if not hasattr(cdp, 'q_factors_rdc_norm_tensor_size_sim'):
709 cdp.q_factors_rdc_norm_tensor_size_sim = {}
710 if not hasattr(cdp, 'q_factors_rdc_norm_squared_sum_sim'):
711 cdp.q_factors_rdc_norm_squared_sum_sim = {}
712
713
714 for align_id in cdp.rdc_ids:
715
716 D2_sum = 0.0
717 sse = 0.0
718 if sim_flag and align_id not in cdp.q_factors_rdc_norm_tensor_size_sim:
719 cdp.q_factors_rdc_norm_tensor_size_sim[align_id] = [None] * cdp.sim_number
720 if sim_flag and align_id not in cdp.q_factors_rdc_norm_squared_sum_sim:
721 cdp.q_factors_rdc_norm_squared_sum_sim[align_id] = [None] * cdp.sim_number
722
723
724 dj = None
725 N = 0
726 interatom_count = 0
727 rdc_data = False
728 rdc_bc_data = False
729 norm2_flag = True
730 for interatom in interatomic_loop():
731 rdc_data_align_id = False
732 rdc_bc_data_align_id = False
733
734
735 interatom_count += 1
736
737
738 if not sim_flag:
739 if hasattr(interatom, 'rdc') and align_id in interatom.rdc and interatom.rdc[align_id] != None:
740 rdc_data_align_id = True
741 if hasattr(interatom, 'rdc_bc') and align_id in interatom.rdc_bc and interatom.rdc_bc[align_id] != None:
742 rdc_bc_data_align_id = True
743 else:
744 if hasattr(interatom, 'rdc_sim') and align_id in interatom.rdc_sim and interatom.rdc_sim[align_id][sim_index] != None:
745 rdc_data_align_id = True
746 if hasattr(interatom, 'rdc_sim_bc') and align_id in interatom.rdc_sim_bc and interatom.rdc_sim_bc[align_id][sim_index] != None:
747 rdc_bc_data_align_id = True
748 j_flag = False
749 if hasattr(interatom, 'rdc_data_types') and align_id in interatom.rdc_data_types and interatom.rdc_data_types[align_id] == 'T':
750 j_flag = True
751 if not hasattr(interatom, 'j_coupling'):
752 raise RelaxNoJError
753
754
755 rdc_data = rdc_data or rdc_data_align_id
756 rdc_bc_data = rdc_bc_data or rdc_bc_data_align_id
757
758
759 if not rdc_data_align_id or not rdc_bc_data_align_id:
760 continue
761
762
763 spin1 = return_spin(interatom.spin_id1)
764 spin2 = return_spin(interatom.spin_id2)
765
766
767 if not sim_flag:
768 rdc = interatom.rdc[align_id]
769 rdc_bc = interatom.rdc_bc[align_id]
770 else:
771 rdc = interatom.rdc_sim[align_id][sim_index]
772 rdc_bc = interatom.rdc_sim_bc[align_id][sim_index]
773
774
775 sse = sse + (rdc - rdc_bc)**2
776
777
778 if j_flag:
779 D2_sum = D2_sum + (rdc - interatom.j_coupling)**2
780 else:
781 D2_sum = D2_sum + rdc**2
782
783
784 if norm2_flag and not hasattr(cdp, 'align_tensors'):
785 if not sim_flag:
786 warn(RelaxWarning("No alignment tensors are present for the alignment '%s', skipping the Q factor normalised with 2Da^2(4 + 3R)/5." % align_id))
787 norm2_flag = False
788
789
790 if norm2_flag and (is_pseudoatom(spin1) or is_pseudoatom(spin2)):
791 if not sim_flag:
792 warn(RelaxWarning("Pseudo-atoms are present for the alignment '%s', skipping the Q factor normalised with 2Da^2(4 + 3R)/5." % align_id))
793 norm2_flag = False
794
795
796 if norm2_flag:
797
798 if not hasattr(spin1, 'isotope'):
799 raise RelaxSpinTypeError(spin_id=interatom.spin_id1)
800 if not hasattr(spin2, 'isotope'):
801 raise RelaxSpinTypeError(spin_id=interatom.spin_id2)
802
803
804 g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
805 g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)
806
807
808 dj_new = 3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r)
809 if dj != None and dj_new != dj:
810 if not sim_flag:
811 warn(RelaxWarning("The dipolar constant is not the same for all RDCs for the alignment '%s', skipping the Q factor normalised with 2Da^2(4 + 3R)/5." % align_id))
812 norm2_flag = False
813 else:
814 dj = dj_new
815
816
817 N = N + 1
818
819
820 if not interatom_count:
821 warn(RelaxWarning("No interatomic data containers have been used in the calculation, skipping the RDC Q factor calculation."))
822 return
823 if not rdc_data:
824 warn(RelaxWarning("No RDC data can be found for the alignment ID '%s', skipping the RDC Q factor calculation for this alignment." % align_id))
825 continue
826 if not rdc_bc_data:
827 warn(RelaxWarning("No back-calculated RDC data can be found for the alignment ID '%s', skipping the RDC Q factor calculation for this alignment." % align_id))
828 continue
829
830
831 if sim_flag and not align_id in cdp.q_factors_rdc_norm_tensor_size_sim:
832 cdp.q_factors_rdc_norm_tensor_size_sim[align_id] = [None] * cdp.sim_number
833
834
835 if norm2_flag:
836 A = cdp.align_tensors[cdp.align_ids.index(align_id)]
837 if not sim_flag:
838 D = dj * A.A_diag
839 else:
840 D = dj * A.A_diag_sim[sim_index]
841 Da = 1.0/3.0 * (D[2, 2] - (D[0, 0]+D[1, 1])/2.0)
842 Dr = 1.0/3.0 * (D[0, 0] - D[1, 1])
843 if Da == 0:
844 R = nan
845 else:
846 R = Dr / Da
847 norm = 2.0 * (Da)**2 * (4.0 + 3.0*R**2)/5.0
848 if Da == 0.0:
849 norm = 1e-15
850
851
852 if sim_flag:
853 cdp.q_factors_rdc_norm_tensor_size_sim[align_id][sim_index] = sqrt(sse / N / norm)
854 else:
855 cdp.q_factors_rdc_norm_tensor_size[align_id] = sqrt(sse / N / norm)
856
857 else:
858 if sim_flag:
859 cdp.q_factors_rdc_norm_tensor_size_sim[align_id][sim_index] = 0.0
860 else:
861 cdp.q_factors_rdc_norm_tensor_size[align_id] = 0.0
862
863
864 if sim_flag:
865 cdp.q_factors_rdc_norm_squared_sum_sim[align_id][sim_index] = sqrt(sse / D2_sum)
866 else:
867 cdp.q_factors_rdc_norm_squared_sum[align_id] = sqrt(sse / D2_sum)
868
869
870 if verbosity:
871 print("\nRDC Q factors normalised by the tensor size (2Da^2(4 + 3R)/5):")
872 for align_id in cdp.rdc_ids:
873 if align_id in cdp.q_factors_rdc_norm_tensor_size:
874 if sim_flag:
875 print(" Alignment ID '%s': %.3f" % (align_id, cdp.q_factors_rdc_norm_tensor_size_sim[align_id][sim_index]))
876 else:
877 print(" Alignment ID '%s': %.3f" % (align_id, cdp.q_factors_rdc_norm_tensor_size[align_id]))
878 print("\nRDC Q factors normalised by the sum of RDCs squared:")
879 for align_id in cdp.rdc_ids:
880 if align_id in cdp.q_factors_rdc_norm_squared_sum:
881 if sim_flag:
882 print(" Alignment ID '%s': %.13f" % (align_id, cdp.q_factors_rdc_norm_squared_sum_sim[align_id][sim_index]))
883 else:
884 print(" Alignment ID '%s': %.13f" % (align_id, cdp.q_factors_rdc_norm_squared_sum[align_id]))
885
886
887 if sim_flag:
888 if not hasattr(cdp, 'q_rdc_norm_tensor_size_sim'):
889 cdp.q_rdc_norm_tensor_size_sim = [None] * cdp.sim_number
890 if not hasattr(cdp, 'q_rdc_norm_squared_sum_sim'):
891 cdp.q_rdc_norm_squared_sum_sim = [None] * cdp.sim_number
892 cdp.q_rdc_norm_tensor_size_sim[sim_index] = 0.0
893 cdp.q_rdc_norm_squared_sum_sim[sim_index] = 0.0
894 for id in cdp.q_factors_rdc_norm_tensor_size_sim:
895 cdp.q_rdc_norm_tensor_size_sim[sim_index] = cdp.q_rdc_norm_tensor_size_sim[sim_index] + cdp.q_factors_rdc_norm_tensor_size_sim[id][sim_index]**2
896 for id in cdp.q_factors_rdc_norm_squared_sum_sim:
897 cdp.q_rdc_norm_squared_sum_sim[sim_index] = cdp.q_rdc_norm_squared_sum_sim[sim_index] + cdp.q_factors_rdc_norm_squared_sum_sim[id][sim_index]**2
898 cdp.q_rdc_norm_tensor_size_sim[sim_index] = sqrt(cdp.q_rdc_norm_tensor_size_sim[sim_index] / len(cdp.q_factors_rdc_norm_tensor_size_sim))
899 cdp.q_rdc_norm_squared_sum_sim[sim_index] = sqrt(cdp.q_rdc_norm_squared_sum_sim[sim_index] / len(cdp.q_factors_rdc_norm_squared_sum_sim))
900 else:
901 cdp.q_rdc_norm_tensor_size = 0.0
902 cdp.q_rdc_norm_squared_sum = 0.0
903 for id in cdp.q_factors_rdc_norm_tensor_size:
904 cdp.q_rdc_norm_tensor_size = cdp.q_rdc_norm_tensor_size + cdp.q_factors_rdc_norm_tensor_size[id]**2
905 for id in cdp.q_factors_rdc_norm_squared_sum:
906 cdp.q_rdc_norm_squared_sum = cdp.q_rdc_norm_squared_sum + cdp.q_factors_rdc_norm_squared_sum[id]**2
907 cdp.q_rdc_norm_tensor_size = sqrt(cdp.q_rdc_norm_tensor_size / len(cdp.q_factors_rdc_norm_tensor_size))
908 cdp.q_rdc_norm_squared_sum = sqrt(cdp.q_rdc_norm_squared_sum / len(cdp.q_factors_rdc_norm_squared_sum))
909
910
911 -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):
912 """Read the RDC data from file.
913
914 @keyword align_id: The alignment tensor ID string.
915 @type align_id: str
916 @keyword file: The name of the file to open.
917 @type file: str
918 @keyword dir: The directory containing the file (defaults to the current directory if None).
919 @type dir: str or None
920 @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.
921 @type file_data: list of lists
922 @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. If set to 'T', then the data will be marked as being J+D values.
923 @keyword spin_id1_col: The column containing the spin ID strings of the first spin.
924 @type spin_id1_col: int
925 @keyword spin_id2_col: The column containing the spin ID strings of the second spin.
926 @type spin_id2_col: int
927 @keyword data_col: The column containing the RDC data in Hz.
928 @type data_col: int or None
929 @keyword error_col: The column containing the RDC errors.
930 @type error_col: int or None
931 @keyword sep: The column separator which, if None, defaults to whitespace.
932 @type sep: str or None
933 @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.
934 @type neg_g_corr: bool
935 @keyword absolute: A flag which if True indicates that the RDCs to load are signless. All RDCs will then be converted to positive values.
936 @type absolute: bool
937 """
938
939
940 check_pipe_setup(sequence=True)
941
942
943 if data_col == None and error_col == None:
944 raise RelaxError("One of either the data or error column must be supplied.")
945
946
947 rdc_types = ['D', '2D', 'T']
948 if data_type not in rdc_types:
949 raise RelaxError("The RDC data type '%s' must be one of %s." % (data_type, rdc_types))
950
951
952
953
954
955 file_data = extract_data(file, dir, sep=sep)
956 file_data = strip(file_data, comments=True)
957
958
959 data = []
960 for line in file_data:
961
962 if spin_id1_col > len(line):
963 warn(RelaxWarning("The data %s is invalid, no first spin ID column can be found." % line))
964 continue
965 if spin_id2_col > len(line):
966 warn(RelaxWarning("The data %s is invalid, no second spin ID column can be found." % line))
967 continue
968 if data_col and data_col > len(line):
969 warn(RelaxWarning("The data %s is invalid, no data column can be found." % line))
970 continue
971 if error_col and error_col > len(line):
972 warn(RelaxWarning("The data %s is invalid, no error column can be found." % line))
973 continue
974
975
976 spin_id1 = line[spin_id1_col-1]
977 spin_id2 = line[spin_id2_col-1]
978 value = None
979 if data_col:
980 value = line[data_col-1]
981 error = None
982 if error_col:
983 error = line[error_col-1]
984
985
986 if spin_id1[0] in ["\"", "\'"]:
987 spin_id1 = eval(spin_id1)
988 if spin_id2[0] in ["\"", "\'"]:
989 spin_id2 = eval(spin_id2)
990
991
992 if value == 'None':
993 value = None
994 if value != None:
995 try:
996 value = float(value)
997 except ValueError:
998 warn(RelaxWarning("The RDC value of the line %s is invalid." % line))
999 continue
1000
1001
1002 if error == 'None':
1003 error = None
1004 if error != None:
1005 try:
1006 error = float(error)
1007 except ValueError:
1008 warn(RelaxWarning("The error value of the line %s is invalid." % line))
1009 continue
1010
1011
1012 spin1 = return_spin(spin_id1)
1013 spin2 = return_spin(spin_id2)
1014
1015
1016 if not spin1:
1017 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id1, line)))
1018 continue
1019 if not spin2:
1020 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id2, line)))
1021 continue
1022
1023
1024 interatom = return_interatom(spin_id1, spin_id2)
1025
1026
1027 if interatom == None:
1028 interatom = create_interatom(spin_id1=spin_id1, spin_id2=spin_id2)
1029
1030
1031 if error == 0.0:
1032 interatom.select = False
1033 warn(RelaxWarning("An error value of zero has been encountered, deselecting the interatomic container between spin '%s' and '%s'." % (spin_id1, spin_id2)))
1034 continue
1035
1036
1037 if not hasattr(interatom, 'rdc_data_types'):
1038 interatom.rdc_data_types = {}
1039 if not align_id in interatom.rdc_data_types:
1040 interatom.rdc_data_types[align_id] = data_type
1041
1042
1043 if data_col:
1044
1045 value = convert(value, data_type, align_id, to_intern=True)
1046
1047
1048 if neg_g_corr and value != None:
1049 value = -value
1050
1051
1052 if absolute:
1053
1054 value = abs(value)
1055
1056
1057 if not hasattr(interatom, 'rdc'):
1058 interatom.rdc = {}
1059
1060
1061 interatom.rdc[align_id] = value
1062
1063
1064 if not hasattr(interatom, 'absolute_rdc'):
1065 interatom.absolute_rdc = {}
1066 interatom.absolute_rdc[align_id] = absolute
1067
1068
1069 if error_col:
1070
1071 error = convert(error, data_type, align_id, to_intern=True)
1072
1073
1074 if not hasattr(interatom, 'rdc_err'):
1075 interatom.rdc_err = {}
1076
1077
1078 interatom.rdc_err[align_id] = error
1079
1080
1081 data.append([spin_id1, spin_id2])
1082 if is_float(value):
1083 data[-1].append("%20.15f" % value)
1084 else:
1085 data[-1].append("%20s" % value)
1086 if is_float(error):
1087 data[-1].append("%20.15f" % error)
1088 else:
1089 data[-1].append("%20s" % error)
1090
1091
1092 if not len(data):
1093 raise RelaxError("No RDC data could be extracted.")
1094
1095
1096 print("The following RDCs have been loaded into the relax data store:\n")
1097 write_data(out=sys.stdout, headings=["Spin_ID1", "Spin_ID2", "Value", "Error"], data=data)
1098
1099
1100 if not hasattr(cdp, 'align_ids'):
1101 cdp.align_ids = []
1102 if not hasattr(cdp, 'rdc_ids'):
1103 cdp.rdc_ids = []
1104
1105
1106 if align_id not in cdp.align_ids:
1107 cdp.align_ids.append(align_id)
1108 if align_id not in cdp.rdc_ids:
1109 cdp.rdc_ids.append(align_id)
1110
1111
1113 """Set up the data structures for optimisation using RDCs as base data sets.
1114
1115 @keyword sim_index: The index of the simulation to optimise. This should be None if normal optimisation is desired.
1116 @type sim_index: None or int
1117 @keyword verbosity: A flag specifying the amount of information to print. The higher the value, the greater the verbosity.
1118 @type verbosity: int
1119 @return: The assembled data structures for using RDCs as the base data for optimisation. These include:
1120 - rdc, the RDC values.
1121 - rdc_err, the RDC errors.
1122 - rdc_weight, the RDC weights.
1123 - vectors, the interatomic vectors (pseudo-atom dependent).
1124 - rdc_const, the dipolar constants (pseudo-atom dependent).
1125 - absolute, the absolute value flags (as 1's and 0's).
1126 - T_flags, the flags for T = J+D type data (as 1's and 0's).
1127 - j_couplings, the J coupling values if the RDC data type is set to T = J+D.
1128 - pseudo_flags, the list of flags indicating if the interatomic data contains a pseudo-atom (as 1's and 0's).
1129 @rtype: tuple of (numpy rank-2 float64 array, numpy rank-2 float64 array, numpy rank-2 float64 array, list of numpy rank-3 float64 arrays, list of lists of floats, numpy rank-2 int32 array, numpy rank-2 int32 array, numpy rank-2 float64 array, numpy rank-1 int32 array)
1130 """
1131
1132
1133 if verbosity:
1134 print("\nRDC data counts:")
1135
1136
1137 setup_pseudoatom_rdc()
1138
1139
1140 rdc = []
1141 rdc_err = []
1142 rdc_weight = []
1143 unit_vect = []
1144 rdc_const = []
1145 absolute = []
1146 T_flags = []
1147 j_couplings = []
1148 pseudo_flags = []
1149
1150
1151 for interatom in interatomic_loop():
1152
1153 spin1 = return_spin(interatom.spin_id1)
1154 spin2 = return_spin(interatom.spin_id2)
1155
1156
1157 if not check_rdcs(interatom):
1158 continue
1159
1160
1161 g1 = periodic_table.gyromagnetic_ratio(spin1.isotope)
1162 g2 = periodic_table.gyromagnetic_ratio(spin2.isotope)
1163
1164
1165 if is_pseudoatom(spin1) and is_pseudoatom(spin2):
1166 raise RelaxError("Support for both spins being in a dipole pair being pseudo-atoms is not implemented yet.")
1167 if is_pseudoatom(spin1) or is_pseudoatom(spin2):
1168
1169 pseudo_flags.append(1)
1170
1171
1172 if is_pseudoatom(spin1):
1173 pseudospin = spin1
1174 base_spin = spin2
1175 pseudospin_id = interatom.spin_id1
1176 base_spin_id = interatom.spin_id2
1177 else:
1178 pseudospin = spin2
1179 base_spin = spin1
1180 pseudospin_id = interatom.spin_id2
1181 base_spin_id = interatom.spin_id1
1182
1183
1184 pseudo_unit_vect = []
1185 pseudo_rdc_const = []
1186 for spin, spin_id in pseudoatom_loop(pseudospin, return_id=True):
1187
1188 pseudo_interatom = return_interatom(spin_id1=spin_id, spin_id2=base_spin_id)
1189
1190
1191 if pseudo_interatom == None:
1192 raise RelaxError("The interatomic data container between the spins '%s' and '%s' for the pseudo-atom '%s' is not defined." % (base_spin_id, spin_id, pseudospin_id))
1193
1194
1195 if is_float(interatom.vector[0]):
1196 pseudo_unit_vect.append([pseudo_interatom.vector])
1197 else:
1198 pseudo_unit_vect.append(pseudo_interatom.vector)
1199
1200
1201 pseudo_rdc_const.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, pseudo_interatom.r))
1202
1203
1204 pseudo_unit_vect = transpose(array(pseudo_unit_vect, float64), (1, 0, 2))
1205
1206
1207 unit_vect.append(pseudo_unit_vect)
1208 rdc_const.append(pseudo_rdc_const)
1209
1210
1211 else:
1212
1213 pseudo_flags.append(0)
1214
1215
1216 if is_float(interatom.vector[0]):
1217 unit_vect.append([interatom.vector])
1218 else:
1219 unit_vect.append(interatom.vector)
1220
1221
1222 rdc_const.append(3.0/(2.0*pi) * dipolar_constant(g1, g2, interatom.r))
1223
1224
1225 indices = []
1226 for i in range(len(unit_vect[-1])):
1227 if unit_vect[-1][i] == None:
1228 raise RelaxError("Unit vectors of None have been detected between the spins '%s' and '%s' %s." % (interatom.spin_id1, interatom.spin_id2, unit_vect[-1]))
1229
1230
1231 if opt_uses_j_couplings():
1232 j_couplings.append(interatom.j_coupling)
1233
1234
1235 num = None
1236 for rdc_index in range(len(unit_vect)):
1237
1238 unit_vect[rdc_index] = array(unit_vect[rdc_index], float64)
1239
1240
1241 if num == None:
1242 if unit_vect[rdc_index] != None:
1243 num = len(unit_vect[rdc_index])
1244 continue
1245
1246
1247 if unit_vect[rdc_index] != None and len(unit_vect[rdc_index]) != num:
1248 raise RelaxError("The number of interatomic vectors for all no match:\n%s" % unit_vect[rdc_index])
1249
1250
1251 if num == None:
1252 raise RelaxError("No interatomic vectors could be found.")
1253
1254
1255 for i in range(len(unit_vect)):
1256 if unit_vect[i] == None:
1257 unit_vect[i] = [[None, None, None]]*num
1258
1259
1260 for i in range(len(cdp.align_ids)):
1261
1262 align_id = cdp.align_ids[i]
1263
1264
1265 if not opt_uses_align_data(align_id):
1266 continue
1267
1268
1269 rdc.append([])
1270 rdc_err.append([])
1271 rdc_weight.append([])
1272 absolute.append([])
1273 T_flags.append([])
1274
1275
1276 j = 0
1277 for interatom in interatomic_loop():
1278
1279 spin1 = return_spin(interatom.spin_id1)
1280 spin2 = return_spin(interatom.spin_id2)
1281
1282
1283 if not check_rdcs(interatom):
1284 continue
1285
1286
1287 if align_id in interatom.rdc_data_types and interatom.rdc_data_types[align_id] == 'T':
1288 T_flags[-1].append(True)
1289 else:
1290 T_flags[-1].append(False)
1291
1292
1293 if T_flags[-1][-1] and not hasattr(interatom, 'j_coupling'):
1294 continue
1295
1296
1297 value = None
1298 error = None
1299
1300
1301 if align_id in interatom.rdc:
1302
1303 if sim_index != None:
1304 value = interatom.rdc_sim[align_id][sim_index]
1305 else:
1306 value = interatom.rdc[align_id]
1307
1308
1309 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err:
1310
1311 if T_flags[-1][-1]:
1312 error = sqrt(interatom.rdc_err[align_id]**2 + interatom.j_coupling_err**2)
1313
1314
1315 else:
1316 error = interatom.rdc_err[align_id]
1317
1318
1319 if value != None:
1320 j += 1
1321
1322
1323 rdc[-1].append(value)
1324
1325
1326 rdc_err[-1].append(error)
1327
1328
1329 if hasattr(interatom, 'rdc_weight') and align_id in interatom.rdc_weight:
1330 rdc_weight[-1].append(interatom.rdc_weight[align_id])
1331 else:
1332 rdc_weight[-1].append(1.0)
1333
1334
1335 if hasattr(interatom, 'absolute_rdc') and align_id in interatom.absolute_rdc:
1336 absolute[-1].append(interatom.absolute_rdc[align_id])
1337 else:
1338 absolute[-1].append(False)
1339
1340
1341 if verbosity:
1342 print(" Alignment ID '%s': %i" % (align_id, j))
1343
1344
1345 rdc = array(rdc, float64)
1346 rdc_err = array(rdc_err, float64)
1347 rdc_weight = array(rdc_weight, float64)
1348 absolute = array(absolute, int32)
1349 T_flags = array(T_flags, int32)
1350 if not opt_uses_j_couplings():
1351 j_couplings = None
1352 pseudo_flags = array(pseudo_flags, int32)
1353
1354
1355 return rdc, rdc_err, rdc_weight, unit_vect, rdc_const, absolute, T_flags, j_couplings, pseudo_flags
1356
1357
1358 -def set_errors(align_id=None, spin_id1=None, spin_id2=None, sd=None):
1359 """Set the RDC errors if not already present.
1360
1361 @keyword align_id: The optional alignment tensor ID string.
1362 @type align_id: str
1363 @keyword spin_id1: The optional spin ID string of the first spin.
1364 @type spin_id1: None or str
1365 @keyword spin_id2: The optional spin ID string of the second spin.
1366 @type spin_id2: None or str
1367 @keyword sd: The RDC standard deviation in Hz.
1368 @type sd: float or int.
1369 """
1370
1371
1372 check_pipe_setup(sequence=True, rdc_id=align_id, rdc=True)
1373
1374
1375 if align_id:
1376 align_ids = [align_id]
1377 else:
1378 align_ids = cdp.rdc_ids
1379
1380
1381 for interatom in interatomic_loop(selection1=spin_id1, selection2=spin_id2):
1382
1383 if not hasattr(interatom, 'rdc_err'):
1384 interatom.rdc_err = {}
1385
1386
1387 for id in align_ids:
1388 interatom.rdc_err[id] = sd
1389
1390
1392 """Make sure that the interatom system is properly set up for pseudo-atoms and RDCs.
1393
1394 Interatomic data containers between the non-pseudo-atom and the pseudo-atom members will be deselected.
1395 """
1396
1397
1398 for interatom in interatomic_loop():
1399
1400 spin1 = return_spin(interatom.spin_id1)
1401 spin2 = return_spin(interatom.spin_id2)
1402
1403
1404 flag1 = is_pseudoatom(spin1)
1405 flag2 = is_pseudoatom(spin2)
1406
1407
1408 if not (flag1 or flag2):
1409 continue
1410
1411
1412 if flag1 and flag2:
1413 warn(RelaxWarning("Support for both spins being in a dipole pair being pseudo-atoms is not implemented yet, deselecting the interatomic data container for the spin pair '%s' and '%s'." % (interatom.spin_id1, interatom.spin_id2)))
1414 interatom.select = False
1415
1416
1417 pseudospin = spin1
1418 base_spin_id = interatom.spin_id2
1419 pseudospin_id = interatom.spin_id1
1420 if flag2:
1421 pseudospin = spin2
1422 base_spin_id = interatom.spin_id1
1423 pseudospin_id = interatom.spin_id2
1424
1425
1426 for spin, spin_id in pseudoatom_loop(pseudospin, return_id=True):
1427
1428 pseudo_interatom = return_interatom(spin_id1=spin_id, spin_id2=base_spin_id)
1429
1430
1431 if pseudo_interatom.select:
1432 warn(RelaxWarning("Deselecting the interatomic data container for the spin pair '%s' and '%s' as it is part of the pseudo-atom system of the spin pair '%s' and '%s'." % (pseudo_interatom.spin_id1, pseudo_interatom.spin_id2, base_spin_id, pseudospin_id)))
1433 pseudo_interatom.select = False
1434
1435
1436 -def weight(align_id=None, spin_id=None, weight=1.0):
1437 """Set optimisation weights on the RDC data.
1438
1439 @keyword align_id: The alignment tensor ID string.
1440 @type align_id: str
1441 @keyword spin_id: The spin ID string.
1442 @type spin_id: None or str
1443 @keyword weight: The optimisation weight. The higher the value, the more importance the RDC will have.
1444 @type weight: float or int.
1445 """
1446
1447
1448 check_pipe_setup(sequence=True, rdc_id=align_id, rdc=True)
1449
1450
1451 for interatom in interatomic_loop():
1452
1453 if not hasattr(interatom, 'rdc_weight'):
1454 interatom.rdc_weight = {}
1455
1456
1457 interatom.rdc_weight[align_id] = weight
1458
1459
1460 -def write(align_id=None, file=None, dir=None, bc=False, force=False):
1461 """Display the RDC data corresponding to the alignment ID.
1462
1463 @keyword align_id: The alignment tensor ID string.
1464 @type align_id: str
1465 @keyword file: The file name or object to write to.
1466 @type file: str or file object
1467 @keyword dir: The name of the directory to place the file into (defaults to the current directory).
1468 @type dir: str
1469 @keyword bc: The back-calculation flag which if True will cause the back-calculated rather than measured data to be written.
1470 @type bc: bool
1471 @keyword force: A flag which if True will cause any pre-existing file to be overwritten.
1472 @type force: bool
1473 """
1474
1475
1476 check_pipe_setup(sequence=True, rdc_id=align_id, rdc=True)
1477
1478
1479 file = open_write_file(file, dir, force)
1480
1481
1482 data = []
1483 for interatom in interatomic_loop():
1484
1485 if not interatom.select:
1486 continue
1487
1488
1489 if not bc and (not hasattr(interatom, 'rdc') or align_id not in interatom.rdc):
1490 continue
1491 elif bc and (not hasattr(interatom, 'rdc_bc') or align_id not in interatom.rdc_bc):
1492 continue
1493
1494
1495 data.append([])
1496 data[-1].append(repr(interatom.spin_id1))
1497 data[-1].append(repr(interatom.spin_id2))
1498
1499
1500 data_type = None
1501 if hasattr(interatom, 'rdc_data_types') and align_id in interatom.rdc_data_types:
1502 data_type = interatom.rdc_data_types[align_id]
1503
1504
1505 if bc:
1506 data[-1].append(repr(convert(interatom.rdc_bc[align_id], data_type, align_id)))
1507 else:
1508 data[-1].append(repr(convert(interatom.rdc[align_id], data_type, align_id)))
1509
1510
1511 if hasattr(interatom, 'rdc_err') and align_id in interatom.rdc_err:
1512 data[-1].append(repr(convert(interatom.rdc_err[align_id], data_type, align_id)))
1513 else:
1514 data[-1].append(repr(None))
1515
1516
1517 write_data(out=file, headings=["Spin_ID1", "Spin_ID2", "RDCs", "RDC_error"], data=data)
1518