OpenMS
Loading...
Searching...
No Matches
SignalToNoiseEstimatorMeanIterative.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Chris Bielow $
6// $Authors: $
7// --------------------------------------------------------------------------
8//
9
10#pragma once
11
16#include <vector>
17#include <algorithm> //for std::max_element
18
19namespace OpenMS
20{
44 template <typename Container = MSSpectrum>
46 public SignalToNoiseEstimator<Container>
47 {
48
49public:
50
53
55 using SignalToNoiseEstimator<Container>::defaults_;
56 using SignalToNoiseEstimator<Container>::param_;
57
60
62
63
66 {
67 //set the name for DefaultParamHandler error messages
68 this->setName("SignalToNoiseEstimatorMeanIterative");
69
70 defaults_.setValue("max_intensity", -1, "maximal intensity considered for histogram construction. By default, it will be calculated automatically (see auto_mode)." \
71 " Only provide this parameter if you know what you are doing (and change 'auto_mode' to '-1')!" \
72 " All intensities EQUAL/ABOVE 'max_intensity' will not be added to the histogram." \
73 " If you choose 'max_intensity' too small, the noise estimate might be too small as well." \
74 " If chosen too big, the bins become quite large (which you could counter by increasing 'bin_count', which increases runtime).", {"advanced"});
75 defaults_.setMinInt("max_intensity", -1);
76
77 defaults_.setValue("auto_max_stdev_factor", 3.0, "parameter for 'max_intensity' estimation (if 'auto_mode' == 0): mean + 'auto_max_stdev_factor' * stdev", {"advanced"});
78 defaults_.setMinFloat("auto_max_stdev_factor", 0.0);
79 defaults_.setMaxFloat("auto_max_stdev_factor", 999.0);
80
81
82 defaults_.setValue("auto_max_percentile", 95, "parameter for 'max_intensity' estimation (if 'auto_mode' == 1): auto_max_percentile th percentile", {"advanced"});
83 defaults_.setMinInt("auto_max_percentile", 0);
84 defaults_.setMaxInt("auto_max_percentile", 100);
85
86 defaults_.setValue("auto_mode", 0, "method to use to determine maximal intensity: -1 --> use 'max_intensity'; 0 --> 'auto_max_stdev_factor' method (default); 1 --> 'auto_max_percentile' method", {"advanced"});
87 defaults_.setMinInt("auto_mode", -1);
88 defaults_.setMaxInt("auto_mode", 1);
89
90 defaults_.setValue("win_len", 200.0, "window length in Thomson");
91 defaults_.setMinFloat("win_len", 1.0);
92
93 defaults_.setValue("bin_count", 30, "number of bins for intensity values");
94 defaults_.setMinInt("bin_count", 3);
95
96 defaults_.setValue("stdev_mp", 3.0, "multiplier for stdev", {"advanced"});
97 defaults_.setMinFloat("stdev_mp", 0.01);
98 defaults_.setMaxFloat("stdev_mp", 999.0);
99
100 defaults_.setValue("min_required_elements", 10, "minimum number of elements required in a window (otherwise it is considered sparse)");
101 defaults_.setMinInt("min_required_elements", 1);
102
103 defaults_.setValue("noise_for_empty_window", std::pow(10.0, 20), "noise value used for sparse windows", {"advanced"});
104
106 }
107
114
120 {
121 if (&source == this) return *this;
122
125 return *this;
126 }
127
129
130
134
135
136protected:
137
138
143 void computeSTN_(const Container& c) override
144 {
145 //first element in the scan
146 PeakIterator scan_first_ = c.begin();
147 //last element in the scan
148 PeakIterator scan_last_ = c.end();
149
150 // reset counter for sparse windows
151 double sparse_window_percent = 0;
152
153 // reset the results
154 stn_estimates_.clear();
155 stn_estimates_.resize(c.size());
156
157 // maximal range of histogram needs to be calculated first
159 {
160 // use MEAN+auto_max_intensity_*STDEV as threshold
161 GaussianEstimate gauss_global = SignalToNoiseEstimator<Container>::estimate_(scan_first_, scan_last_);
162 max_intensity_ = gauss_global.mean + std::sqrt(gauss_global.variance) * auto_max_stdev_Factor_;
163 }
164 else if (auto_mode_ == AUTOMAXBYPERCENT)
165 {
166 // get value at "auto_max_percentile_"th percentile
167 // we use a histogram approach here as well.
168 if ((auto_max_percentile_ < 0) || (auto_max_percentile_ > 100))
169 {
171 throw Exception::InvalidValue(__FILE__,
172 __LINE__,
173 OPENMS_PRETTY_FUNCTION,
174 "auto_mode is on AUTOMAXBYPERCENT! auto_max_percentile is not in [0,100]. Use setAutoMaxPercentile(<value>) to change it!",
175 s);
176 }
177
178 if (c.empty())
179 {
180 return;
181 }
182
183 std::vector<int> histogram_auto(100, 0);
184
185 // find maximum of current scan
186 auto maxIt = std::max_element(c.begin(), c.end() ,[](const PeakType& a, const PeakType& b){ return a.getIntensity() < b.getIntensity();});
187 typename PeakType::IntensityType maxInt = maxIt->getIntensity();
188
189 double bin_size = maxInt > 0 ? static_cast<double>(maxInt) / 100.0 : 1.0;
190
191 // fill histogram
192 for (const auto& peak : c)
193 {
194 const int bin = (int) std::max(0.0, std::min(peak.getIntensity() / bin_size, 99.0));
195 ++histogram_auto[bin];
196 }
197
198 // add up element counts in histogram until ?th percentile is reached
199 int elements_below_percentile = std::max(1, (int) (auto_max_percentile_ * c.size() / 100));
200 int elements_seen = 0;
201 int i = -1;
202
203 while (i < 99 && elements_seen < elements_below_percentile)
204 {
205 ++i;
206 elements_seen += histogram_auto[i];
207 }
208
209 max_intensity_ = (((double)i) + 0.5) * bin_size;
210 }
211 else //if (auto_mode_ == MANUAL)
212 {
213 if (max_intensity_ <= 0)
214 {
215 std::string s = StringUtils::toStr(max_intensity_);
216 throw Exception::InvalidValue(__FILE__,
217 __LINE__,
218 OPENMS_PRETTY_FUNCTION,
219 "auto_mode is on MANUAL! max_intensity is <=0. Needs to be positive! Use setMaxIntensity(<value>) or enable auto_mode!",
220 s);
221 }
222 }
223
224 if (max_intensity_ < 0)
225 {
226 OPENMS_LOG_WARN << "SignalToNoiseEstimatorMeanIterative: the max_intensity_ value should be positive! " << max_intensity_ << std::endl;
227 return;
228 }
229
230 PeakIterator window_pos_center = scan_first_;
231 PeakIterator window_pos_borderleft = scan_first_;
232 PeakIterator window_pos_borderright = scan_first_;
233
234 double window_half_size = win_len_ / 2;
235 double bin_size = std::max(1.0, max_intensity_ / bin_count_); // at least size of 1 for intensity bins
236
237 std::vector<int> histogram(bin_count_, 0);
238 std::vector<double> bin_value(bin_count_, 0);
239 // calculate average intensity that is represented by a bin
240 for (int bin = 0; bin < bin_count_; bin++)
241 {
242 histogram[bin] = 0;
243 bin_value[bin] = (bin + 0.5) * bin_size;
244 }
245 // index of last valid bin during iteration
246 int hist_rightmost_bin;
247 // bin in which a datapoint would fall
248 int to_bin;
249 // mean & stdev of the histogram
250 double hist_mean;
251 double hist_stdev;
252
253 // tracks elements in current window, which may vary because of unevenly spaced data
254 int elements_in_window = 0;
255 int window_count = 0;
256
257 double noise; // noise value of a datapoint
258
260 SignalToNoiseEstimator<Container>::startProgress(0, c.size(), "noise estimation of data");
261
262 // MAIN LOOP
263 while (window_pos_center != scan_last_)
264 {
265 // erase all elements from histogram that will leave the window on the LEFT side
266 while ((*window_pos_borderleft).getMZ() < (*window_pos_center).getMZ() - window_half_size)
267 {
268 //std::cout << "S: " << (*window_pos_borderleft).getMZ() << " " << ( (*window_pos_center).getMZ() - window_half_size ) << "\n";
269 to_bin = (int) ((std::max((*window_pos_borderleft).getIntensity(), 0.0f)) / bin_size);
270 if (to_bin < bin_count_)
271 {
272 --histogram[to_bin];
273 --elements_in_window;
274 }
275 ++window_pos_borderleft;
276 }
277
278 //std::printf("S1: %E %E\n", (*window_pos_borderright).getMZ(), (*window_pos_center).getMZ() + window_half_size);
279
280
281 // add all elements to histogram that will enter the window on the RIGHT side
282 while ((window_pos_borderright != scan_last_)
283 && ((*window_pos_borderright).getMZ() < (*window_pos_center).getMZ() + window_half_size))
284 {
285 //std::printf("Sb: %E %E %E\n", (*window_pos_borderright).getMZ(), (*window_pos_center).getMZ() + window_half_size, (*window_pos_borderright).getMZ() - ((*window_pos_center).getMZ() + window_half_size));
286
287 to_bin = (int) ((std::max((*window_pos_borderright).getIntensity(), 0.0f)) / bin_size);
288 if (to_bin < bin_count_)
289 {
290 ++histogram[to_bin];
291 ++elements_in_window;
292 }
293 ++window_pos_borderright;
294 }
295
296 if (elements_in_window < min_required_elements_)
297 {
299 ++sparse_window_percent;
300 }
301 else
302 {
303
304 hist_rightmost_bin = bin_count_;
305
306 // do iteration on histogram and find threshold
307 for (int i = 0; i < 3; ++i)
308 {
309 // mean
310 hist_mean = 0;
311 for (int bin = 0; bin < hist_rightmost_bin; ++bin)
312 {
313 //std::cout << "V: " << bin << " " << hist_mean << " " << histogram[bin] << " " << elements_in_window << " " << bin_value[bin] << "\n";
314 // immediate division is numerically more stable
315 hist_mean += histogram[bin] / (double) elements_in_window * bin_value[bin];
316 }
317 //hist_mean = hist_mean / elements_in_window;
318
319 // stdev
320 hist_stdev = 0;
321 for (int bin = 0; bin < hist_rightmost_bin; ++bin)
322 {
323 double tmp(bin_value[bin] - hist_mean);
324 hist_stdev += histogram[bin] / (double) elements_in_window * tmp * tmp;
325 }
326 hist_stdev = std::sqrt(hist_stdev);
327
328 //determine new threshold (i.e. the rightmost bin we consider)
329 int estimate = (int) ((hist_mean + hist_stdev * stdev_ - 1) / bin_size + 1);
330 //std::cout << "E: " << hist_mean << " " << hist_stdev << " " << stdev_ << " " << bin_size<< " " << estimate << "\n";
331 hist_rightmost_bin = std::min(estimate, bin_count_);
332 }
333
334 // just avoid division by 0
335 noise = std::max(1.0, hist_mean);
336 }
337
338 // store result
339 stn_estimates_[window_count] = (*window_pos_center).getIntensity() / noise;
340
341
342
343 // advance the window center by one datapoint
344 ++window_pos_center;
345 ++window_count;
346 // update progress
348
349 } // end while
350
352
353 sparse_window_percent = sparse_window_percent * 100 / window_count;
354 // warn if percentage of sparse windows is above 20%
355 if (sparse_window_percent > 20)
356 {
357 OPENMS_LOG_WARN << "WARNING in SignalToNoiseEstimatorMeanIterative: "
358 << sparse_window_percent
359 << "% of all windows were sparse. You should consider increasing 'win_len' or increasing 'min_required_elements'"
360 << " You should also check the MaximalIntensity value (or the parameters for its heuristic estimation)"
361 << " If it is too low, then too many high intensity peaks will be discarded, which leads to a sparse window!"
362 << std::endl;
363 }
364
365 return;
366
367 } // end of shiftWindow_
368
370 void updateMembers_() override
371 {
372 max_intensity_ = (double)param_.getValue("max_intensity");
373 auto_max_stdev_Factor_ = (double)param_.getValue("auto_max_stdev_factor");
374 auto_max_percentile_ = param_.getValue("auto_max_percentile");
375 auto_mode_ = param_.getValue("auto_mode");
376 win_len_ = (double)param_.getValue("win_len");
377 bin_count_ = param_.getValue("bin_count");
378 stdev_ = (double)param_.getValue("stdev_mp");
379 min_required_elements_ = param_.getValue("min_required_elements");
380 noise_for_empty_window_ = (double)param_.getValue("noise_for_empty_window");
381 stn_estimates_.clear();
382 }
383
393 double win_len_;
397 double stdev_;
403
404
405
406
407 };
408
409} // namespace OpenMS
410
#define OPENMS_LOG_WARN
Macro for warnings.
Definition LogStream.h:691
void defaultsToParam_()
Updates the parameters after the defaults have been set in the constructor.
Param param_
Container for current parameters.
Definition DefaultParamHandler.h:139
Param defaults_
Container for default parameters. This member should be filled in the constructor of derived classes!
Definition DefaultParamHandler.h:146
void setName(const std::string &name)
Mutable access to the name.
Invalid value exception.
Definition Exception.h:306
const ParamValue & getValue(const std::string &key) const
Returns a value of a parameter.
void setMaxFloat(const std::string &key, double max)
Sets the maximum value for the floating point or floating point list parameter key.
void setMaxInt(const std::string &key, int max)
Sets the maximum value for the integer or integer list parameter key.
void setMinInt(const std::string &key, int min)
Sets the minimum value for the integer or integer list parameter key.
void setValue(const std::string &key, const ParamValue &value, const std::string &description="", const std::vector< std::string > &tags=std::vector< std::string >())
Sets a value.
void setMinFloat(const std::string &key, double min)
Sets the minimum value for the floating point or floating point list parameter key.
float IntensityType
Intensity type.
Definition Peak2D.h:37
void setProgress(SignedSize value) const
Sets the current progress.
void endProgress(UInt64 bytes_processed=0) const
void startProgress(SignedSize begin, SignedSize end, const std::string &label) const
Initializes the progress display.
Estimates the signal/noise (S/N) ratio of each data point in a scan based on an iterative scheme whic...
Definition SignalToNoiseEstimatorMeanIterative.h:47
SignalToNoiseEstimator< Container >::PeakIterator PeakIterator
Definition SignalToNoiseEstimatorMeanIterative.h:58
SignalToNoiseEstimatorMeanIterative()
default constructor
Definition SignalToNoiseEstimatorMeanIterative.h:65
double win_len_
range of data points which belong to a window in Thomson
Definition SignalToNoiseEstimatorMeanIterative.h:393
double stdev_
multiplier for the stdev of intensities
Definition SignalToNoiseEstimatorMeanIterative.h:397
double noise_for_empty_window_
Definition SignalToNoiseEstimatorMeanIterative.h:402
~SignalToNoiseEstimatorMeanIterative() override
Destructor.
Definition SignalToNoiseEstimatorMeanIterative.h:132
SignalToNoiseEstimatorMeanIterative(const SignalToNoiseEstimatorMeanIterative &source)
Copy Constructor.
Definition SignalToNoiseEstimatorMeanIterative.h:109
double max_intensity_
maximal intensity considered during binning (values above get discarded)
Definition SignalToNoiseEstimatorMeanIterative.h:385
double auto_max_percentile_
parameter for initial automatic estimation of "max_intensity_" percentile or a stdev
Definition SignalToNoiseEstimatorMeanIterative.h:389
void computeSTN_(const Container &c) override
Definition SignalToNoiseEstimatorMeanIterative.h:143
void updateMembers_() override
overridden function from DefaultParamHandler to keep members up to date, when a parameter is changed
Definition SignalToNoiseEstimatorMeanIterative.h:370
int min_required_elements_
minimal number of elements a window needs to cover to be used
Definition SignalToNoiseEstimatorMeanIterative.h:399
SignalToNoiseEstimator< Container >::PeakType PeakType
Definition SignalToNoiseEstimatorMeanIterative.h:59
SignalToNoiseEstimator< Container >::GaussianEstimate GaussianEstimate
Definition SignalToNoiseEstimatorMeanIterative.h:61
int auto_mode_
determines which method shall be used for estimating "max_intensity_". valid are MANUAL=-1,...
Definition SignalToNoiseEstimatorMeanIterative.h:391
IntensityThresholdCalculation
method to use for estimating the maximal intensity that is used for histogram calculation
Definition SignalToNoiseEstimatorMeanIterative.h:52
@ MANUAL
Definition SignalToNoiseEstimatorMeanIterative.h:52
@ AUTOMAXBYSTDEV
Definition SignalToNoiseEstimatorMeanIterative.h:52
@ AUTOMAXBYPERCENT
Definition SignalToNoiseEstimatorMeanIterative.h:52
SignalToNoiseEstimatorMeanIterative & operator=(const SignalToNoiseEstimatorMeanIterative &source)
Definition SignalToNoiseEstimatorMeanIterative.h:119
int bin_count_
number of bins in the histogram
Definition SignalToNoiseEstimatorMeanIterative.h:395
double auto_max_stdev_Factor_
parameter for initial automatic estimation of "max_intensity_": a stdev multiplier
Definition SignalToNoiseEstimatorMeanIterative.h:387
This class represents the abstract base class of a signal to noise estimator.
Definition SignalToNoiseEstimator.h:33
double variance
variance of estimated Gaussian
Definition SignalToNoiseEstimator.h:108
PeakIterator::value_type PeakType
Definition SignalToNoiseEstimator.h:40
SignalToNoiseEstimator & operator=(const SignalToNoiseEstimator &source)
Assignment operator.
Definition SignalToNoiseEstimator.h:60
static GaussianEstimate estimate_(const PeakIterator &scan_first_, const PeakIterator &scan_last_)
calculate mean & stdev of intensities of a spectrum
Definition SignalToNoiseEstimator.h:113
double mean
mean of estimated Gaussian
Definition SignalToNoiseEstimator.h:107
std::vector< double > stn_estimates_
stores the noise estimate for each peak
Definition SignalToNoiseEstimator.h:146
Container::const_iterator PeakIterator
Definition SignalToNoiseEstimator.h:39
protected struct to store parameters my, sigma for a Gaussian distribution
Definition SignalToNoiseEstimator.h:106
std::string toStr(int i)
Definition StringUtils.h:101
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19