OpenMS  2.5.0
StatisticFunctions.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2020.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Timo Sachsenberg $
32 // $Authors: Clemens Groepl, Johannes Junker, Mathias Walzer, Chris Bielow $
33 // --------------------------------------------------------------------------
34 #pragma once
35 
36 #include <vector>
38 #include <OpenMS/CONCEPT/Types.h>
39 
40 // array_wrapper needs to be included before it is used
41 // only in boost1.64+. See issue #2790
42 #if OPENMS_BOOST_VERSION_MINOR >= 64
43 #include <boost/serialization/array_wrapper.hpp>
44 #endif
45 #include <boost/accumulators/accumulators.hpp>
46 #include <boost/accumulators/statistics/covariance.hpp>
47 #include <boost/accumulators/statistics/mean.hpp>
48 #include <boost/accumulators/statistics/stats.hpp>
49 #include <boost/accumulators/statistics/variance.hpp>
50 #include <boost/accumulators/statistics/variates/covariate.hpp>
51 #include <boost/function/function_base.hpp>
52 #include <boost/lambda/casts.hpp>
53 #include <boost/lambda/lambda.hpp>
54 
55 #include <iterator>
56 #include <algorithm>
57 
58 namespace OpenMS
59 {
60 
61  namespace Math
62  {
63 
71  template <typename IteratorType>
72  static void checkIteratorsNotNULL(IteratorType begin, IteratorType end)
73  {
74  if (begin == end)
75  {
76  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
77  }
78  }
79 
87  template <typename IteratorType>
88  static void checkIteratorsEqual(IteratorType begin, IteratorType end)
89  {
90  if (begin != end)
91  {
92  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
93  }
94  }
95 
103  template <typename IteratorType1, typename IteratorType2>
105  IteratorType1 begin_b, IteratorType1 end_b,
106  IteratorType2 begin_a, IteratorType2 end_a)
107  {
108  if (begin_b != end_b && begin_a == end_a)
109  {
110  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
111  }
112  }
113 
119  template <typename IteratorType>
120  static double sum(IteratorType begin, IteratorType end)
121  {
122  return std::accumulate(begin, end, 0.0);
123  }
124 
132  template <typename IteratorType>
133  static double mean(IteratorType begin, IteratorType end)
134  {
135  checkIteratorsNotNULL(begin, end);
136  return sum(begin, end) / std::distance(begin, end);
137  }
138 
150  template <typename IteratorType>
151  static double median(IteratorType begin, IteratorType end,
152  bool sorted = false)
153  {
154  checkIteratorsNotNULL(begin, end);
155  if (!sorted)
156  {
157  std::sort(begin, end);
158  }
159 
160  Size size = std::distance(begin, end);
161  if (size % 2 == 0) // even size => average two middle values
162  {
163  IteratorType it1 = begin;
164  std::advance(it1, size / 2 - 1);
165  IteratorType it2 = it1;
166  std::advance(it2, 1);
167  return (*it1 + *it2) / 2.0;
168  }
169  else
170  {
171  IteratorType it = begin;
172  std::advance(it, (size - 1) / 2);
173  return *it;
174  }
175  }
176 
177 
197  template <typename IteratorType>
198  double MAD(IteratorType begin, IteratorType end, double median_of_numbers)
199  {
200  std::vector<double> diffs;
201  diffs.reserve(std::distance(begin, end));
202  for (IteratorType it = begin; it != end; ++it)
203  {
204  diffs.push_back(fabs(*it - median_of_numbers));
205  }
206  return median(diffs.begin(), diffs.end(), false);
207  }
208 
222  template <typename IteratorType>
223  static double quantile1st(IteratorType begin, IteratorType end,
224  bool sorted = false)
225  {
226  checkIteratorsNotNULL(begin, end);
227 
228  if (!sorted)
229  {
230  std::sort(begin, end);
231  }
232 
233  Size size = std::distance(begin, end);
234  if (size % 2 == 0)
235  {
236  return median(begin, begin + (size/2)-1, true); //-1 to exclude median values
237  }
238  return median(begin, begin + (size/2), true);
239  }
240 
254  template <typename IteratorType>
255  static double quantile3rd(
256  IteratorType begin, IteratorType end, bool sorted = false)
257  {
258  checkIteratorsNotNULL(begin, end);
259  if (!sorted)
260  {
261  std::sort(begin, end);
262  }
263 
264  Size size = std::distance(begin, end);
265  return median(begin + (size/2)+1, end, true); //+1 to exclude median values
266  }
267 
277  template <typename IteratorType>
278  static double variance(IteratorType begin, IteratorType end,
279  double mean = std::numeric_limits<double>::max())
280  {
281  checkIteratorsNotNULL(begin, end);
282  double sum = 0.0;
283  if (mean == std::numeric_limits<double>::max())
284  {
285  mean = Math::mean(begin, end);
286  }
287  for (IteratorType iter=begin; iter!=end; ++iter)
288  {
289  double diff = *iter - mean;
290  sum += diff * diff;
291  }
292  return sum / (std::distance(begin, end)-1);
293  }
294 
304  template <typename IteratorType>
305  static double sd(IteratorType begin, IteratorType end,
306  double mean = std::numeric_limits<double>::max())
307  {
308  checkIteratorsNotNULL(begin, end);
309  return std::sqrt( variance(begin, end, mean) );
310  }
311 
319  template <typename IteratorType>
320  static double absdev(IteratorType begin, IteratorType end,
321  double mean = std::numeric_limits<double>::max())
322  {
323  checkIteratorsNotNULL(begin, end);
324  double sum = 0.0;
325  if (mean == std::numeric_limits<double>::max())
326  {
327  mean = Math::mean(begin, end);
328  }
329  for (IteratorType iter=begin; iter!=end; ++iter)
330  {
331  sum += *iter - mean;
332  }
333  return sum / std::distance(begin, end);
334  }
335 
345  template <typename IteratorType1, typename IteratorType2>
346  static double covariance(IteratorType1 begin_a, IteratorType1 end_a,
347  IteratorType2 begin_b, IteratorType2 end_b)
348  {
349  //no data or different lengths
350  checkIteratorsNotNULL(begin_a, end_a);
351 
352  double sum = 0.0;
353  double mean_a = Math::mean(begin_a, end_a);
354  double mean_b = Math::mean(begin_b, end_b);
355  IteratorType1 iter_a = begin_a;
356  IteratorType2 iter_b = begin_b;
357  for (; iter_a != end_a; ++iter_a, ++iter_b)
358  {
359  /* assure both ranges have the same number of elements */
360  checkIteratorsAreValid(begin_b, end_b, begin_a, end_a);
361  sum += (*iter_a - mean_a) * (*iter_b - mean_b);
362  }
363  /* assure both ranges have the same number of elements */
364  checkIteratorsEqual(iter_b, end_b);
365  Size n = std::distance(begin_a, end_a);
366  return sum / (n-1);
367  }
368 
378  template <typename IteratorType1, typename IteratorType2>
379  static double meanSquareError(IteratorType1 begin_a, IteratorType1 end_a,
380  IteratorType2 begin_b, IteratorType2 end_b)
381  {
382  //no data or different lengths
383  checkIteratorsNotNULL(begin_a, end_a);
384 
385  SignedSize dist = std::distance(begin_a, end_a);
386  double error = 0;
387  IteratorType1 iter_a = begin_a;
388  IteratorType2 iter_b = begin_b;
389  for (; iter_a != end_a; ++iter_a, ++iter_b)
390  {
391  /* assure both ranges have the same number of elements */
392  checkIteratorsAreValid(iter_b, end_b, iter_a, end_a);
393 
394  double tmp(*iter_a - *iter_b);
395  error += tmp * tmp;
396  }
397  /* assure both ranges have the same number of elements */
398  checkIteratorsEqual(iter_b, end_b);
399 
400  return error / dist;
401  }
402 
412  template <typename IteratorType1, typename IteratorType2>
413  static double classificationRate(IteratorType1 begin_a, IteratorType1 end_a,
414  IteratorType2 begin_b, IteratorType2 end_b)
415  {
416  //no data or different lengths
417  checkIteratorsNotNULL(begin_a, end_a);
418 
419  SignedSize dist = std::distance(begin_a, end_a);
420  SignedSize correct = dist;
421  IteratorType1 iter_a = begin_a;
422  IteratorType2 iter_b = begin_b;
423  for (; iter_a != end_a; ++iter_a, ++iter_b)
424  {
425  /* assure both ranges have the same number of elements */
426  checkIteratorsAreValid(iter_b, end_b, iter_a, end_a);
427  if ((*iter_a < 0 && *iter_b >= 0) || (*iter_a >= 0 && *iter_b < 0))
428  {
429  --correct;
430  }
431 
432  }
433  /* assure both ranges have the same number of elements */
434  checkIteratorsEqual(iter_b, end_b);
435 
436  return double(correct) / dist;
437  }
438 
451  template <typename IteratorType1, typename IteratorType2>
453  IteratorType1 begin_a, IteratorType1 end_a,
454  IteratorType2 begin_b, IteratorType2 end_b)
455  {
456  //no data or different lengths
457  checkIteratorsNotNULL(begin_a, end_b);
458 
459  double tp = 0;
460  double fp = 0;
461  double tn = 0;
462  double fn = 0;
463  IteratorType1 iter_a = begin_a;
464  IteratorType2 iter_b = begin_b;
465  for (; iter_a != end_a; ++iter_a, ++iter_b)
466  {
467  /* assure both ranges have the same number of elements */
468  checkIteratorsAreValid(iter_b, end_b, iter_a, end_a);
469 
470  if (*iter_a < 0 && *iter_b >= 0)
471  {
472  ++fn;
473  }
474  else if (*iter_a < 0 && *iter_b < 0)
475  {
476  ++tn;
477  }
478  else if (*iter_a >= 0 && *iter_b >= 0)
479  {
480  ++tp;
481  }
482  else if (*iter_a >= 0 && *iter_b < 0)
483  {
484  ++fp;
485  }
486  }
487  /* assure both ranges have the same number of elements */
488  checkIteratorsEqual(iter_b, end_b);
489 
490  return (tp * tn - fp * fn) / sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn));
491  }
492 
504  template <typename IteratorType1, typename IteratorType2>
506  IteratorType1 begin_a, IteratorType1 end_a,
507  IteratorType2 begin_b, IteratorType2 end_b)
508  {
509  //no data or different lengths
510  checkIteratorsNotNULL(begin_a, end_a);
511 
512  //calculate average
513  SignedSize dist = std::distance(begin_a, end_a);
514  double avg_a = std::accumulate(begin_a, end_a, 0.0) / dist;
515  double avg_b = std::accumulate(begin_b, end_b, 0.0) / dist;
516 
517  double numerator = 0;
518  double denominator_a = 0;
519  double denominator_b = 0;
520  IteratorType1 iter_a = begin_a;
521  IteratorType2 iter_b = begin_b;
522  for (; iter_a != end_a; ++iter_a, ++iter_b)
523  {
524  /* assure both ranges have the same number of elements */
525  checkIteratorsAreValid(iter_b, end_b, iter_a, end_a);
526  double temp_a = *iter_a - avg_a;
527  double temp_b = *iter_b - avg_b;
528  numerator += (temp_a * temp_b);
529  denominator_a += (temp_a * temp_a);
530  denominator_b += (temp_b * temp_b);
531  }
532  /* assure both ranges have the same number of elements */
533  checkIteratorsEqual(iter_b, end_b);
534  return numerator / sqrt(denominator_a * denominator_b);
535  }
536 
538  template <typename Value>
539  static void computeRank(std::vector<Value> & w)
540  {
541  Size i = 0; // main index
542  Size z = 0; // "secondary" index
543  Value rank = 0;
544  Size n = (w.size() - 1);
545  //store original indices for later
546  std::vector<std::pair<Size, Value> > w_idx;
547  for (Size j = 0; j < w.size(); ++j)
548  {
549  w_idx.push_back(std::make_pair(j, w[j]));
550  }
551  //sort
552  std::sort(w_idx.begin(), w_idx.end(),
553  boost::lambda::ret<bool>((&boost::lambda::_1->*& std::pair<Size, Value>::second) <
554  (&boost::lambda::_2->*& std::pair<Size, Value>::second)));
555  //replace pairs <orig_index, value> in w_idx by pairs <orig_index, rank>
556  while (i < n)
557  {
558  // test for equality with tolerance:
559  if (fabs(w_idx[i + 1].second - w_idx[i].second) > 0.0000001 * fabs(w_idx[i + 1].second)) // no tie
560  {
561  w_idx[i].second = Value(i + 1);
562  ++i;
563  }
564  else // tie, replace by mean rank
565  {
566  // count number of ties
567  for (z = i + 1; (z <= n) && fabs(w_idx[z].second - w_idx[i].second) <= 0.0000001 * fabs(w_idx[z].second); ++z)
568  {
569  }
570  // compute mean rank of tie
571  rank = 0.5 * (i + z + 1);
572  // replace intensities by rank
573  for (Size v = i; v <= z - 1; ++v)
574  {
575  w_idx[v].second = rank;
576  }
577  i = z;
578  }
579  }
580  if (i == n)
581  w_idx[n].second = Value(n + 1);
582  //restore original order and replace elements of w with their ranks
583  for (Size j = 0; j < w.size(); ++j)
584  {
585  w[w_idx[j].first] = w_idx[j].second;
586  }
587  }
588 
600  template <typename IteratorType1, typename IteratorType2>
602  IteratorType1 begin_a, IteratorType1 end_a,
603  IteratorType2 begin_b, IteratorType2 end_b)
604  {
605  //no data or different lengths
606  checkIteratorsNotNULL(begin_a, end_a);
607 
608  // store and sort intensities of model and data
609  SignedSize dist = std::distance(begin_a, end_a);
610  std::vector<double> ranks_data;
611  ranks_data.reserve(dist);
612  std::vector<double> ranks_model;
613  ranks_model.reserve(dist);
614  IteratorType1 iter_a = begin_a;
615  IteratorType2 iter_b = begin_b;
616  for (; iter_a != end_a; ++iter_a, ++iter_b)
617  {
618  /* assure both ranges have the same number of elements */
619  checkIteratorsAreValid(iter_b, end_b, iter_a, end_a);
620 
621  ranks_model.push_back(*iter_a);
622  ranks_data.push_back(*iter_b);
623  }
624  /* assure both ranges have the same number of elements */
625  checkIteratorsEqual(iter_b, end_b);
626 
627  // replace entries by their ranks
628  computeRank(ranks_data);
629  computeRank(ranks_model);
630 
631  double mu = double(ranks_data.size() + 1) / 2.; // mean of ranks
632  // Was the following, but I think the above is more correct ... (Clemens)
633  // double mu = (ranks_data.size() + 1) / 2;
634 
635  double sum_model_data = 0;
636  double sqsum_data = 0;
637  double sqsum_model = 0;
638 
639  for (Int i = 0; i < dist; ++i)
640  {
641  sum_model_data += (ranks_data[i] - mu) * (ranks_model[i] - mu);
642  sqsum_data += (ranks_data[i] - mu) * (ranks_data[i] - mu);
643  sqsum_model += (ranks_model[i] - mu) * (ranks_model[i] - mu);
644  }
645 
646  // check for division by zero
647  if (!sqsum_data || !sqsum_model)
648  {
649  return 0;
650  }
651 
652  return sum_model_data / (sqrt(sqsum_data) * sqrt(sqsum_model));
653  }
654 
656  template<typename T>
658  {
660  :mean(0), variance(0), min(0), lowerq(0), median(0), upperq(0), max(0)
661  {
662  }
663 
664  // Ctor with data
666  {
667  count = data.size();
668  // Sanity check: avoid core dump if no data points present.
669  if (data.empty())
670  {
671  mean = variance = min = lowerq = median = upperq = max = 0.0;
672  }
673  else
674  {
675  sort(data.begin(), data.end());
676  mean = Math::mean(data.begin(), data.end());
677  variance = Math::variance(data.begin(), data.end(), mean);
678  min = data.front();
679  lowerq = Math::quantile1st(data.begin(), data.end(), true);
680  median = Math::median(data.begin(), data.end(), true);
681  upperq = Math::quantile3rd(data.begin(), data.end(), true);
682  max = data.back();
683  }
684  }
685 
687  typename T::value_type min, max;
688  size_t count;
689  };
690 
691  } // namespace Math
692 } // namespace OpenMS
693 
OpenMS::Math::SummaryStatistics::mean
double mean
Definition: StatisticFunctions.h:686
OpenMS::Math::sum
static double sum(IteratorType begin, IteratorType end)
Calculates the sum of a range of values.
Definition: StatisticFunctions.h:120
OpenMS::Math::SummaryStatistics::median
double median
Definition: StatisticFunctions.h:686
double
OpenMS::Math::median
static double median(IteratorType begin, IteratorType end, bool sorted=false)
Calculates the median of a range of values.
Definition: StatisticFunctions.h:151
Types.h
OpenMS::Math::rankCorrelationCoefficient
static double rankCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
calculates the rank correlation coefficient for the values in [begin_a, end_a) and [begin_b,...
Definition: StatisticFunctions.h:601
OpenMS::Math::checkIteratorsEqual
static void checkIteratorsEqual(IteratorType begin, IteratorType end)
Helper function checking if two iterators are equal.
Definition: StatisticFunctions.h:88
OpenMS::Math::checkIteratorsAreValid
static void checkIteratorsAreValid(IteratorType1 begin_b, IteratorType1 end_b, IteratorType2 begin_a, IteratorType2 end_a)
Helper function checking if an iterator and a co-iterator both have a next element.
Definition: StatisticFunctions.h:104
OpenMS::Exception::InvalidRange
Invalid range exception.
Definition: Exception.h:285
OpenMS::Size
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
OpenMS::Math::SummaryStatistics
Helper class to gather (and dump) some statistics from a e.g. vector<double>.
Definition: StatisticFunctions.h:657
OpenMS::Math::SummaryStatistics::SummaryStatistics
SummaryStatistics(T &data)
Definition: StatisticFunctions.h:665
OpenMS
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
Exception.h
OpenMS::Math::SummaryStatistics::variance
double variance
Definition: StatisticFunctions.h:686
OpenMS::Math::matthewsCorrelationCoefficient
static double matthewsCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
Calculates the Matthews correlation coefficient for the values in [begin_a, end_a) and [begin_b,...
Definition: StatisticFunctions.h:452
OpenMS::Math::SummaryStatistics::max
T::value_type max
Definition: StatisticFunctions.h:687
int
OpenMS::Math::meanSquareError
static double meanSquareError(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
Calculates the mean square error for the values in [begin_a, end_a) and [begin_b, end_b)
Definition: StatisticFunctions.h:379
OpenMS::Math::MAD
double MAD(IteratorType begin, IteratorType end, double median_of_numbers)
median absolute deviation (MAD)
Definition: StatisticFunctions.h:198
OpenMS::Math::SummaryStatistics::lowerq
double lowerq
Definition: StatisticFunctions.h:686
OpenMS::Math::quantile1st
static double quantile1st(IteratorType begin, IteratorType end, bool sorted=false)
Calculates the first quantile of a range of values.
Definition: StatisticFunctions.h:223
OpenMS::Math::SummaryStatistics::SummaryStatistics
SummaryStatistics()
Definition: StatisticFunctions.h:659
OpenMS::Math::quantile3rd
static double quantile3rd(IteratorType begin, IteratorType end, bool sorted=false)
Calculates the third quantile of a range of values.
Definition: StatisticFunctions.h:255
OpenMS::Math::computeRank
static void computeRank(std::vector< Value > &w)
Replaces the elements in vector w by their ranks.
Definition: StatisticFunctions.h:539
OpenMS::Math::checkIteratorsNotNULL
static void checkIteratorsNotNULL(IteratorType begin, IteratorType end)
Helper function checking if two iterators are not equal.
Definition: StatisticFunctions.h:72
OpenMS::SignedSize
ptrdiff_t SignedSize
Signed Size type e.g. used as pointer difference.
Definition: Types.h:134
OpenMS::Math::variance
static double variance(IteratorType begin, IteratorType end, double mean=std::numeric_limits< double >::max())
Calculates the variance of a range of values.
Definition: StatisticFunctions.h:278
Value
OpenMS::Math::mean
static double mean(IteratorType begin, IteratorType end)
Calculates the mean of a range of values.
Definition: StatisticFunctions.h:133
OpenMS::Math::covariance
static double covariance(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
Calculates the covariance of two ranges of values.
Definition: StatisticFunctions.h:346
OpenMS::Math::classificationRate
static double classificationRate(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
Calculates the classification rate for the values in [begin_a, end_a) and [begin_b,...
Definition: StatisticFunctions.h:413
OpenMS::Math::SummaryStatistics::upperq
double upperq
Definition: StatisticFunctions.h:686
OpenMS::Math::SummaryStatistics::count
size_t count
Definition: StatisticFunctions.h:688
OpenMS::Math::absdev
static double absdev(IteratorType begin, IteratorType end, double mean=std::numeric_limits< double >::max())
Calculates the absolute deviation of a range of values.
Definition: StatisticFunctions.h:320
OpenMS::Math::SummaryStatistics::min
T::value_type min
Definition: StatisticFunctions.h:687
OpenMS::Math::pearsonCorrelationCoefficient
static double pearsonCorrelationCoefficient(IteratorType1 begin_a, IteratorType1 end_a, IteratorType2 begin_b, IteratorType2 end_b)
Calculates the Pearson correlation coefficient for the values in [begin_a, end_a) and [begin_b,...
Definition: StatisticFunctions.h:505
OpenMS::Math::sd
static double sd(IteratorType begin, IteratorType end, double mean=std::numeric_limits< double >::max())
Calculates the standard deviation of a range of values.
Definition: StatisticFunctions.h:305