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