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 handling base data of the N-state model or structural ensemble analysis."""
24
25
26 from math import pi, sqrt
27 from numpy.linalg import norm
28 from warnings import warn
29
30
31 from lib.check_types import is_float
32 from lib.errors import RelaxError, RelaxNoValueError, RelaxSpinTypeError
33 from lib.physical_constants import dipolar_constant, g1H, return_gyromagnetic_ratio
34 from lib.warnings import RelaxWarning
35 from pipe_control import align_tensor
36 from pipe_control.interatomic import interatomic_loop, return_interatom
37 from pipe_control.pcs import opt_uses_pcs
38 from pipe_control.rdc import opt_uses_rdc
39 from pipe_control.mol_res_spin import is_pseudoatom, return_spin, spin_loop
40
41
43 """Determine all the base data types.
44
45 The base data types can include::
46 - 'rdc', residual dipolar couplings.
47 - 'pcs', pseudo-contact shifts.
48 - 'noesy', NOE restraints.
49 - 'tensor', alignment tensors.
50
51 @return: A list of all the base data types.
52 @rtype: list of str
53 """
54
55
56 list = []
57
58
59 for interatom in interatomic_loop():
60 if hasattr(interatom, 'rdc'):
61 list.append('rdc')
62 break
63
64
65 for spin in spin_loop():
66 if hasattr(spin, 'pcs'):
67 list.append('pcs')
68 break
69
70
71 if not ('rdc' in list or 'pcs' in list) and hasattr(cdp, 'align_tensors'):
72 list.append('tensor')
73
74
75 if hasattr(cdp, 'noe_restraints'):
76 list.append('noesy')
77
78
79 if not list:
80 raise RelaxError("Neither RDC, PCS, NOESY nor alignment tensor data is present.")
81
82
83 return list
84
85
87 """Calculate the average distances.
88
89 The formula used is::
90
91 _N_
92 / 1 \ \ 1/exp
93 <r> = | - > |p1i - p2i|^exp |
94 \ N /__ /
95 i
96
97 where i are the members of the ensemble, N is the total number of structural models, and p1
98 and p2 at the two atom positions.
99
100
101 @param atom1: The atom identification string of the first atom.
102 @type atom1: str
103 @param atom2: The atom identification string of the second atom.
104 @type atom2: str
105 @keyword exp: The exponent used for the averaging, e.g. 1 for linear averaging and -6 for
106 r^-6 NOE averaging.
107 @type exp: int
108 @return: The average distance between the two atoms.
109 @rtype: float
110 """
111
112
113 spin1 = return_spin(atom1)
114 spin2 = return_spin(atom2)
115
116
117 num_models = len(spin1.pos)
118 ave_dist = 0.0
119 for i in range(num_models):
120
121 dist = norm(spin1.pos[i] - spin2.pos[i])
122 ave_dist = ave_dist + dist**(exp)
123
124
125 ave_dist = ave_dist / num_models
126
127
128 ave_dist = ave_dist**(1.0/exp)
129
130
131 return ave_dist
132
133
175
176
178 """Generator method for looping over the full or reduced tensors.
179
180 @keyword red: A flag which if True causes the reduced tensors to be returned, and if False
181 the full tensors are returned.
182 @type red: bool
183 @return: The tensor index and the tensor.
184 @rtype: (int, AlignTensorData instance)
185 """
186
187
188 n = len(cdp.align_tensors.reduction)
189
190
191 data = cdp.align_tensors
192 list = data.reduction
193
194
195 if red:
196 index = 1
197 else:
198 index = 0
199
200
201 for i in range(n):
202 yield i, data[list[i][index]]
203