1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The main methods of the analysis specific API for the steady-state heteronuclear NOE calculation."""
24
25
26 from math import sqrt
27 from warnings import warn
28
29
30 from lib.errors import RelaxError, RelaxNoSequenceError
31 from lib.warnings import RelaxDeselectWarning
32 from pipe_control import pipes
33 from pipe_control.mol_res_spin import exists_mol_res_spin_data, spin_loop
34 from user_functions.data import Uf_tables; uf_tables = Uf_tables()
35 from user_functions.objects import Desc_container
36
37
39 """Class containing functions for relaxation data."""
40
41 - def _assign_function(self, spin=None, intensity=None, spectrum_type=None):
42 """Place the peak intensity data into the spin container.
43
44 The intensity data can be either that of the reference or saturated spectrum.
45
46 @keyword spin: The spin container.
47 @type spin: SpinContainer instance
48 @keyword intensity: The intensity value.
49 @type intensity: float
50 @keyword spectrum_type: The type of spectrum, one of 'ref' or 'sat'.
51 @type spectrum_type: str
52 """
53
54
55 if spectrum_type == 'ref':
56 spin.ref = intensity
57 elif spectrum_type == 'sat':
58 spin.sat = intensity
59 else:
60 raise RelaxError("The spectrum type '%s' is unknown." % spectrum_type)
61
62
63 - def _spectrum_type(self, spectrum_type=None, spectrum_id=None):
64 """Set the spectrum type corresponding to the spectrum_id.
65
66 @keyword spectrum_type: The type of NOE spectrum, one of 'ref' or 'sat'.
67 @type spectrum_type: str
68 @keyword spectrum_id: The spectrum id string.
69 @type spectrum_id: str
70 """
71
72
73 pipes.test()
74
75
76 if spectrum_id not in cdp.spectrum_ids:
77 raise RelaxError("The peak intensities corresponding to the spectrum id '%s' does not exist." % spectrum_id)
78
79
80 if not hasattr(cdp, 'spectrum_type'):
81 cdp.spectrum_type = {}
82
83
84 cdp.spectrum_type[spectrum_id] = spectrum_type
85
86
87 - def calculate(self, spin_id=None, verbosity=1, sim_index=None):
88 """Calculate the NOE and its error.
89
90 The error for each peak is calculated using the formula::
91 ___________________________________________
92 \/ {sd(sat)*I(unsat)}^2 + {sd(unsat)*I(sat)}^2
93 sd(NOE) = -----------------------------------------------
94 I(unsat)^2
95
96 @keyword spin_id: The spin identification string.
97 @type spin_id: None or str
98 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
99 @type verbosity: int
100 @keyword sim_index: The MC simulation index (unused).
101 @type sim_index: None
102 """
103
104
105 pipes.test()
106
107
108 if not hasattr(cdp, 'spectrum_type'):
109 raise RelaxError("The spectrum types have not been set.")
110
111
112 if not 'ref' in cdp.spectrum_type.values() or not 'sat' in cdp.spectrum_type.values():
113 raise RelaxError("The reference and saturated NOE spectra have not been loaded.")
114
115
116 for spin in spin_loop():
117
118 if not spin.select:
119 continue
120
121
122 sat = 0.0
123 sat_err2 = 0.0
124 sat_count = 0
125 ref = 0.0
126 ref_err2 = 0.0
127 ref_count = 0
128 for id in cdp.spectrum_ids:
129
130 if cdp.spectrum_type[id] == 'sat':
131 sat += spin.intensities[id]
132 sat_err2 += spin.intensity_err[id]**2
133 sat_count += 1
134
135
136 if cdp.spectrum_type[id] == 'ref':
137 ref += spin.intensities[id]
138 ref_err2 += spin.intensity_err[id]**2
139 ref_count += 1
140
141
142 sat = sat / sat_count
143 sat_err2 = sat_err2 / sat_count
144 ref = ref / ref_count
145 ref_err2 = ref_err2 / ref_count
146
147
148 spin.noe = sat / ref
149
150
151 spin.noe_err = sqrt(sat_err2 * ref**2 + ref_err2 * sat**2) / ref**2
152
153
154 - def overfit_deselect(self, data_check=True, verbose=True):
155 """Deselect spins which have insufficient data to support calculation.
156
157 @keyword data_check: A flag to signal if the presence of base data is to be checked for.
158 @type data_check: bool
159 @keyword verbose: A flag which if True will allow printouts.
160 @type verbose: bool
161 """
162
163
164 if verbose:
165 print("\nOver-fit spin deselection:")
166
167
168 if not exists_mol_res_spin_data():
169 raise RelaxNoSequenceError
170
171
172 deselect_flag = False
173 all_desel = True
174 for spin, spin_id in spin_loop(return_id=True):
175
176 if not spin.select:
177 continue
178
179
180 if not hasattr(spin, 'intensities'):
181 warn(RelaxDeselectWarning(spin_id, 'the absence of intensity data'))
182 spin.select = False
183 deselect_flag = True
184 continue
185
186
187 if not len(spin.intensities) >= 2:
188 warn(RelaxDeselectWarning(spin_id, 'insufficient data (less than two data points)'))
189 spin.select = False
190 deselect_flag = True
191 continue
192
193
194 if not hasattr(spin, 'intensity_err'):
195 warn(RelaxDeselectWarning(spin_id, 'the absence of errors'))
196 spin.select = False
197 deselect_flag = True
198 continue
199
200
201 if not len(spin.intensity_err) >= 2:
202 warn(RelaxDeselectWarning(spin_id, 'missing errors (less than two error points)'))
203 spin.select = False
204 deselect_flag = True
205 continue
206
207
208 all_desel = False
209
210
211 if verbose and not deselect_flag:
212 print("No spins have been deselected.")
213
214
215 if all_desel:
216 raise RelaxError("All spins have been deselected.")
217
218
219 return_data_name_doc = Desc_container("NOE calculation data type string matching patterns")
220 _table = uf_tables.add_table(label="table: NOE data type patterns", caption="NOE data type string matching patterns.")
221 _table.add_headings(["Data type", "Object name"])
222 _table.add_row(["Reference intensity", "'ref'"])
223 _table.add_row(["Saturated intensity", "'sat'"])
224 _table.add_row(["NOE", "'noe'"])
225 return_data_name_doc.add_table(_table.label)
226
227
228 - def return_units(self, param):
229 """Dummy function which returns None as the stats have no units.
230
231 @param param: The name of the parameter to return the units string for.
232 @type param: str
233 @return: Nothing.
234 @rtype: None
235 """
236
237 return None
238