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