Logo ROOT  
Reference Guide
RAxis.cxx
Go to the documentation of this file.
1/// \file RAxis.cxx
2/// \ingroup Hist ROOT7
3/// \author Axel Naumann <axel@cern.ch>
4/// \date 2015-08-06
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include "ROOT/RAxis.hxx"
17
18#include <cmath>
19#include <limits>
20
22
24 // Bin borders must match
25 if (!HasSameBinBordersAs(other))
26 return false;
27
28 // Bin labels must match
29 auto lbl_ptr = dynamic_cast<const RAxisLabels*>(this);
30 auto other_lbl_ptr = dynamic_cast<const RAxisLabels*>(&other);
31 if (bool(lbl_ptr) != bool(other_lbl_ptr)) {
32 return false;
33 } else if (lbl_ptr) {
34 auto lbl_cmp = lbl_ptr->CompareBinLabels(*other_lbl_ptr);
35 return (lbl_cmp == RAxisLabels::kLabelsCmpSame);
36 } else {
37 return true;
38 }
39}
40
42{
43 // fracBinIdx is the fractional bin index of x in this axis. It's (close to)
44 // an integer if it's an axis border.
45 double fracBinIdx = GetFirstBin() + FindBinRaw(x);
46
47 // fracBinIdx might be 12.99999999. It's a bin border if the deviation from
48 // an regular bin border is "fairly small".
49 int binIdx = std::round(fracBinIdx);
50 double binOffset = fracBinIdx - binIdx;
51 if (std::fabs(binOffset) > 10 * std::numeric_limits<double>::epsilon())
53
54 // If the bin index is below the first bin (i.e. x is the lower edge of the
55 // underflow bin) then it's out of range.
56 if (binIdx < GetFirstBin())
58 // If x is the lower edge of the overflow bin then that's still okay - but if
59 // even the bin before binIdx is an overflow it's out of range.
60 if (binIdx > GetLastBin() + 1)
62
63 return binIdx;
64}
65
67 // This is an optimized override for the equidistant-equidistant case,
68 // fall back to the default implementation if we're not in that case.
69 auto other_eq_ptr = dynamic_cast<const RAxisEquidistant*>(&other);
70 if (!other_eq_ptr)
72 const RAxisEquidistant& other_eq = *other_eq_ptr;
73
74 // Can directly compare equidistant/growable axis properties in this case
75 return fInvBinWidth == other_eq.fInvBinWidth &&
76 fLow == other_eq.fLow &&
77 fNBinsNoOver == other_eq.fNBinsNoOver &&
78 CanGrow() == other_eq.CanGrow();
79}
80
82{
83 // Check in which bin `x` resides
84 double fracBinIdx = FindBinRaw(x);
85 const int binIdx = fracBinIdx;
86
87 // Are we close to the lower and upper bin boundaries, if any?
88 constexpr double tol = 10 * std::numeric_limits<double>::epsilon();
89 if (binIdx >= GetFirstBin()) {
90 const double lowBound = GetBinFrom(binIdx);
91 if (std::fabs(x - lowBound) < tol * std::fabs(lowBound))
92 return binIdx;
93 }
94 if (binIdx <= GetLastBin()) {
95 const double upBound = GetBinTo(binIdx);
96 if (std::fabs(x - upBound) < tol * std::fabs(upBound))
97 return binIdx + 1;
98 }
99
100 // If not, report failure
102}
103
105 // This is an optimized override for the irregular-irregular case,
106 // fall back to the default implementation if we're not in that case.
107 auto other_irr_ptr = dynamic_cast<const RAxisIrregular*>(&other);
108 if (!other_irr_ptr)
109 return RAxisBase::HasSameBinBordersAs(other);
110 const RAxisIrregular& other_irr = *other_irr_ptr;
111
112 // Only need to compare bin borders in this specialized case
113 return fBinBorders == other_irr.fBinBorders;
114}
115
117 const RAxisEquidistant &source) noexcept
118{
119 // First, let's get the common "all parameters are equal" case out of the way
120 if (source.HasSameBinningAs(target))
122
123 // Do the source min/max boundaries correspond to target bin boundaries?
124 int idxTargetLow = target.GetBinIndexForLowEdge(source.GetMinimum());
125 int idxTargetHigh = target.GetBinIndexForLowEdge(source.GetMaximum());
126 if (idxTargetLow < 0 || idxTargetHigh < 0)
127 // If not, the source is incompatible with the target since the first or
128 // last source bin does not map into a target axis bin.
130
131 // If so, and if the bin width is the same, then since we've eliminated the
132 // care where min/max/width are equal, source must be a subset of target.
133 if (source.GetInverseBinWidth() == target.GetInverseBinWidth())
135
136 // Now we are left with the case
137 // source: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6
138 // target: ...0.0, 0.3, 0.6...
139 // The question is: is the ratio of the bin width identical to the ratio of
140 // the number of bin?
141 if (std::fabs(target.GetInverseBinWidth() * source.GetNBinsNoOver() -
142 source.GetInverseBinWidth() * (idxTargetHigh - idxTargetLow)) > 1E-6 * target.GetInverseBinWidth())
144
145 // source is a fine-grained version of target.
147}
148
149// TODO: the other CanMap() overloads
Histogram axis base class.
Definition: RAxis.hxx:44
virtual bool HasSameBinBordersAs(const RAxisBase &other) const
Check if two axis have the same bin borders.
Definition: RAxis.hxx:98
static constexpr const int kInvalidBin
Special bin index returned to signify that no bin matches a request.
Definition: RAxis.hxx:226
bool HasSameBinningAs(const RAxisBase &other) const
Check if two axes use the same binning convention, i.e.
Definition: RAxis.cxx:23
virtual ~RAxisBase()
Virtual destructor needed in this inheritance-based design.
Definition: RAxis.cxx:21
Axis with equidistant bin borders.
Definition: RAxis.hxx:384
int GetBinIndexForLowEdge(double x) const noexcept final override
If the coordinate x is within 10 ULPs of a bin low edge coordinate, return the bin for which this is ...
Definition: RAxis.cxx:41
bool HasSameBinBordersAs(const RAxisBase &other) const override
See RAxisBase::HasSameBinBordersAs.
Definition: RAxis.cxx:66
double fInvBinWidth
The inverse of the bin width.
Definition: RAxis.hxx:387
bool CanGrow() const noexcept override
This axis cannot grow.
Definition: RAxis.hxx:458
unsigned int fNBinsNoOver
Number of bins excluding under- and overflow.
Definition: RAxis.hxx:388
double fLow
The lower limit of the axis.
Definition: RAxis.hxx:386
An axis with non-equidistant bins (also known as "variable binning").
Definition: RAxis.hxx:591
bool HasSameBinBordersAs(const RAxisBase &other) const override
See RAxisBase::HasSameBinBordersAs.
Definition: RAxis.cxx:104
int GetBinIndexForLowEdge(double x) const noexcept final override
If the coordinate x is within 10 ULPs of a bin low edge coordinate, return the bin for which this is ...
Definition: RAxis.cxx:81
std::vector< double > fBinBorders
Bin borders, one more than the number of regular bins.
Definition: RAxis.hxx:594
A RAxisGrow that has a label assigned to each bin and a bin width of 1.
Definition: RAxis.hxx:738
@ kLabelsCmpSame
Both axes have the same labels, mapping to the same bins.
Definition: RAxis.hxx:800
LabelsCmpFlags CompareBinLabels(const RAxisLabels &other) const noexcept
Compare the labels of this axis with those of another axis.
Definition: RAxis.hxx:813
Double_t x[n]
Definition: legend1.C:17
EAxisCompatibility CanMap(const RAxisEquidistant &target, const RAxisEquidistant &source) noexcept
Whether (and how) the source axis can be merged into the target axis.
Definition: RAxis.cxx:116
@ kContains
The source is a subset of bins of the target axis.
@ kIdentical
Source and target axes are identical.
@ kIncompatible
The source axis and target axis have different binning.
@ kSampling
The bins of the source axis have finer granularity, but the bin borders are compatible.
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
constexpr Double_t E()
Base of natural log:
Definition: TMath.h:97
REAL epsilon
Definition: triangle.c:617