OpenMS  2.8.0
RangeManager.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-2021.
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: Chris Bielow $
32 // $Authors: Chris Bielow $
33 // --------------------------------------------------------------------------
34 
35 #pragma once
36 
37 #include <OpenMS/config.h>
39 
40 #include <algorithm> // for min/max
41 #include <cassert>
42 #include <iosfwd> // for std::ostream
43 
44 
45 namespace OpenMS
46 {
48  enum class MSDim
49  {
50  RT,
51  MZ,
52  INT,
53  IM
54  };
55 
57  struct OPENMS_DLLAPI RangeBase
58  {
59  public:
61  RangeBase() = default;
62 
65  RangeBase(const double min, const double max) :
66  min_(min), max_(max)
67  {
68  if (min_ > max_)
69  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Invalid initialization of range");
70  }
71 
73  void clear()
74  {
75  *this = RangeBase(); // overwrite with fresh instance
76  }
77 
79  bool isEmpty() const
80  { // invariant: only possible when default constructed or clear()'ed
81  return min_ > max_;
82  }
83 
85  bool contains(const double value) const
86  {
87  return min_ <= value && value <= max_;
88  }
89 
91  bool contains(const RangeBase& inner_range) const
92  {
93  return contains(inner_range.min_) && contains(inner_range.max_);
94  }
95 
101 
103  void setMin(const double min)
104  {
105  min_ = min;
106  if (max_ < min)
107  max_ = min;
108  }
109 
111  void setMax(const double max)
112  {
113  max_ = max;
114  if (min_ > max)
115  min_ = max;
116  }
117 
119  double getMin() const
120  {
121  return min_;
122  }
123 
125  double getMax() const
126  {
127  return max_;
128  }
130 
132  void extend(const RangeBase& other)
133  {
134  min_ = std::min(min_, other.min_);
135  max_ = std::max(max_, other.max_);
136  }
137 
139  void extend(const double value)
140  {
141  min_ = std::min(min_, value);
142  max_ = std::max(max_, value);
143  }
144 
155  void scaleBy(const double factor)
156  {
157  if (isEmpty()) return;
158  const double dist = max_ - min_;
159  const double extension = dist * (factor - 1) / 2;
160  min_ -= extension;
161  max_ += extension;
162  }
163 
164  void assign(const RangeBase& rhs)
165  {
166  *this = rhs;
167  }
168 
169  bool operator==(const RangeBase& rhs) const
170  {
171  return min_ == rhs.min_ && max_ == rhs.max_;
172  }
173 
174  protected:
175  // make members non-accessible to maintain invariant: min <= max (unless uninitialized)
176  double min_ = std::numeric_limits<double>::max();
177  double max_ = -std::numeric_limits<double>::max();
178  };
179 
180  OPENMS_DLLAPI std::ostream& operator<<(std::ostream& out, const RangeBase& b);
181 
182  struct OPENMS_DLLAPI RangeRT : public RangeBase {
183 
184  const static MSDim DIM = MSDim::RT;
185 
186  RangeRT() = default;
187  RangeRT(const double min, const double max) :
188  RangeBase(min, max)
189  {
190  }
191 
197 
199  void setMinRT(const double min)
200  {
201  setMin(min);
202  }
203 
205  void setMaxRT(const double max)
206  {
207  setMax(max);
208  }
209 
211  double getMinRT() const
212  {
213  return min_;
214  }
215 
217  double getMaxRT() const
218  {
219  return max_;
220  }
222 
224  void extendRT(const double value)
225  {
226  extend(value);
227  }
228 
230  bool containsRT(const double value) const
231  {
232  return RangeBase::contains(value);
233  }
234 
236  bool containsRT(const RangeBase& inner_range) const
237  {
238  return RangeBase::contains(inner_range);
239  }
240  };
241 
242  OPENMS_DLLAPI std::ostream& operator<<(std::ostream& out, const RangeRT& range);
243 
244  struct OPENMS_DLLAPI RangeMZ : public RangeBase
245  {
246 
247  const static MSDim DIM = MSDim::MZ;
248 
249  RangeMZ() = default;
250  RangeMZ(const double min, const double max) :
251  RangeBase(min, max)
252  {
253  }
254 
260 
262  void setMinMZ(const double min)
263  {
264  setMin(min);
265  }
266 
268  void setMaxMZ(const double max)
269  {
270  setMax(max);
271  }
272 
274  double getMinMZ() const
275  {
276  return min_;
277  }
278 
280  double getMaxMZ() const
281  {
282  return max_;
283  }
285 
287  void extendMZ(const double value)
288  {
289  extend(value);
290  }
291 
293  bool containsMZ(const double value) const
294  {
295  return RangeBase::contains(value);
296  }
297 
299  bool containsMZ(const RangeBase& inner_range) const
300  {
301  return RangeBase::contains(inner_range);
302  }
303  };
304  OPENMS_DLLAPI std::ostream& operator<<(std::ostream& out, const RangeMZ& range);
305 
306  struct OPENMS_DLLAPI RangeIntensity : public RangeBase {
307 
308  const static MSDim DIM = MSDim::INT;
309 
310  RangeIntensity() = default;
311  RangeIntensity(const double min, const double max) :
312  RangeBase(min, max)
313  {
314  }
315 
321 
323  void setMinIntensity(const double min)
324  {
325  setMin(min);
326  }
327 
329  void setMaxIntensity(const double max)
330  {
331  setMax(max);
332  }
333 
335  double getMinIntensity() const
336  {
337  return min_;
338  }
339 
341  double getMaxIntensity() const
342  {
343  return max_;
344  }
346 
348  void extendIntensity(const double value)
349  {
350  extend(value);
351  }
352 
354  bool containsIntensity(const double value) const
355  {
356  return RangeBase::contains(value);
357  }
358 
360  bool containsIntensity(const RangeBase& inner_range) const
361  {
362  return RangeBase::contains(inner_range);
363  }
364  };
365 
366  OPENMS_DLLAPI std::ostream& operator<<(std::ostream& out, const RangeIntensity& range);
367 
368  struct OPENMS_DLLAPI RangeMobility : public RangeBase
369  {
370  const static MSDim DIM = MSDim::IM;
371 
372  RangeMobility() = default;
373  RangeMobility(const double min, const double max) :
374  RangeBase(min, max)
375  {
376  }
377 
383 
385  void setMinMobility(const double min)
386  {
387  setMin(min);
388  }
389 
391  void setMaxMobility(const double max)
392  {
393  setMax(max);
394  }
395 
397  double getMinMobility() const
398  {
399  return min_;
400  }
401 
403  double getMaxMobility() const
404  {
405  return max_;
406  }
408 
410  void extendMobility(const double value)
411  {
412  extend(value);
413  }
414 
416  bool containsMobility(const double value) const
417  {
418  return RangeBase::contains(value);
419  }
420 
422  bool containsMobility(const RangeBase& inner_range) const
423  {
424  return RangeBase::contains(inner_range);
425  }
426  };
427 
428  OPENMS_DLLAPI std::ostream& operator<<(std::ostream& out, const RangeMobility& range);
429 
431  enum class HasRangeType
432  {
433  ALL,
434  SOME,
435  NONE
436  };
437 
453  template<typename... RangeBases>
454  class RangeManager : public RangeBases...
455  {
456  public:
457  // rule of 0 -- no need for a virtual d'tor or anything fancy
458  // ...
459 
460  bool operator==(const RangeManager& rhs) const
461  {
462  bool equal = true;
463  for_each_base_([&](auto* base) {
464  using T_BASE = std::decay_t<decltype(*base)>; // remove const/ref qualifiers
465  equal &= ((T_BASE&) rhs == (T_BASE&) *this);
466  });
467  return equal;
468  }
469 
470 
475  template <typename... RangeBasesOther>
477  {
478  bool found = false;
479  for_each_base_([&](auto* base) {
480  using T_BASE = std::decay_t<decltype(*base)>; // remove const/ref qualifiers
481  if constexpr (std::is_base_of_v<T_BASE, RangeManager<RangeBasesOther...>>)
482  {
483  base->assign((T_BASE&) rhs);
484  found = true;
485  }
486  });
487 
488  return found;
489  }
490 
495  template<typename... RangeBasesOther>
497  {
498  if (!assignUnsafe(rhs))
499  {
500  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION , "No assignment took place (no dimensions in common!);");
501  }
502  }
503 
508  template<typename... RangeBasesOther>
510  {
511  bool found = false;
512  for_each_base_([&](auto* base) {
513  using T_BASE = std::decay_t<decltype(*base)>; // remove const/ref qualifiers
514  if constexpr (std::is_base_of_v<T_BASE, RangeManager<RangeBasesOther...>>)
515  {
516  base->extend((T_BASE&) rhs);
517  found = true;
518  }
519  });
520  return found;
521  }
522 
527  template<typename... RangeBasesOther>
529  {
530  if (!extendUnsafe(rhs))
531  {
532  throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "No assignment took place (no dimensions in common!);");
533  }
534  }
535 
537  void scaleBy(const double factor)
538  {
539  for_each_base_([&](auto* base) {
540  base->scaleBy(factor);
541  });
542  }
543 
546  {
547  RangeBase* r_base = nullptr;
548 
549  static_for_each_base_([&](auto* base) {
550  using Base = std::decay_t<decltype(*base)>; // remove const/ref qualifiers
551  if (base->DIM == dim)
552  r_base = (Base*) this;
553  });
554 
555  assert((r_base != nullptr) && "No base class has this MSDim!");
556  return *r_base;
557  }
558 
561  {
562  constexpr size_t total{sizeof...(RangeBases)};// total number of bases
563  size_t count{0};
564  for_each_base_([&](auto* base) {
565  count += !base->isEmpty();
566  });
567  switch (count)
568  {
569  case 0:
570  return HasRangeType::NONE;
571  case total:
572  return HasRangeType::ALL;
573  default:
574  return HasRangeType::SOME;
575  }
576  }
577 
582  template<typename... RangeBasesOther>
584  {
585  bool contained = true; // assume rhs is contained, until proven otherwise
586  bool has_overlap = false;
587  for_each_base_([&](auto* base) {
588  using T_BASE = std::decay_t<decltype(*base)>; // remove const/ref qualifiers
589  if constexpr (std::is_base_of_v<T_BASE, RangeManager<RangeBasesOther...>>)
590  {
591  has_overlap = true; // at least one dimension overlaps
592  if (((T_BASE&)rhs).isEmpty()) return;
593  if (base->contains((T_BASE&) rhs)) return;
594  contained = false;
595  }
596  });
597  if (!has_overlap) throw Exception::InvalidRange(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION);
598 
599  return contained;
600  }
601 
603  void clearRanges()
604  {
605  for_each_base_([&](auto* base) {
606  base->clear();
607  });
608  }
609 
611  void printRange(std::ostream& out) const
612  {
613  for_each_base_([&](auto* base) {
614  out << *base;
615  });
616  }
617 
618  protected:
620  template<typename Visitor>
621  void for_each_base_(Visitor&& visitor)
622  {
623  (void(visitor(static_cast<RangeBases*>(this))), ...);
624  }
626  template<typename Visitor>
627  void for_each_base_(Visitor&& visitor) const
628  {
629  (void(visitor(static_cast<const RangeBases*>(this))), ...);
630  }
631 
633  template<typename Visitor>
634  static void static_for_each_base_(Visitor&& visitor)
635  {
636  (void(visitor(static_cast<const RangeBases*>(nullptr))), ...);
637  }
638  };
639 
640  template<typename... Range>
641  std::ostream& operator<<(std::ostream& out, const RangeManager<Range...>& me)
642  {
643  me.printRange(out);
644  return out;
645  }
646 
649  template <typename ...RangeBases>
651  : public RangeManager<RangeBases...>
652  {
653  public:
656  virtual void updateRanges() = 0;
657 
659  const RangeManager<RangeBases...>& getRange() const
660  {
661  return (RangeManager<RangeBases...>&) *this;
662  }
663 
665  RangeManager<RangeBases...>& getRange()
666  {
667  return (RangeManager<RangeBases...>&)*this;
668  }
669 
670  };
671 
672 } // namespace OpenMS
Invalid range exception.
Definition: Exception.h:278
Definition: RangeManager.h:652
RangeManager< RangeBases... > & getRange()
get mutable range, provided for efficiency reasons (avoid updateRanges(), if only minor changes were ...
Definition: RangeManager.h:665
virtual void updateRanges()=0
const RangeManager< RangeBases... > & getRange() const
get range of current data (call updateRanges() before to ensure the range is accurate)
Definition: RangeManager.h:659
Handles the management of a multidimensional range, e.g. RangeMZ and RangeIntensity for spectra.
Definition: RangeManager.h:455
bool assignUnsafe(const RangeManager< RangeBasesOther... > &rhs)
Definition: RangeManager.h:476
HasRangeType hasRange() const
is any/some/all dimension in this range populated?
Definition: RangeManager.h:560
RangeBase & getRangeForDim(MSDim dim)
obtain a range dimension at runtime using dim
Definition: RangeManager.h:545
bool operator==(const RangeManager &rhs) const
Definition: RangeManager.h:460
void for_each_base_(Visitor &&visitor)
use fold expression to iterate over all RangeBases of RangeManager and apply a lambda (Visitor) for e...
Definition: RangeManager.h:621
void for_each_base_(Visitor &&visitor) const
.. and a const version
Definition: RangeManager.h:627
void scaleBy(const double factor)
calls RangeBase::scale() for each dimension
Definition: RangeManager.h:537
bool extendUnsafe(const RangeManager< RangeBasesOther... > &rhs)
Definition: RangeManager.h:509
void clearRanges()
Resets all ranges.
Definition: RangeManager.h:603
void printRange(std::ostream &out) const
print each dimension (base classes) to a stream
Definition: RangeManager.h:611
void extend(const RangeManager< RangeBasesOther... > &rhs)
Definition: RangeManager.h:528
void assign(const RangeManager< RangeBasesOther... > &rhs)
Definition: RangeManager.h:496
bool containsAll(const RangeManager< RangeBasesOther... > &rhs) const
Definition: RangeManager.h:583
static void static_for_each_base_(Visitor &&visitor)
use fold expression to iterate over all RangeBases of RangeManager and apply a lambda (Visitor) for e...
Definition: RangeManager.h:634
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:47
std::ostream & operator<<(std::ostream &os, const AccurateMassSearchResult &amsr)
MSDim
Dimensions of data acquisition for MS data.
Definition: RangeManager.h:49
HasRangeType
Enum listing state of dimensions (RangeBases)
Definition: RangeManager.h:432
@ ALL
all dimensions are filled
@ SOME
some dimensions are empty, some are filled
@ NONE
all dimensions are empty (=cleared)
Base class for a simple range with minimum and maximum.
Definition: RangeManager.h:58
double max_
Definition: RangeManager.h:177
void setMin(const double min)
sets the minimum (and the maximum, if uninitialized)
Definition: RangeManager.h:103
void scaleBy(const double factor)
Scale the range of the dimension by a factor. A factor > 1 increases the range; factor < 1 decreases ...
Definition: RangeManager.h:155
void assign(const RangeBase &rhs)
Definition: RangeManager.h:164
bool contains(const double value) const
is value within [min, max]?
Definition: RangeManager.h:85
RangeBase()=default
Ctor: initialize with empty range.
void extend(const double value)
extend the range such that it includes the given value
Definition: RangeManager.h:139
bool contains(const RangeBase &inner_range) const
is the range inner_range within [min, max]?
Definition: RangeManager.h:91
double getMin() const
only useful if isEmpty() returns false
Definition: RangeManager.h:119
void clear()
make the range empty, i.e. isEmpty() will be true
Definition: RangeManager.h:73
void setMax(const double max)
sets the maximum (and the minimum, if uninitialized)
Definition: RangeManager.h:111
bool isEmpty() const
is the range empty (i.e. default constructed or cleared using clear())?
Definition: RangeManager.h:79
double min_
Definition: RangeManager.h:176
RangeBase(const double min, const double max)
Definition: RangeManager.h:65
bool operator==(const RangeBase &rhs) const
Definition: RangeManager.h:169
double getMax() const
only useful if isEmpty() returns false
Definition: RangeManager.h:125
void extend(const RangeBase &other)
ensure the range includes the range of other
Definition: RangeManager.h:132
Definition: RangeManager.h:306
void setMinIntensity(const double min)
sets the minimum (and the maximum, if uninitialized)
Definition: RangeManager.h:323
double getMinIntensity() const
only useful if isEmpty() returns false
Definition: RangeManager.h:335
void extendIntensity(const double value)
extend the range such that it includes the given value
Definition: RangeManager.h:348
bool containsIntensity(const double value) const
is value within [min, max]?
Definition: RangeManager.h:354
RangeIntensity(const double min, const double max)
Definition: RangeManager.h:311
double getMaxIntensity() const
only useful if isEmpty() returns false
Definition: RangeManager.h:341
bool containsIntensity(const RangeBase &inner_range) const
is the range inner_range within [min, max] of this range?
Definition: RangeManager.h:360
void setMaxIntensity(const double max)
sets the maximum (and the minimum, if uninitialized)
Definition: RangeManager.h:329
Definition: RangeManager.h:245
bool containsMZ(const RangeBase &inner_range) const
is the range inner_range within [min, max] of this range?
Definition: RangeManager.h:299
void setMaxMZ(const double max)
sets the maximum (and the minimum, if uninitialized)
Definition: RangeManager.h:268
void extendMZ(const double value)
extend the range such that it includes the given value
Definition: RangeManager.h:287
void setMinMZ(const double min)
sets the minimum (and the maximum, if uninitialized)
Definition: RangeManager.h:262
double getMaxMZ() const
only useful if isEmpty() returns false
Definition: RangeManager.h:280
double getMinMZ() const
only useful if isEmpty() returns false
Definition: RangeManager.h:274
RangeMZ(const double min, const double max)
Definition: RangeManager.h:250
RangeMZ()=default
bool containsMZ(const double value) const
is value within [min, max]?
Definition: RangeManager.h:293
Definition: RangeManager.h:369
bool containsMobility(const double value) const
is value within [min, max]?
Definition: RangeManager.h:416
void extendMobility(const double value)
extend the range such that it includes the given value
Definition: RangeManager.h:410
double getMinMobility() const
only useful if isEmpty() returns false
Definition: RangeManager.h:397
bool containsMobility(const RangeBase &inner_range) const
is the range inner_range within [min, max] of this range?
Definition: RangeManager.h:422
double getMaxMobility() const
only useful if isEmpty() returns false
Definition: RangeManager.h:403
void setMinMobility(const double min)
sets the minimum (and the maximum, if uninitialized)
Definition: RangeManager.h:385
void setMaxMobility(const double max)
sets the maximum (and the minimum, if uninitialized)
Definition: RangeManager.h:391
RangeMobility(const double min, const double max)
Definition: RangeManager.h:373
Definition: RangeManager.h:182
bool containsRT(const RangeBase &inner_range) const
is the range inner_range within [min, max] of this range?
Definition: RangeManager.h:236
void extendRT(const double value)
extend the range such that it includes the given value
Definition: RangeManager.h:224
double getMaxRT() const
only useful if isEmpty() returns false
Definition: RangeManager.h:217
RangeRT(const double min, const double max)
Definition: RangeManager.h:187
void setMaxRT(const double max)
sets the maximum (and the minimum, if uninitialized)
Definition: RangeManager.h:205
RangeRT()=default
void setMinRT(const double min)
sets the minimum (and the maximum, if uninitialized)
Definition: RangeManager.h:199
double getMinRT() const
only useful if isEmpty() returns false
Definition: RangeManager.h:211
bool containsRT(const double value) const
is value within [min, max]?
Definition: RangeManager.h:230