Logo ROOT   6.08/07
Reference Guide
TAxis.hxx
Go to the documentation of this file.
1 /// \file ROOT/TAxis.h
2 /// \ingroup Hist
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-03-23
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
6 
7 /*************************************************************************
8  * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
9  * All rights reserved. *
10  * *
11  * For the licensing terms see $ROOTSYS/LICENSE. *
12  * For the list of contributors see $ROOTSYS/README/CREDITS. *
13  *************************************************************************/
14 
15 #ifndef ROOT7_TAxis
16 #define ROOT7_TAxis
17 
18 #include <algorithm>
19 #include <cmath>
20 #include <string>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "RStringView.h"
25 #include "ROOT/TLogger.hxx"
26 
27 namespace ROOT {
28 namespace Experimental {
29 
30 /**
31  \class TAxisBase ROOT7
32  Histogram axis base class. Keeps track of the number of bins and overflow
33  handling. Offers bin iteration.
34 
35  Bin indices are starting from 0 for the underflow bin (representing values that
36  are lower than the axis range). Starting at index 1 are the actual bins of the
37  axis, up to N + 1 for an axis with N bins. Index N + 2 is the overflow bin for
38  values larger than the axis range.
39  */
40 class TAxisBase {
41 public:
42  /// Status of FindBin(x)
43  enum class EFindStatus {
44  kCanGrow, ///< Coordinate could fit after growing the axis
45  kValid ///< The returned bin index is valid
46  };
47 
48 protected:
49  ///\name Inaccessible copy, assignment
50  /// The copy and move constructors and assignment operators are protected to
51  /// prevent slicing.
52  ///\{
53  TAxisBase(const TAxisBase &) = default;
54  TAxisBase(TAxisBase &&) = default;
55  TAxisBase &operator=(const TAxisBase &) = default;
56  TAxisBase &operator=(TAxisBase &&) = default;
57  ///\}
58 
59  /// Default construct a TAxisBase (for use by derived classes for I/O)
60  TAxisBase() : fCanGrow(false)
61  {
62  }
63 
64  /// Given rawbin (<0 for underflow, >= GetNBinsNoOver() for overflow), determine the
65  /// actual bin number taking into account how over/underflow should be
66  /// handled.
67  ///
68  /// \param[out] status result status of the bin determination.
69  /// \return Returns the bin number adjusted for potential over- and underflow
70  /// bins. Returns kIgnoreBin if the axis cannot handle the over- / underflow,
71  /// in which case `status` will tell how to deal with this overflow.
72  int AdjustOverflowBinNumber(int rawbin) const {
73  if (rawbin < 0) return 0;
74  // Take underflow into account.
75  ++rawbin;
76 
77  if (rawbin >= GetNBins())
78  return GetNBins() - 1;
79 
80  return rawbin;
81  }
82 
83 public:
84  /**
85  \class const_iterator
86  Random const_iterator through bins. Represents the bin index, not a bin
87  content: the axis has no notion of any content.
88  */
90  public std::iterator<std::random_access_iterator_tag,
91  int /*value*/, int /*distance*/,
92  const int * /*pointer*/, const int & /*ref*/> {
93  int fCursor = 0; ///< Current iteration position
94 
95  public:
96  const_iterator() = default;
97 
98  /// Initialize a const_iterator with its position
99  explicit const_iterator(int cursor) noexcept: fCursor(cursor) { }
100 
101  /// ++i
103  // Could check whether fCursor < fEnd - but what for?
104  ++fCursor;
105  return *this;
106  }
107 
108  /// --i
110  // Could check whether fCursor > fBegin - but what for?
111  --fCursor;
112  return *this;
113  }
114 
115  /// i++
116  const_iterator operator++(int) noexcept {
117  const_iterator old(*this);
118  ++(*this);
119  return old;
120  }
121 
122  // i--
123  const_iterator operator--(int) noexcept {
124  const_iterator old(*this);
125  --(*this);
126  return old;
127  }
128 
129  // i += 2
130  const_iterator &operator+=(int d) noexcept {
131  fCursor += d;
132  return *this;
133  }
134 
135  // i -= 2
136  const_iterator &operator-=(int d) noexcept {
137  fCursor -= d;
138  return *this;
139  }
140 
141  // i + 2
142  const_iterator operator+(int d) noexcept {
143  const_iterator ret(*this);
144  ret += d;
145  return ret;
146  }
147 
148  // i - 2
149  const_iterator operator-(int d) noexcept {
150  const_iterator ret(*this);
151  ret -= d;
152  return ret;
153  }
154 
155  // *i
156  const int *operator*() const noexcept { return &fCursor; }
157 
158  // i->
159  int operator->() const noexcept { return fCursor; }
160 
161  friend bool operator<(const_iterator lhs, const_iterator rhs) noexcept;
162  friend bool operator>(const_iterator lhs, const_iterator rhs) noexcept;
163  friend bool operator<=(const_iterator lhs, const_iterator rhs) noexcept;
164  friend bool operator>=(const_iterator lhs, const_iterator rhs) noexcept;
165  friend bool operator==(const_iterator lhs, const_iterator rhs) noexcept;
166  friend bool operator!=(const_iterator lhs, const_iterator rhs) noexcept;
167  };
168 
169 
170  /// FindBin() returns this bin to signal that the bin number is invalid.
171  constexpr static const int kIgnoreBin = -1;
172 
173  /// Extra bins for each EAxisOverflow value.
174  constexpr static const int kNOverflowBins[4] = {0, 1, 1, 2};
175 
176  /// Construct a TAxisBase.
177  ///
178  ///\param[in] nbins - number of bins in this axis, excluding under- and
179  /// overflow bins.
180  ///\param[in] canGrow - whether this axis can extend its range.
181  TAxisBase(int nbinsNoOver, bool canGrow) noexcept:
182  fNBins(nbinsNoOver + (canGrow ? 0 : 2)), fCanGrow(canGrow) { }
183 
184  /// Construct a TAxisBase.
185  ///
186  ///\param[in] title - axis title used for graphics and text representation.
187  ///\param[in] nbins - number of bins in this axis, excluding under- and
188  /// overflow bins.
189  ///\param[in] canGrow - whether this axis can extend its range.
190  TAxisBase(std::string_view title, int nbinsNoOver, bool canGrow) noexcept:
191  fNBins(nbinsNoOver + (canGrow ? 0 : 2)), fTitle(title), fCanGrow(canGrow) { }
192 
193  const std::string& GetTitle() const { return fTitle; }
194 
195  /// Get the number of bins, excluding under- and overflow.
196  int GetNBinsNoOver() const noexcept {
197  return fNBins - GetNOverflowBins();
198  }
199 
200  /// Get the number of bins, including under- and overflow.
201  int GetNBins() const noexcept {
202  return fNBins;
203  }
204 
205  /// Get the number of over- and underflow bins: 0 for growable axes, 2 otherwise.
206  int GetNOverflowBins() const noexcept {
207  if (fCanGrow)
208  return 0;
209  else
210  return 2;
211  };
212 
213  /// Get the bin index for the underflow bin.
214  int GetUnderflowBin() const noexcept { return 0; }
215 
216  /// Get the bin index for the underflow bin (or the next bin outside range
217  /// if CanGrow()).
218  int GetOverflowBin() const noexcept {
219  return GetNBinsNoOver() + 1;
220  }
221 
222  /// Whether the bin index is referencing a bin lower than the axis range.
223  bool IsUnderflowBin(int bin) const noexcept {
224  return bin <= GetUnderflowBin();
225  }
226 
227  /// Whether the bin index is referencing a bin higher than the axis range.
228  bool IsOverflowBin(int bin) const noexcept {
229  return bin >= GetOverflowBin();
230  }
231 
232  ///\name Iterator interfaces
233  ///\{
234 
235  /// Get a const_iterator pointing to the first non-underflow bin.
236  const_iterator begin() const noexcept { return const_iterator{1}; }
237 
238  /// Get a const_iterator pointing the underflow bin.
240  return const_iterator{0};
241  }
242 
243  /// Get a const_iterator pointing right beyond the last non-overflow bin
244  /// (i.e. pointing to the overflow bin).
245  const_iterator end() const noexcept {
246  return const_iterator{GetOverflowBin()};
247  }
248 
249  /// Get a const_iterator pointing right beyond the overflow bin.
251  return const_iterator{GetOverflowBin() + 1};
252  }
253  ///\}
254 
255 private:
256  unsigned int fNBins; ///< Number of bins including under- and overflow.
257  std::string fTitle; ///< Title of this axis, used for graphics / text.
258  const bool fCanGrow; ///< Whether this axis can grow (and thus has no overflow bins).
259 };
260 
261 ///\name TAxisBase::const_iterator comparison operators
262 ///\{
263 
264 /// i < j
266  TAxisBase::const_iterator rhs) noexcept {
267  return lhs.fCursor < rhs.fCursor;
268 }
269 
270 /// i > j
272  TAxisBase::const_iterator rhs) noexcept {
273  return lhs.fCursor > rhs.fCursor;
274 }
275 
276 /// i <= j
278  TAxisBase::const_iterator rhs) noexcept {
279  return lhs.fCursor <= rhs.fCursor;
280 }
281 
282 /// i >= j
284  TAxisBase::const_iterator rhs) noexcept {
285  return lhs.fCursor >= rhs.fCursor;
286 }
287 
288 /// i == j
290  TAxisBase::const_iterator rhs) noexcept {
291  return lhs.fCursor == rhs.fCursor;
292 }
293 
294 /// i != j
296  TAxisBase::const_iterator rhs) noexcept {
297  return lhs.fCursor != rhs.fCursor;
298 }
299 ///\}
300 
301 
302 /**
303  Axis with equidistant bin borders. Defined by lower l and upper u limit and
304  the number of bins n. All bins have the same width (u-l)/n.
305 
306  This axis cannot grow; use `TAxisGrow` for that.
307  */
309 protected:
310  double fLow = 0.; ///< The lower limit of the axis
311  double fInvBinWidth = 0.; ///< The inverse of the bin width
312 
313  /// Determine the inverse bin width.
314  /// \param nbinsNoOver - number of bins without unter-/overflow
315  /// \param lowOrHigh - first axis boundary
316  /// \param lighOrLow - second axis boundary
317  static double GetInvBinWidth(int nbinsNoOver, double lowOrHigh, double highOrLow) {
318  return nbinsNoOver / std::abs(highOrLow - lowOrHigh);
319  }
320 
321  /// Initialize a TAxisEquidistant.
322  /// \param nbins - number of bins in the axis, excluding under- and overflow
323  /// bins.
324  /// \param low - the low axis range. Any coordinate below that is considered
325  /// as underflow. The first bin's lower edge is at this value.
326  /// \param high - the high axis range. Any coordinate above that is considered
327  /// as overflow. The last bin's higher edge is at this value.
328  explicit TAxisEquidistant(int nbinsNoOver, double low, double high, bool canGrow) noexcept:
329  TAxisBase(nbinsNoOver, canGrow), fLow(std::min(low, high)),
330  fInvBinWidth(GetInvBinWidth(nbinsNoOver, low, high)) { }
331 
332  /// Initialize a TAxisEquidistant.
333  /// \param[in] title - axis title used for graphics and text representation.
334  /// \param nbins - number of bins in the axis, excluding under- and overflow
335  /// bins.
336  /// \param low - the low axis range. Any coordinate below that is considered
337  /// as underflow. The first bin's lower edge is at this value.
338  /// \param high - the high axis range. Any coordinate above that is considered
339  /// as overflow. The last bin's higher edge is at this value.
340  explicit TAxisEquidistant(std::string_view title, int nbinsNoOver, double low,
341  double high, bool canGrow) noexcept:
342  TAxisBase(title, nbinsNoOver, canGrow), fLow(low),
343  fInvBinWidth(GetInvBinWidth(nbinsNoOver, low, high)) { }
344 
345 public:
346  TAxisEquidistant() = default;
347 
348  /// Initialize a TAxisEquidistant.
349  /// \param nbins - number of bins in the axis, excluding under- and overflow
350  /// bins.
351  /// \param low - the low axis range. Any coordinate below that is considered
352  /// as underflow. The first bin's lower edge is at this value.
353  /// \param high - the high axis range. Any coordinate above that is considered
354  /// as overflow. The last bin's higher edge is at this value.
355  /// \param canGrow - whether this axis can extend its range.
356  explicit TAxisEquidistant(int nbinsNoOver, double low, double high) noexcept:
357  TAxisEquidistant(nbinsNoOver, low, high, false /*canGrow*/) { }
358 
359  /// Initialize a TAxisEquidistant.
360  /// \param[in] title - axis title used for graphics and text representation.
361  /// \param nbins - number of bins in the axis, excluding under- and overflow
362  /// bins.
363  /// \param low - the low axis range. Any coordinate below that is considered
364  /// as underflow. The first bin's lower edge is at this value.
365  /// \param high - the high axis range. Any coordinate above that is considered
366  /// as overflow. The last bin's higher edge is at this value.
367  explicit TAxisEquidistant(std::string_view title, int nbinsNoOver, double low,
368  double high) noexcept:
369  TAxisEquidistant(title, nbinsNoOver, low, high, false /*canGrow*/) { }
370 
371  /// Find the bin index for the given coordinate.
372  /// \note Passing a bin border coordinate can either return the bin above or
373  /// below the bin border. I.e. don't do that for reliable results!
374  int FindBin(double x) const noexcept {
375  int rawbin = (x - fLow) * fInvBinWidth;
376  return AdjustOverflowBinNumber(rawbin);
377  }
378 
379  /// This axis cannot grow.
380  static bool CanGrow() noexcept { return false; }
381 
382  /// Get the low end of the axis range.
383  double GetMinimum() const noexcept { return fLow; }
384 
385  /// Get the high end of the axis range.
386  double GetMaximum() const noexcept {
387  return fLow + GetNBinsNoOver()/ fInvBinWidth;
388  }
389 
390  /// Get the width of the bins
391  double GetBinWidth() const noexcept { return 1. / fInvBinWidth; }
392 
393  /// Get the inverse of the width of the bins
394  double GetInverseBinWidth() const noexcept { return fInvBinWidth; }
395 
396  /// Get the bin center for the given bin index.
397  /// For the bin == 1 (the first bin) of 2 bins for an axis (0., 1.), this
398  /// returns 0.25.
399  double GetBinCenter(int bin) const noexcept {
400  return fLow + (bin - 0.5) / fInvBinWidth;
401  }
402 
403  /// Get the low bin border for the given bin index.
404  /// For the bin == 1 (the first bin) of 2 bins for an axis (0., 1.), this
405  /// returns 0.
406  double GetBinFrom(int bin) const noexcept {
407  return fLow + (bin - 1) / fInvBinWidth;
408  }
409 
410  /// Get the high bin border for the given bin index.
411  /// For the bin == 1 (the first bin) of 2 bins for an axis (0., 1.), this
412  /// returns 0.5.
413  double GetBinTo(int bin) const noexcept {
414  return GetBinFrom(bin + 1);
415  }
416 
417  int GetBinIndexForLowEdge(double x) const noexcept;
418 };
419 
420 /// Equality-compare two TAxisEquidistant.
421 inline
422 bool operator==(const TAxisEquidistant &lhs,
423  const TAxisEquidistant &rhs) noexcept {
424  return lhs.GetNBins() == rhs.GetNBins()
425  && lhs.GetMinimum() == rhs.GetMinimum()
426  && lhs.GetInverseBinWidth() == rhs.GetInverseBinWidth();
427 }
428 
429 
430 /** An axis that can extend its range, keeping the number of its bins unchanged.
431  The axis is constructed with an initial range. Apart from its ability to
432  grow, this axis behaves like a TAxisEquidistant.
433  */
435 public:
436  /// Initialize a TAxisGrow.
437  /// \param nbins - number of bins in the axis, excluding under- and overflow
438  /// bins. This value is fixed over the lifetime of the object.
439  /// \param low - the initial value for the low axis range. Any coordinate
440  /// below that is considered as underflow. To trigger the growing of the
441  /// axis call Grow().
442  /// \param high - the initial value for the high axis range. Any coordinate
443  /// above that is considered as overflow. To trigger the growing of the
444  /// axis call Grow()
445  explicit TAxisGrow(std::string_view title, int nbins, double low,
446  double high) noexcept:
447  TAxisEquidistant(title, nbins, low, high, CanGrow()) { }
448 
449  /// Initialize a TAxisGrow.
450  /// \param[in] title - axis title used for graphics and text representation.
451  /// \param nbins - number of bins in the axis, excluding under- and overflow
452  /// bins. This value is fixed over the lifetime of the object.
453  /// \param low - the initial value for the low axis range. Any coordinate
454  /// below that is considered as underflow. To trigger the growing of the
455  /// axis call Grow().
456  /// \param high - the initial value for the high axis range. Any coordinate
457  /// above that is considered as overflow. To trigger the growing of the
458  /// axis call Grow()
459  explicit TAxisGrow(int nbins, double low, double high) noexcept:
460  TAxisEquidistant(nbins, low, high, CanGrow()) { }
461 
462  /// Grow this axis to make the "virtual bin" toBin in-range. This keeps the
463  /// non-affected axis limit unchanged, and extends the other axis limit such
464  /// that a number of consecutive bins are merged.
465  ///
466  /// Example, assuming an initial TAxisGrow with 10 bins from 0. to 1.:
467  /// - `Grow(0)`: that (virtual) bin spans from -0.1 to 0. To include it
468  /// in the axis range, the lower limit must be shifted. The minimal number
469  /// of bins that can be merged is 2, thus the new axis will span from
470  /// -1. to 1.
471  /// - `Grow(-1)`: that (virtual) bin spans from -0.2 to 0.1. To include it
472  /// in the axis range, the lower limit must be shifted. The minimal number
473  /// of bins that can be merged is 2, thus the new axis will span from
474  /// -1. to 1.
475  /// - `Grow(50)`: that (virtual) bin spans from 4.9 to 5.0. To include it
476  /// in the axis range, the higher limit must be shifted. Five bins need to
477  /// be merged, making the new axis range 0. to 5.0.
478  ///
479  /// \param toBin - the "virtual" bin number, as if the axis had an infinite
480  /// number of bins with the current bin width. For instance, for an axis
481  /// with ten bins in the range 0. to 1., the coordinate 2.05 has the virtual
482  /// bin index 20.
483  /// \return Returns the number of bins that were merged to reach the value.
484  /// A value of 1 means that no bins were merged (toBin was in the original
485  /// axis range).
486  int Grow(int toBin);
487 
488  /// This axis kind can increase its range.
489  bool CanGrow() const { return true; }
490 };
491 
492 
493 /**
494  An axis with non-equidistant bins (also known as "variable binning"). It is
495  defined by an array of bin borders - one more than the number of
496  (non-overflow-) bins it has! As an example, an axis with two bin needs three
497  bin borders:
498  - lower edge of the first bin;
499  - higher edge of the first bin, identical to the lower edge of the second
500  bin;
501  - higher edge of the second bin
502 
503  This axis cannot grow; the size of new bins would not be well defined.
504  */
505 class TAxisIrregular: public TAxisBase {
506 private:
507  /// Bin borders, one more than the number of non-overflow bins.
508  std::vector<double> fBinBorders;
509 
510 public:
511  TAxisIrregular() = default;
512 
513  /// Construct a TAxisIrregular from a vector of bin borders.
514  /// \note The bin borders must be sorted in increasing order!
515  explicit TAxisIrregular(const std::vector<double> &binborders):
516  TAxisBase(binborders.size() - 1, CanGrow()), fBinBorders(binborders) {
517 #ifdef R__DO_RANGE_CHECKS
518  if (!std::is_sorted(fBinBorders.begin(), fBinBorders.end()))
519  R__ERROR_HERE("HIST") << "Bin borders must be sorted!";
520 #endif // R__DO_RANGE_CHECKS
521  }
522 
523  /// Construct a TAxisIrregular from a vector of bin borders.
524  /// \note The bin borders must be sorted in increasing order!
525  /// Faster, noexcept version taking an rvalue of binborders. The compiler will
526  /// know when it can take this one.
527  explicit TAxisIrregular(std::vector<double> &&binborders) noexcept:
528  TAxisBase(binborders.size() - 1, CanGrow()), fBinBorders(std::move(binborders)) {
529 #ifdef R__DO_RANGE_CHECKS
530  if (!std::is_sorted(fBinBorders.begin(), fBinBorders.end()))
531  R__ERROR_HERE("HIST") << "Bin borders must be sorted!";
532 #endif // R__DO_RANGE_CHECKS
533  }
534 
535  /// Construct a TAxisIrregular from a vector of bin borders.
536  /// \note The bin borders must be sorted in increasing order!
537  explicit TAxisIrregular(std::string_view title, const std::vector<double> &binborders):
538  TAxisBase(title, binborders.size() - 1, CanGrow()), fBinBorders(binborders) {
539 #ifdef R__DO_RANGE_CHECKS
540  if (!std::is_sorted(fBinBorders.begin(), fBinBorders.end()))
541  R__ERROR_HERE("HIST") << "Bin borders must be sorted!";
542 #endif // R__DO_RANGE_CHECKS
543  }
544 
545  /// Construct a TAxisIrregular from a vector of bin borders.
546  /// \note The bin borders must be sorted in increasing order!
547  /// Faster, noexcept version taking an rvalue of binborders. The compiler will
548  /// know when it can take this one.
549  explicit TAxisIrregular(std::string_view title, std::vector<double> &&binborders) noexcept:
550  TAxisBase(title, binborders.size() - 1, CanGrow()), fBinBorders(std::move(binborders)) {
551 #ifdef R__DO_RANGE_CHECKS
552  if (!std::is_sorted(fBinBorders.begin(), fBinBorders.end()))
553  R__ERROR_HERE("HIST") << "Bin borders must be sorted!";
554 #endif // R__DO_RANGE_CHECKS
555  }
556 
557  /// Find the bin index corresponding to coordinate x. If the coordinate is
558  /// below the axis range, return 0. If it is above, return N + 1 for an axis
559  /// with N non-overflow bins.
560  int FindBin(double x) const noexcept {
561  const auto bBegin = fBinBorders.begin();
562  const auto bEnd = fBinBorders.end();
563  auto iNotLess = std::lower_bound(bBegin, bEnd, x);
564  int rawbin = iNotLess - bBegin;
565  // if x is < bBegin then iNotLess == bBegin thus rawbin == 0:
566  // we don't want not-less but just-below, thus:
567  rawbin -= 1;
568  // No need for AdjustOverflowBinNumber(rawbin) here; lower_bound() - 1 is
569  // the answer.
570  return rawbin;
571  }
572 
573  /// Get the bin center of the bin with the given index.
574  ///
575  /// For the bin at index 0 (i.e. the underflow bin), a bin center of
576  /// `std::numeric_limits<double>::min()` is returned, i.e. the minimum value
577  /// that can be held in a double.
578  /// Similarly, for the bin at index N + 1 (i.e. the overflow bin), a bin
579  /// center of `std::numeric_limits<double>::max()` is returned, i.e. the
580  /// maximum value that can be held in a double.
581  double GetBinCenter(int bin) const noexcept {
582  if (IsUnderflowBin(bin))
583  return std::numeric_limits<double>::min();
584  if (IsOverflowBin(bin))
585  return std::numeric_limits<double>::max();
586  return 0.5 * (fBinBorders[bin - 1] + fBinBorders[bin]);
587  }
588 
589  /// Get the lower bin border for a given bin index.
590  ///
591  /// For the bin at index 0 (i.e. the underflow bin), a lower bin border of
592  /// `std::numeric_limits<double>::min()` is returned, i.e. the minimum value
593  /// that can be held in a double.
594  double GetBinFrom(int bin) const noexcept {
595  if (IsUnderflowBin(bin))
596  return std::numeric_limits<double>::min();
597  // bin 0 is underflow;
598  // bin 1 starts at fBinBorders[0]
599  return fBinBorders[bin - 1];
600  }
601 
602  /// Get the higher bin border for a given bin index.
603  ///
604  /// For the bin at index N + 1 (i.e. the overflow bin), a bin border of
605  /// `std::numeric_limits<double>::max()` is returned, i.e. the maximum value
606  /// that can be held in a double.
607  double GetBinTo(int bin) const noexcept {
608  if (IsOverflowBin(bin))
609  return std::numeric_limits<double>::max();
610  return GetBinFrom(bin + 1);
611  }
612 
613  /// This axis cannot be extended.
614  static bool CanGrow() noexcept { return false; }
615 
616  /// Access to the bin borders used by this axis.
617  const std::vector<double> &GetBinBorders() const noexcept { return fBinBorders; }
618 };
619 
620 
621 /**
622  \class TAxisLabels
623  A TAxisGrow that has a label assigned to each bin and a bin width of 1.
624 
625  While filling still works through coordinates (i.e. arrays of doubles),
626  TAxisLabels allows to convert a string to a bin number or the bin's coordinate
627  center. The number of labels and the number of bins reported by TAxisGrow might
628  differ: the TAxisGrow will only grow when seeing a Fill(), while the TAxisLabels
629  will add a new label whenever `GetBinCenter()` is called.
630 
631  Implementation details:
632  Filling happens often; GetBinCenter() needs to be fast. Thus the unordered_map.
633  The painter needs the reverse: it wants the label for bin 0, bin 1 etc. The axis
634  should only store the bin labels once; referencing them is (due to re-allocation,
635  hashing etc) non-trivial. So instead, build a vector<string_view> for the few
636  times the axis needs to be painted.
637  */
638 class TAxisLabels: public TAxisGrow {
639 private:
640  /// Map of label (view on `fLabels`'s elements) to bin index
641  std::unordered_map<std::string, int /*bin number*/> fLabelsIndex;
642 
643 public:
644  /// Construct a TAxisLables from a `vector` of `string_view`s
645  explicit TAxisLabels(const std::vector<std::string_view> &labels):
646  TAxisGrow(labels.size(), 0., static_cast<double>(labels.size())) {
647  for (size_t i = 0, n = labels.size(); i < n; ++i)
648  fLabelsIndex[std::string(labels[i])] = i;
649  }
650 
651  /// Construct a TAxisLables from a `vector` of `string`s
652  explicit TAxisLabels(const std::vector<std::string> &labels):
653  TAxisGrow(labels.size(), 0., static_cast<double>(labels.size())) {
654  for (size_t i = 0, n = labels.size(); i < n; ++i)
655  fLabelsIndex[labels[i]] = i;
656  }
657 
658  /// Construct a TAxisLables from a `vector` of `string_view`s, with title.
659  explicit TAxisLabels(std::string_view title, const std::vector<std::string_view> &labels):
660  TAxisGrow(title, labels.size(), 0., static_cast<double>(labels.size())) {
661  for (size_t i = 0, n = labels.size(); i < n; ++i)
662  fLabelsIndex[std::string(labels[i])] = i;
663  }
664 
665  /// Construct a TAxisLables from a `vector` of `string`s, with title.
666  explicit TAxisLabels(std::string_view title, const std::vector<std::string> &labels):
667  TAxisGrow(title, labels.size(), 0., static_cast<double>(labels.size())) {
668  for (size_t i = 0, n = labels.size(); i < n; ++i)
669  fLabelsIndex[labels[i]] = i;
670  }
671 
672  /// Get the bin index with label.
673  int GetBinIndex(const std::string &label) {
674  auto insertResult = fLabelsIndex.insert({label, -1});
675  if (insertResult.second) {
676  // we have created a new label
677  int idx = fLabelsIndex.size() - 1;
678  insertResult.first->second = idx;
679  return idx;
680  }
681  return insertResult.first->second;
682  }
683 
684  /// Get the center of the bin with label.
685  double GetBinCenter(const std::string &label) {
686  return GetBinIndex(label) - 0.5; // bin *center*
687  }
688 
689  /// Build a vector of labels. The position in the vector defines the label's bin.
690  std::vector <std::string_view> GetBinLabels() const {
691  std::vector <std::string_view> vec(fLabelsIndex.size());
692  for (const auto &kv: fLabelsIndex)
693  vec.at(kv.second) = kv.first;
694  return vec;
695  }
696 };
697 
698 
699 /**
700  \class TAxisConfig
701  Objects used to configure the different axis types. It can store the
702  properties of all possible axis types, together with the type of the axis.
703 
704  TODO: that's what a variant will be invented for!
705  */
706 class TAxisConfig: public TAxisBase {
707 public:
708  enum EKind {
709  kEquidistant, ///< represents a TAxisEquidistant
710  kGrow, ///< represents a TAxisGrow
711  kIrregular, ///< represents a TAxisIrregular
712  kLabels, ///< represents a TAxisLabels
713  kNumKinds
714  };
715 
716 private:
717  EKind fKind; ///< The kind of axis represented by this configuration
718  std::vector<double> fBinBorders; ///< Bin borders of the TAxisIrregular
719  std::vector <std::string> fLabels; ///< Bin labels for a TAxisLabels
720 
721  /// Represents a `TAxisEquidistant` with `nbins` from `from` to `to`, and
722  /// axis title.
723  explicit TAxisConfig(std::string_view title, int nbins, double from, double to,
724  EKind kind):
725  TAxisBase(title, nbins, kind == kGrow), fKind(kind), fBinBorders(2)
726  {
727  if (from > to)
728  std::swap(to, from);
729 
730  fBinBorders[0] = from;
731  fBinBorders[1] = to;
732  }
733 
734 public:
735  /// Tag type signalling that an axis should be able to grow; used for calling
736  /// the appropriate constructor.
737  struct Grow_t {
738  };
739  /// Tag signalling that an axis should be able to grow; used for calling the
740  /// appropriate constructor like so:
741  /// TAxisConfig ac(TAxisConfig::Grow, 10, 0., 1.);
742  constexpr static const Grow_t Grow{};
743 
744  /// Represents a `TAxisEquidistant` with `nbins` from `from` to `to`, and
745  /// axis title.
746  TAxisConfig(std::string_view title, int nbins, double from, double to):
747  TAxisConfig(title, nbins, from, to, kEquidistant) {}
748 
749  /// Represents a `TAxisEquidistant` with `nbins` from `from` to `to`.
750  TAxisConfig(int nbins, double from, double to):
751  TAxisConfig("", nbins, from, to, kEquidistant) {}
752 
753  /// Represents a `TAxisGrow` with `nbins` from `from` to `to`, and axis title.
754  TAxisConfig(std::string_view title, Grow_t, int nbins, double from, double to):
755  TAxisConfig(title, nbins, from, to, kGrow) {}
756 
757  /// Represents a `TAxisGrow` with `nbins` from `from` to `to`.
758  TAxisConfig(Grow_t, int nbins, double from, double to):
759  TAxisConfig("", nbins, from, to, kGrow) {}
760 
761 
762  /// Represents a `TAxisIrregular` with `binborders`.
763  TAxisConfig(const std::vector<double> &binborders):
764  TAxisBase(binborders.size() - 1, false /*canGrow*/), fKind(kIrregular),
765  fBinBorders(binborders) { }
766 
767  /// Represents a `TAxisIrregular` with `binborders` and title.
768  TAxisConfig(std::string_view title, const std::vector<double> &binborders):
769  TAxisBase(title, binborders.size() - 1, false /*canGrow*/), fKind(kIrregular),
770  fBinBorders(binborders) { }
771 
772  /// Represents a `TAxisIrregular` with `binborders`.
773  TAxisConfig(std::vector<double> &&binborders) noexcept:
774  TAxisBase(binborders.size() - 1, false /*canGrow*/), fKind(kIrregular),
775  fBinBorders(std::move(binborders)) { }
776 
777  /// Represents a `TAxisIrregular` with `binborders`.
778  TAxisConfig(std::string_view title, std::vector<double> &&binborders) noexcept:
779  TAxisBase(title, binborders.size() - 1, false /*canGrow*/), fKind(kIrregular),
780  fBinBorders(std::move(binborders)) { }
781 
782  /// Represents a `TAxisLabels` with `labels`.
783  TAxisConfig(const std::vector<std::string_view> &labels):
784  TAxisBase(labels.size(), true /*canGrow*/),
785  fKind(kLabels),
786  fLabels(labels.begin(), labels.end()) { }
787 
788  /// Represents a `TAxisLabels` with `labels` and title.
789  TAxisConfig(std::string_view title, const std::vector<std::string_view> &labels):
790  TAxisBase(title, labels.size(), true /*canGrow*/),
791  fKind(kLabels),
792  fLabels(labels.begin(), labels.end()) { }
793 
794  /// Represents a `TAxisLabels` with `labels`.
795  TAxisConfig(std::vector<std::string> &&labels):
796  TAxisBase(labels.size(), true /*canGrow*/),
797  fKind(kLabels),
798  fLabels(labels.begin(), labels.end()) { }
799 
800  /// Represents a `TAxisLabels` with `labels` and title.
801  TAxisConfig(std::string_view title, std::vector<std::string> &&labels):
802  TAxisBase(title, labels.size(), true /*canGrow*/),
803  fKind(kLabels),
804  fLabels(labels.begin(), labels.end()) { }
805 
806  /// \name Axis normalization
807  ///\{
808 
809  /// Build a TAxisConfig from a TAxisEquidistant.
810  explicit TAxisConfig(const TAxisEquidistant &ax):
811  TAxisBase(ax), fKind(kEquidistant),
812  fBinBorders{{ax.GetMinimum(), ax.GetMaximum()}} { }
813 
814  /// Build a TAxisConfig from a TAxisGrow.
815  explicit TAxisConfig(const TAxisGrow &ax):
816  TAxisBase(ax), fKind(kGrow),
817  fBinBorders{{ax.GetMinimum(), ax.GetMaximum()}} { }
818 
819  /// Build a TAxisConfig from a TAxisIrregular.
820  explicit TAxisConfig(const TAxisIrregular &ax):
821  TAxisBase(ax), fKind(kIrregular), fBinBorders(ax.GetBinBorders()) { }
822 
823  /// Build a TAxisConfig from a TAxisLabels.
824  explicit TAxisConfig(const TAxisLabels &ax):
825  TAxisBase(ax), fKind(kLabels) {
826  auto labels = ax.GetBinLabels();
827  for (auto &&lab: labels)
828  fLabels.emplace_back(std::string(lab));
829  }
830  ///\}
831 
832  /// Get the axis kind represented by this `TAxisConfig`.
833  EKind GetKind() const noexcept { return fKind; }
834 
835  /// Get the bin borders; non-empty if the GetKind() == kIrregular.
836  const std::vector<double> &GetBinBorders() const noexcept { return fBinBorders; }
837 
838  /// Get the bin labels; non-empty if the GetKind() == kLabels.
839  const std::vector <std::string> &GetBinLabels() const noexcept { return fLabels; }
840 };
841 
842 
843 namespace Internal {
844 
845 /// Converts a TAxisConfig of whatever kind to the corresponding TAxisBase-derived
846 /// object.
847 template<TAxisConfig::EKind>
848 struct AxisConfigToType; // Only specializations are defined.
849 
850 template<>
851 struct AxisConfigToType<TAxisConfig::kEquidistant> {
853 
854  Axis_t operator()(const TAxisConfig& cfg) noexcept {
855  return TAxisEquidistant(cfg.GetTitle(), cfg.GetNBinsNoOver(),
856  cfg.GetBinBorders()[0], cfg.GetBinBorders()[1]);
857  }
858 };
859 
860 template<>
862  using Axis_t = TAxisGrow;
863 
864  Axis_t operator()(const TAxisConfig& cfg) noexcept {
865  return TAxisGrow(cfg.GetTitle(), cfg.GetNBinsNoOver(),
866  cfg.GetBinBorders()[0], cfg.GetBinBorders()[1]);
867  }
868 };
869 template<>
870 struct AxisConfigToType<TAxisConfig::kIrregular> {
872 
874  return TAxisIrregular(cfg.GetTitle(), cfg.GetBinBorders());
875  }
876 };
877 
878 template<>
879 struct AxisConfigToType<TAxisConfig::kLabels> {
881 
883  return TAxisLabels(cfg.GetTitle(), cfg.GetBinLabels());
884  }
885 };
886 
887 } // namespace Internal
888 
889 
890 /// Common view on a TAxis, no matter what its kind.
891 class TAxisView {
892  /// View on a `TAxisEquidistant`, `TAxisGrow` or `TAxisLabel`.
893  const TAxisEquidistant *fEqui = nullptr;
894  /// View on a `TAxisIrregular`.
895  const TAxisIrregular *fIrr = nullptr;
896 
897 public:
898  TAxisView() = default;
899 
900  /// Construct a view on a `TAxisEquidistant`, `TAxisGrow` or `TAxisLabel`.
901  TAxisView(const TAxisEquidistant &equi): fEqui(&equi) { }
902 
903  /// Construct a view on a `TAxisIrregular`.
904  TAxisView(const TAxisIrregular &irr): fIrr(&irr) { }
905 
906  const std::string& GetTitle() const {
907  return fEqui ? fEqui->GetTitle() : fIrr->GetTitle();
908  }
909 
910  /// Find the bin containing coordinate `x`. Forwards to the underlying axis.
911  int FindBin(double x) const noexcept {
912  if (fEqui)
913  return fEqui->FindBin(x);
914  return fIrr->FindBin(x);
915  }
916 
917  /// Get the number of bins. Forwards to the underlying axis.
918  int GetNBins() const noexcept {
919  if (fEqui)
920  return fEqui->GetNBins();
921  return fIrr->GetNBins();
922  }
923 
924  /// Get the lower axis limit.
925  double GetFrom() const { return GetBinFrom(1); }
926  /// Get the upper axis limit.
927  double GetTo() const { return GetBinTo(GetNBins() - 2); }
928 
929  /// Get the bin center of bin index `i`. Forwards to the underlying axis.
930  double GetBinCenter(int i) const noexcept {
931  if (fEqui)
932  return fEqui->GetBinCenter(i);
933  return fIrr->GetBinCenter(i);
934  }
935 
936  /// Get the minimal coordinate of bin index `i`. Forwards to the underlying axis.
937  double GetBinFrom(int i) const noexcept {
938  if (fEqui)
939  return fEqui->GetBinFrom(i);
940  return fIrr->GetBinFrom(i);
941  }
942 
943  /// Get the maximal coordinate of bin index `i`. Forwards to the underlying axis.
944  double GetBinTo(int i) const noexcept {
945  if (fEqui)
946  return fEqui->GetBinTo(i);
947  return fIrr->GetBinTo(i);
948  }
949 
950  /// Get the axis as a TAxisEquidistant; returns nullptr if it's a TAxisIrregular.
951  const TAxisEquidistant* GetAsEquidistant() const { return fEqui; }
952  /// Get the axis as a TAxisIrregular; returns nullptr if it's a TAxisEquidistant.
953  const TAxisIrregular* GetAsIrregular() const { return fIrr; }
954 };
955 
956 ///\name Axis Compatibility
957 ///\{
958 enum class EAxisCompatibility {
959  kIdentical, ///< Source and target axes are identical
960 
961  kContains, ///< The source is a subset of bins of the target axis
962 
963  /// The bins of the source axis have finer granularity, but the bin borders
964  /// are compatible. Example:
965  /// source: 0., 1., 2., 3., 4., 5., 6.; target: 0., 2., 5., 6.
966  /// Note that this is *not* a symmetrical property: only one of
967  /// CanMerge(source, target), CanMap(target, source) can return kContains.
968  kSampling,
969 
970  /// The source axis and target axis have different binning. Example:
971  /// source: 0., 1., 2., 3., 4., target: 0., 0.1, 0.2, 0.3, 0.4
973 };
974 
976  TAxisEquidistant &source) noexcept;
977 ///\}
978 
979 
980 
981 } // namespace Experimental
982 } // namespace ROOT
983 
984 #endif
double GetFrom() const
Get the lower axis limit.
Definition: TAxis.hxx:925
TAxisView(const TAxisEquidistant &equi)
Construct a view on a TAxisEquidistant, TAxisGrow or TAxisLabel.
Definition: TAxis.hxx:901
TAxisBase(std::string_view title, int nbinsNoOver, bool canGrow) noexcept
Construct a TAxisBase.
Definition: TAxis.hxx:190
TAxisConfig(std::vector< double > &&binborders) noexcept
Represents a TAxisIrregular with binborders.
Definition: TAxis.hxx:773
const_iterator operator+(int d) noexcept
Definition: TAxis.hxx:142
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
TAxisLabels(std::string_view title, const std::vector< std::string > &labels)
Construct a TAxisLables from a vector of strings, with title.
Definition: TAxis.hxx:666
TAxisBase & operator=(const TAxisBase &)=default
const_iterator begin() const noexcept
Get a const_iterator pointing to the first non-underflow bin.
Definition: TAxis.hxx:236
double GetMinimum() const noexcept
Get the low end of the axis range.
Definition: TAxis.hxx:383
TAxisConfig(const TAxisEquidistant &ax)
Build a TAxisConfig from a TAxisEquidistant.
Definition: TAxis.hxx:810
double GetBinCenter(int i) const noexcept
Get the bin center of bin index i. Forwards to the underlying axis.
Definition: TAxis.hxx:930
TAxisConfig(const std::vector< double > &binborders)
Represents a TAxisIrregular with binborders.
Definition: TAxis.hxx:763
const_iterator operator++(int) noexcept
i++
Definition: TAxis.hxx:116
void swap(TDirectoryEntry &e1, TDirectoryEntry &e2) noexcept
double GetBinTo(int bin) const noexcept
Get the higher bin border for a given bin index.
Definition: TAxis.hxx:607
TAxisLabels(const std::vector< std::string > &labels)
Construct a TAxisLables from a vector of strings.
Definition: TAxis.hxx:652
const std::vector< double > & GetBinBorders() const noexcept
Get the bin borders; non-empty if the GetKind() == kIrregular.
Definition: TAxis.hxx:836
const_iterator & operator--() noexcept
–i
Definition: TAxis.hxx:109
TAxisConfig(const TAxisLabels &ax)
Build a TAxisConfig from a TAxisLabels.
Definition: TAxis.hxx:824
double GetInverseBinWidth() const noexcept
Get the inverse of the width of the bins.
Definition: TAxis.hxx:394
TAxisEquidistant(std::string_view title, int nbinsNoOver, double low, double high, bool canGrow) noexcept
Initialize a TAxisEquidistant.
Definition: TAxis.hxx:340
double GetBinTo(int bin) const noexcept
Get the high bin border for the given bin index.
Definition: TAxis.hxx:413
int FindBin(double x) const noexcept
Find the bin containing coordinate x. Forwards to the underlying axis.
Definition: TAxis.hxx:911
Common view on a TAxis, no matter what its kind.
Definition: TAxis.hxx:891
int GetNBinsNoOver() const noexcept
Get the number of bins, excluding under- and overflow.
Definition: TAxis.hxx:196
Axis with equidistant bin borders.
Definition: TAxis.hxx:308
int nbins[3]
double GetBinFrom(int bin) const noexcept
Get the lower bin border for a given bin index.
Definition: TAxis.hxx:594
double GetTo() const
Get the upper axis limit.
Definition: TAxis.hxx:927
TAxisConfig(Grow_t, int nbins, double from, double to)
Represents a TAxisGrow with nbins from from to to.
Definition: TAxis.hxx:758
EFindStatus
Status of FindBin(x)
Definition: TAxis.hxx:43
std::vector< double > fBinBorders
Bin borders of the TAxisIrregular.
Definition: TAxis.hxx:718
const int * operator*() const noexcept
Definition: TAxis.hxx:156
int AdjustOverflowBinNumber(int rawbin) const
Given rawbin (<0 for underflow, >= GetNBinsNoOver() for overflow), determine the actual bin number ta...
Definition: TAxis.hxx:72
int FindBin(double x) const noexcept
Find the bin index corresponding to coordinate x.
Definition: TAxis.hxx:560
const_iterator end_with_overflow() const noexcept
Get a const_iterator pointing right beyond the overflow bin.
Definition: TAxis.hxx:250
The bins of the source axis have finer granularity, but the bin borders are compatible.
Double_t x[n]
Definition: legend1.C:17
std::vector< double > fBinBorders
Bin borders, one more than the number of non-overflow bins.
Definition: TAxis.hxx:508
static constexpr const int kNOverflowBins[4]
Extra bins for each EAxisOverflow value.
Definition: TAxis.hxx:174
double GetBinFrom(int i) const noexcept
Get the minimal coordinate of bin index i. Forwards to the underlying axis.
Definition: TAxis.hxx:937
represents a TAxisEquidistant
Definition: TAxis.hxx:709
const_iterator begin_with_underflow() const noexcept
Get a const_iterator pointing the underflow bin.
Definition: TAxis.hxx:239
represents a TAxisGrow
Definition: TAxis.hxx:710
int GetUnderflowBin() const noexcept
Get the bin index for the underflow bin.
Definition: TAxis.hxx:214
const std::vector< double > & GetBinBorders() const noexcept
Access to the bin borders used by this axis.
Definition: TAxis.hxx:617
const TAxisIrregular * GetAsIrregular() const
Get the axis as a TAxisIrregular; returns nullptr if it&#39;s a TAxisEquidistant.
Definition: TAxis.hxx:953
TAxisEquidistant(int nbinsNoOver, double low, double high) noexcept
Initialize a TAxisEquidistant.
Definition: TAxis.hxx:356
An axis that can extend its range, keeping the number of its bins unchanged.
Definition: TAxis.hxx:434
EAxisCompatibility CanMap(TAxisEquidistant &target, TAxisEquidistant &source) noexcept
Whether (and how) the source axis can be merged into the target axis.
Definition: TAxis.cxx:49
double GetBinFrom(int bin) const noexcept
Get the low bin border for the given bin index.
Definition: TAxis.hxx:406
TAxisConfig(const std::vector< std::string_view > &labels)
Represents a TAxisLabels with labels.
Definition: TAxis.hxx:783
bool operator>=(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i >= j
Definition: TAxis.hxx:283
TAxisIrregular(std::string_view title, std::vector< double > &&binborders) noexcept
Construct a TAxisIrregular from a vector of bin borders.
Definition: TAxis.hxx:549
double GetBinCenter(const std::string &label)
Get the center of the bin with label.
Definition: TAxis.hxx:685
TAxisBase(int nbinsNoOver, bool canGrow) noexcept
Construct a TAxisBase.
Definition: TAxis.hxx:181
bool operator<(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i < j
Definition: TAxis.hxx:265
const std::vector< std::string > & GetBinLabels() const noexcept
Get the bin labels; non-empty if the GetKind() == kLabels.
Definition: TAxis.hxx:839
EKind fKind
The kind of axis represented by this configuration.
Definition: TAxis.hxx:717
TAxisConfig(std::string_view title, int nbins, double from, double to)
Represents a TAxisEquidistant with nbins from from to to, and axis title.
Definition: TAxis.hxx:746
Objects used to configure the different axis types.
Definition: TAxis.hxx:706
unsigned int fNBins
Number of bins including under- and overflow.
Definition: TAxis.hxx:256
TAxisConfig(std::string_view title, const std::vector< double > &binborders)
Represents a TAxisIrregular with binborders and title.
Definition: TAxis.hxx:768
TAxisGrow(std::string_view title, int nbins, double low, double high) noexcept
Initialize a TAxisGrow.
Definition: TAxis.hxx:445
Random const_iterator through bins.
Definition: TAxis.hxx:89
TAxisIrregular(std::string_view title, const std::vector< double > &binborders)
Construct a TAxisIrregular from a vector of bin borders.
Definition: TAxis.hxx:537
double GetBinCenter(int bin) const noexcept
Get the bin center for the given bin index.
Definition: TAxis.hxx:399
TAxisConfig(int nbins, double from, double to)
Represents a TAxisEquidistant with nbins from from to to.
Definition: TAxis.hxx:750
int GetNOverflowBins() const noexcept
Get the number of over- and underflow bins: 0 for growable axes, 2 otherwise.
Definition: TAxis.hxx:206
const_iterator & operator++() noexcept
++i
Definition: TAxis.hxx:102
const_iterator operator--(int) noexcept
Definition: TAxis.hxx:123
represents a TAxisIrregular
Definition: TAxis.hxx:711
TAxisConfig(std::string_view title, int nbins, double from, double to, EKind kind)
Represents a TAxisEquidistant with nbins from from to to, and axis title.
Definition: TAxis.hxx:723
int GetBinIndex(const std::string &label)
Get the bin index with label.
Definition: TAxis.hxx:673
Tag type signalling that an axis should be able to grow; used for calling the appropriate constructor...
Definition: TAxis.hxx:737
static constexpr const int kIgnoreBin
FindBin() returns this bin to signal that the bin number is invalid.
Definition: TAxis.hxx:171
TAxisConfig(std::vector< std::string > &&labels)
Represents a TAxisLabels with labels.
Definition: TAxis.hxx:795
bool operator==(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i == j
Definition: TAxis.hxx:289
int GetNBins() const noexcept
Get the number of bins, including under- and overflow.
Definition: TAxis.hxx:201
int GetOverflowBin() const noexcept
Get the bin index for the underflow bin (or the next bin outside range if CanGrow()).
Definition: TAxis.hxx:218
std::vector< std::string_view > GetBinLabels() const
Build a vector of labels. The position in the vector defines the label&#39;s bin.
Definition: TAxis.hxx:690
bool operator>(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i > j
Definition: TAxis.hxx:271
TAxisEquidistant(int nbinsNoOver, double low, double high, bool canGrow) noexcept
Initialize a TAxisEquidistant.
Definition: TAxis.hxx:328
TAxisConfig(std::string_view title, std::vector< double > &&binborders) noexcept
Represents a TAxisIrregular with binborders.
Definition: TAxis.hxx:778
std::string fTitle
Title of this axis, used for graphics / text.
Definition: TAxis.hxx:257
TAxisGrow(int nbins, double low, double high) noexcept
Initialize a TAxisGrow.
Definition: TAxis.hxx:459
bool CanGrow() const
This axis kind can increase its range.
Definition: TAxis.hxx:489
const_iterator operator-(int d) noexcept
Definition: TAxis.hxx:149
An axis with non-equidistant bins (also known as "variable binning").
Definition: TAxis.hxx:505
TAxisView(const TAxisIrregular &irr)
Construct a view on a TAxisIrregular.
Definition: TAxis.hxx:904
bool IsUnderflowBin(int bin) const noexcept
Whether the bin index is referencing a bin lower than the axis range.
Definition: TAxis.hxx:223
bool operator!=(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i != j
Definition: TAxis.hxx:295
TAxisEquidistant(std::string_view title, int nbinsNoOver, double low, double high) noexcept
Initialize a TAxisEquidistant.
Definition: TAxis.hxx:367
const TAxisEquidistant * GetAsEquidistant() const
Get the axis as a TAxisEquidistant; returns nullptr if it&#39;s a TAxisIrregular.
Definition: TAxis.hxx:951
TAxisBase()
Default construct a TAxisBase (for use by derived classes for I/O)
Definition: TAxis.hxx:60
double GetBinTo(int i) const noexcept
Get the maximal coordinate of bin index i. Forwards to the underlying axis.
Definition: TAxis.hxx:944
represents a TAxisLabels
Definition: TAxis.hxx:712
static bool CanGrow() noexcept
This axis cannot be extended.
Definition: TAxis.hxx:614
EKind GetKind() const noexcept
Get the axis kind represented by this TAxisConfig.
Definition: TAxis.hxx:833
static double GetInvBinWidth(int nbinsNoOver, double lowOrHigh, double highOrLow)
Determine the inverse bin width.
Definition: TAxis.hxx:317
The source is a subset of bins of the target axis.
TAxisLabels(const std::vector< std::string_view > &labels)
Construct a TAxisLables from a vector of string_views.
Definition: TAxis.hxx:645
const_iterator(int cursor) noexcept
Initialize a const_iterator with its position.
Definition: TAxis.hxx:99
TAxisConfig(const TAxisIrregular &ax)
Build a TAxisConfig from a TAxisIrregular.
Definition: TAxis.hxx:820
const std::string & GetTitle() const
Definition: TAxis.hxx:193
const_iterator end() const noexcept
Get a const_iterator pointing right beyond the last non-overflow bin (i.e.
Definition: TAxis.hxx:245
Converts a TAxisConfig of whatever kind to the corresponding TAxisBase-derived object.
Definition: TAxis.hxx:848
double GetBinWidth() const noexcept
Get the width of the bins.
Definition: TAxis.hxx:391
std::unordered_map< std::string, int > fLabelsIndex
Map of label (view on fLabels&#39;s elements) to bin index.
Definition: TAxis.hxx:641
double GetBinCenter(int bin) const noexcept
Get the bin center of the bin with the given index.
Definition: TAxis.hxx:581
TAxisIrregular(std::vector< double > &&binborders) noexcept
Construct a TAxisIrregular from a vector of bin borders.
Definition: TAxis.hxx:527
Histogram axis base class.
Definition: TAxis.hxx:40
TAxisConfig(std::string_view title, std::vector< std::string > &&labels)
Represents a TAxisLabels with labels and title.
Definition: TAxis.hxx:801
const_iterator & operator-=(int d) noexcept
Definition: TAxis.hxx:136
TAxisConfig(std::string_view title, Grow_t, int nbins, double from, double to)
Represents a TAxisGrow with nbins from from to to, and axis title.
Definition: TAxis.hxx:754
A TAxisGrow that has a label assigned to each bin and a bin width of 1.
Definition: TAxis.hxx:638
Source and target axes are identical.
int GetNBins() const noexcept
Get the number of bins. Forwards to the underlying axis.
Definition: TAxis.hxx:918
Axis_t operator()(const TAxisConfig &cfg) noexcept
Definition: TAxis.hxx:864
The source axis and target axis have different binning.
Coordinate could fit after growing the axis.
TAxisConfig(const TAxisGrow &ax)
Build a TAxisConfig from a TAxisGrow.
Definition: TAxis.hxx:815
bool IsOverflowBin(int bin) const noexcept
Whether the bin index is referencing a bin higher than the axis range.
Definition: TAxis.hxx:228
const bool fCanGrow
Whether this axis can grow (and thus has no overflow bins).
Definition: TAxis.hxx:258
static bool CanGrow() noexcept
This axis cannot grow.
Definition: TAxis.hxx:380
double GetMaximum() const noexcept
Get the high end of the axis range.
Definition: TAxis.hxx:386
int FindBin(double x) const noexcept
Find the bin index for the given coordinate.
Definition: TAxis.hxx:374
TAxisIrregular(const std::vector< double > &binborders)
Construct a TAxisIrregular from a vector of bin borders.
Definition: TAxis.hxx:515
TAxisLabels(std::string_view title, const std::vector< std::string_view > &labels)
Construct a TAxisLables from a vector of string_views, with title.
Definition: TAxis.hxx:659
const Int_t n
Definition: legend1.C:16
const_iterator & operator+=(int d) noexcept
Definition: TAxis.hxx:130
#define R__ERROR_HERE(GROUP)
Definition: TLogger.hxx:122
std::vector< std::string > fLabels
Bin labels for a TAxisLabels.
Definition: TAxis.hxx:719
const std::string & GetTitle() const
Definition: TAxis.hxx:906
bool operator<=(TAxisBase::const_iterator lhs, TAxisBase::const_iterator rhs) noexcept
i <= j
Definition: TAxis.hxx:277
TAxisConfig(std::string_view title, const std::vector< std::string_view > &labels)
Represents a TAxisLabels with labels and title.
Definition: TAxis.hxx:789