OpenMS
Loading...
Searching...
No Matches
MathFunctions.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: Timo Sachsenberg$
6// $Authors: Marc Sturm $
7// --------------------------------------------------------------------------
8
9#pragma once
10
16
17#include <cmath>
18#include <cstdint>
19#include <limits>
20#include <random>
21#include <utility> // for std::pair
22#include <vector>
23
24namespace OpenMS
25{
33namespace Math
34{
35
44 template<typename T>
45 bool extendRange(T& min, T& max, const T& value)
46 {
47 if (value < min)
48 {
49 min = value;
50 return true;
51 }
52 if (value > max)
53 {
54 max = value;
55 return true;
56 }
57 return false;
58 }
59
65 template<typename T>
66 bool contains(T value, T min, T max)
67 {
68 return min <= value && value <= max;
69 }
70
91 inline std::pair<double, double> zoomIn(const double left, const double right, const float factor, const float align)
92 {
93 OPENMS_PRECONDITION(factor >= 0, "Factor must be >=0")
94 OPENMS_PRECONDITION(align >= 0, "align must be >=0")
95 OPENMS_PRECONDITION(align <= 1, "align must be <=1")
96 std::pair<double, double> res;
97 auto old_width = right - left;
98 auto offset_left = (1.0f - factor) * old_width * align;
99 res.first = left + offset_left;
100 res.second = res.first + old_width * factor;
101 return res;
102 }
103
104 using BinContainer = std::vector<RangeBase>;
120 inline BinContainer createBins(double min, double max, uint32_t number_of_bins, double extend_margin = 0)
121 {
122 OPENMS_PRECONDITION(number_of_bins >= 1, "Number of bins must be >= 1")
123 OPENMS_PRECONDITION(min < max, "Require min < max");
124 std::vector<RangeBase> res(number_of_bins);
125 const double bin_width = (max - min) / number_of_bins;
126 for (uint32_t i = 0; i < number_of_bins; ++i)
127 {
128 res[i] = RangeBase(min + i * bin_width, min + (i + 1) * bin_width);
129 res[i].extendLeftRight(extend_margin);
130 }
131 res.front().setMin(min); // undo potential margin
132 res.back().setMax(max); // undo potential margin
133
134 return res;
135 }
136
137
149 inline double ceilDecimal(double x, int decPow)
150 {
151 return (ceil(x / pow(10.0, decPow))) * pow(10.0, decPow); // decimal shift right, ceiling, decimal shift left
152 }
153
164 inline double roundDecimal(double x, int decPow)
165 {
166 if (x > 0) return (floor(0.5 + x / pow(10.0, decPow))) * pow(10.0, decPow);
167
168 return -((floor(0.5 + fabs(x) / pow(10.0, decPow))) * pow(10.0, decPow));
169 }
170
176 inline double intervalTransformation(double x, double left1, double right1, double left2, double right2)
177 {
178 return left2 + (x - left1) * (right2 - left2) / (right1 - left1);
179 }
180
188 inline double linear2log(double x)
189 {
190 return log10(x + 1); //+1 to avoid negative logarithms
191 }
192
200 inline double log2linear(double x)
201 {
202 return pow(10, x) - 1;
203 }
204
210 inline bool isOdd(UInt x)
211 {
212 return (x & 1) != 0;
213 }
214
220 template<typename T>
221 T round(T x)
222 {
223 return std::round(x);
224 }
225
240 template<typename T>
241 T roundTo(const T value, int digits)
242 {
243 T factor = 1.0;
244 if (digits > 0)
245 {
246 for (int i = 0; i < digits; ++i)
247 factor *= 10.0;
248 }
249 else if (digits < 0)
250 {
251 for (int i = 0; i < -digits; ++i)
252 factor /= 10.0;
253 }
254
255 return std::round(value * factor) / factor;
256 }
257
275 template<typename T>
276 double percentOf(T value, T total, int digits)
277 {
278 if (value < 0) { throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Value must be non-negative",StringUtils::toStr(value)); }
279 if (total < 0) { throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Total must be non-negative",StringUtils::toStr(total)); }
280 if (total <= 0) // avoid float equality compare
281 {
282 return 0.0; // avoid division by zero
283 }
284 return roundTo(value * 100.0 / total, digits);
285 }
286
292 inline bool approximatelyEqual(double a, double b, double tol)
293 {
294 return std::fabs(a - b) <= tol;
295 }
296
305 template<typename T>
306 T gcd(T a, T b)
307 {
308 T c;
309 while (b != 0)
310 {
311 c = a % b;
312 a = b;
313 b = c;
314 }
315 return a;
316 }
317
330 template<typename T>
331 T gcd(T a, T b, T& u1, T& u2)
332 {
333 u1 = 1;
334 u2 = 0;
335 T u3 = a;
336
337 T v1 = 0;
338 T v2 = 1;
339 T v3 = b;
340
341 while (v3 != 0)
342 {
343 T q = u3 / v3;
344 T t1 = u1 - v1 * q;
345 T t2 = u2 - v2 * q;
346 T t3 = u3 - v3 * q;
347
348 u1 = v1;
349 u2 = v2;
350 u3 = v3;
351
352 v1 = t1;
353 v2 = t2;
354 v3 = t3;
355 }
356
357 return u3;
358 }
359
369 template<typename T>
370 T getPPM(T mz_obs, T mz_ref)
371 {
372 return (mz_obs - mz_ref) / mz_ref * 1e6;
373 }
374
384 template<typename T>
385 T getPPMAbs(T mz_obs, T mz_ref)
386 {
387 return std::fabs(getPPM(mz_obs, mz_ref));
388 }
389
399 template<typename T>
400 T ppmToMass(T ppm, T mz_ref)
401 {
402 return (ppm / T(1e6)) * mz_ref;
403 }
404
405 /*
406 @brief Compute the absolute mass diff in [Th], given a ppm value and a reference point.
407
408 The returned mass diff is always positive!
409
410 @param[in] ppm Parts-per-million error
411 @param[in] mz_ref Reference m/z
412 @return The absolute mass diff in [Th]
413 */
414 template<typename T>
415 T ppmToMassAbs(T ppm, T mz_ref)
416 {
417 return std::fabs(ppmToMass(ppm, mz_ref));
418 }
419
433 inline std::pair<double, double> getTolWindow(double val, double tol, bool ppm)
434 {
435 double left, right;
436
437 if (ppm)
438 {
439 left = val - val * tol * 1e-6;
440 right = val / (1.0 - tol * 1e-6);
441 }
442 else
443 {
444 left = val - tol;
445 right = val + tol;
446 }
447
448 return std::make_pair(left, right);
449 }
450
454 template<typename T1>
455 typename T1::value_type quantile(const T1& x, double q)
456 {
457 if (x.empty()) throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Quantile requested from empty container.");
458 if (q < 0.0) q = 0.;
459 if (q > 1.0) q = 1.;
460
461 const auto n = x.size();
462 const auto id = std::max(0., n * q - 1); // -1 for c++ index starting at 0
463 const auto lo = floor(id);
464 const auto hi = ceil(id);
465 const auto qs = x[lo];
466 const auto h = (id - lo);
467
468 return (1.0 - h) * qs + h * x[hi];
469 }
470
478 class OPENMS_DLLAPI RandomShuffler
479 {
480 public:
482 RandomShuffler() = default;
484 explicit RandomShuffler(int seed): rng_(static_cast<std::uint64_t>(seed))
485 {
486 }
487
488 template<class RandomAccessIterator>
489 void portable_random_shuffle(RandomAccessIterator first, RandomAccessIterator last)
490 {
491 for (auto i = last - first; i > 1; --i)
492 {
493 std::iter_swap(first + i - 1, first + randomIndex_(i - 1));
494 }
495 }
496
497 void seed(uint64_t value)
498 {
499 rng_.seed(value);
500 }
501
502 private:
503 std::mt19937_64 rng_;
505 std::ptrdiff_t randomIndex_(std::ptrdiff_t upper);
506 };
507
516 OPENMS_DLLAPI double log_binomial_coef(unsigned n, unsigned k);
517
525 inline double log_sum_exp(double x, double y)
526 {
527 // Handle infinite cases
528 if (std::isinf(x) && x < 0) return y;
529 if (std::isinf(y) && y < 0) return x;
530
531 // Use the maximum value for numerical stability
532 double max_val = std::max(x, y);
533 return max_val + std::log(std::exp(x - max_val) + std::exp(y - max_val));
534 }
535
548 OPENMS_DLLAPI double binomial_cdf_complement(unsigned N, unsigned n, double p);
549} // namespace Math
550} // namespace OpenMS
Exception indicating that an invalid parameter was handed over to an algorithm.
Definition Exception.h:317
Invalid value exception.
Definition Exception.h:306
Portable random shuffle with a reproducible, platform-independent random sequence.
Definition MathFunctions.h:479
RandomShuffler(int seed)
Constructor seeding the engine with seed.
Definition MathFunctions.h:484
std::ptrdiff_t randomIndex_(std::ptrdiff_t upper)
A uniform index in [0, upper], drawn so that every platform gets the same one.
void portable_random_shuffle(RandomAccessIterator first, RandomAccessIterator last)
Definition MathFunctions.h:489
RandomShuffler()=default
Default constructor; the engine starts from its default seed.
std::mt19937_64 rng_
Definition MathFunctions.h:503
void seed(uint64_t value)
Definition MathFunctions.h:497
OpenMS looks in the< code > OPENMS_THERMO_MANAGED_DIR</code > environment variable first
Definition common-cmake-parameters.doxygen:179
unsigned int UInt
Unsigned integer type.
Definition Types.h:64
#define OPENMS_PRECONDITION(condition, message)
Precondition macro.
Definition openms/include/OpenMS/CONCEPT/Macros.h:91
bool approximatelyEqual(double a, double b, double tol)
Returns if a is approximately equal b , allowing a tolerance of tol.
Definition MathFunctions.h:292
bool isOdd(UInt x)
Returns true if the given integer is odd.
Definition MathFunctions.h:210
T gcd(T a, T b)
Returns the greatest common divisor (gcd) of two numbers by applying the Euclidean algorithm.
Definition MathFunctions.h:306
double log2linear(double x)
Transforms a number from log10 to to linear scale. Subtracts the 1 added by linear2log(double)
Definition MathFunctions.h:200
double roundDecimal(double x, int decPow)
rounds x to the next decimal power 10 ^ decPow
Definition MathFunctions.h:164
double linear2log(double x)
Transforms a number from linear to log10 scale. Avoids negative logarithms by adding 1.
Definition MathFunctions.h:188
T round(T x)
Rounds the value.
Definition MathFunctions.h:221
double ceilDecimal(double x, int decPow)
rounds x up to the next decimal power 10 ^ decPow
Definition MathFunctions.h:149
double intervalTransformation(double x, double left1, double right1, double left2, double right2)
transforms point x of interval [left1,right1] into interval [left2,right2]
Definition MathFunctions.h:176
double log_sum_exp(double x, double y)
Log-sum-exp operation for numerical stability.
Definition MathFunctions.h:525
T getPPMAbs(T mz_obs, T mz_ref)
Compute absolute parts-per-million of two m/z values.
Definition MathFunctions.h:385
BinContainer createBins(double min, double max, uint32_t number_of_bins, double extend_margin=0)
Split a range [min,max] into number_of_bins (with optional overlap) and return the ranges of each bin...
Definition MathFunctions.h:120
T1::value_type quantile(const T1 &x, double q)
Returns the value of the q th quantile (0-1) in a sorted non-empty vector x.
Definition MathFunctions.h:455
double binomial_cdf_complement(unsigned N, unsigned n, double p)
Calculate binomial cumulative distribution function P(X ≥ n)
std::pair< double, double > zoomIn(const double left, const double right, const float factor, const float align)
Zoom into an interval [left, right], decreasing its width by factor (which must be in [0,...
Definition MathFunctions.h:91
double log_binomial_coef(unsigned n, unsigned k)
Calculate logarithm of binomial coefficient C(n,k) using log-gamma function.
T getPPM(T mz_obs, T mz_ref)
Compute parts-per-million of two m/z values.
Definition MathFunctions.h:370
std::pair< double, double > getTolWindow(double val, double tol, bool ppm)
Return tolerance window around val given tolerance tol.
Definition MathFunctions.h:433
T roundTo(const T value, int digits)
Definition MathFunctions.h:241
T ppmToMass(T ppm, T mz_ref)
Compute the mass diff in [Th], given a ppm value and a reference point.
Definition MathFunctions.h:400
T ppmToMassAbs(T ppm, T mz_ref)
Definition MathFunctions.h:415
double percentOf(T value, T total, int digits)
Definition MathFunctions.h:276
bool contains(T value, T min, T max)
Is a value contained in [min, max] ?
Definition MathFunctions.h:66
std::vector< RangeBase > BinContainer
Definition MathFunctions.h:104
bool extendRange(T &min, T &max, const T &value)
Given an interval/range and a new value, extend the range to include the new value if needed.
Definition MathFunctions.h:45
std::string toStr(int i)
Definition StringUtils.h:100
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
STL namespace.
Base class for a simple range with minimum and maximum.
Definition RangeManager.h:37