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