Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "ROOT/RHistUtils.hxx"
19#include <ROOT/RLogger.hxx>
20
21#include <cmath>
22#include <limits>
23
24// From RHistUtils.hxx:
26 static RLogChannel sLog("ROOT.Hist");
27 return sLog;
28}
29
30
32
34 // Bin borders must match
35 if (!HasSameBinBordersAs(other))
36 return false;
37
38 // Bin labels must match
39 auto lbl_ptr = dynamic_cast<const RAxisLabels*>(this);
40 auto other_lbl_ptr = dynamic_cast<const RAxisLabels*>(&other);
41 if (bool(lbl_ptr) != bool(other_lbl_ptr)) {
42 return false;
43 } else if (lbl_ptr) {
44 auto lbl_cmp = lbl_ptr->CompareBinLabels(*other_lbl_ptr);
45 return (lbl_cmp == RAxisLabels::kLabelsCmpSame);
46 } else {
47 return true;
48 }
49}
50
52{
53 // fracBinIdx is the fractional bin index of x in this axis. It's (close to)
54 // an integer if it's an axis border.
55 double fracBinIdx = GetFirstBin() + FindBinRaw(x);
56
57 // fracBinIdx might be 12.99999999. It's a bin border if the deviation from
58 // an regular bin border is "fairly small".
59 int binIdx = std::round(fracBinIdx);
60 double binOffset = fracBinIdx - binIdx;
61 if (std::fabs(binOffset) > 10 * std::numeric_limits<double>::epsilon())
63
64 // If the bin index is below the first bin (i.e. x is the lower edge of the
65 // underflow bin) then it's out of range.
66 if (binIdx < GetFirstBin())
68 // If x is the lower edge of the overflow bin then that's still okay - but if
69 // even the bin before binIdx is an overflow it's out of range.
70 if (binIdx > GetLastBin() + 1)
72
73 return binIdx;
74}
75
77 // This is an optimized override for the equidistant-equidistant case,
78 // fall back to the default implementation if we're not in that case.
79 auto other_eq_ptr = dynamic_cast<const RAxisEquidistant*>(&other);
80 if (!other_eq_ptr)
82 const RAxisEquidistant& other_eq = *other_eq_ptr;
83
84 // Can directly compare equidistant/growable axis properties in this case
85 return fInvBinWidth == other_eq.fInvBinWidth &&
86 fLow == other_eq.fLow &&
87 fNBinsNoOver == other_eq.fNBinsNoOver &&
88 CanGrow() == other_eq.CanGrow();
89}
90
92{
93 // Check in which bin `x` resides
94 double fracBinIdx = FindBinRaw(x);
95 const int binIdx = fracBinIdx;
96
97 // Are we close to the lower and upper bin boundaries, if any?
98 constexpr double tol = 10 * std::numeric_limits<double>::epsilon();
99 if (binIdx >= GetFirstBin()) {
100 const double lowBound = GetBinFrom(binIdx);
101 if (std::fabs(x - lowBound) < tol * std::fabs(lowBound))
102 return binIdx;
103 }
104 if (binIdx <= GetLastBin()) {
105 const double upBound = GetBinTo(binIdx);
106 if (std::fabs(x - upBound) < tol * std::fabs(upBound))
107 return binIdx + 1;
108 }
109
110 // If not, report failure
112}
113
115 // This is an optimized override for the irregular-irregular case,
116 // fall back to the default implementation if we're not in that case.
117 auto other_irr_ptr = dynamic_cast<const RAxisIrregular*>(&other);
118 if (!other_irr_ptr)
119 return RAxisBase::HasSameBinBordersAs(other);
120 const RAxisIrregular& other_irr = *other_irr_ptr;
121
122 // Only need to compare bin borders in this specialized case
123 return fBinBorders == other_irr.fBinBorders;
124}
125
127 const RAxisEquidistant &source) noexcept
128{
129 // First, let's get the common "all parameters are equal" case out of the way
130 if (source.HasSameBinningAs(target))
132
133 // Do the source min/max boundaries correspond to target bin boundaries?
134 int idxTargetLow = target.GetBinIndexForLowEdge(source.GetMinimum());
135 int idxTargetHigh = target.GetBinIndexForLowEdge(source.GetMaximum());
136 if (idxTargetLow < 0 || idxTargetHigh < 0)
137 // If not, the source is incompatible with the target since the first or
138 // last source bin does not map into a target axis bin.
140
141 // If so, and if the bin width is the same, then since we've eliminated the
142 // care where min/max/width are equal, source must be a subset of target.
143 if (source.GetInverseBinWidth() == target.GetInverseBinWidth())
145
146 // Now we are left with the case
147 // source: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6
148 // target: ...0.0, 0.3, 0.6...
149 // The question is: is the ratio of the bin width identical to the ratio of
150 // the number of bin?
151 if (std::fabs(target.GetInverseBinWidth() * source.GetNBinsNoOver() -
152 source.GetInverseBinWidth() * (idxTargetHigh - idxTargetLow)) > 1E-6 * target.GetInverseBinWidth())
154
155 // source is a fine-grained version of target.
157}
158
159// 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:33
virtual ~RAxisBase()
Virtual destructor needed in this inheritance-based design.
Definition RAxis.cxx:31
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:51
bool HasSameBinBordersAs(const RAxisBase &other) const override
See RAxisBase::HasSameBinBordersAs.
Definition RAxis.cxx:76
double fInvBinWidth
The inverse of the bin width.
Definition RAxis.hxx:387
bool CanGrow() const noexcept override
This axis cannot grow.
Definition RAxis.hxx:457
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:590
bool HasSameBinBordersAs(const RAxisBase &other) const override
See RAxisBase::HasSameBinBordersAs.
Definition RAxis.cxx:114
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:91
std::vector< double > fBinBorders
Bin borders, one more than the number of regular bins.
Definition RAxis.hxx:593
A RAxisGrow that has a label assigned to each bin and a bin width of 1.
Definition RAxis.hxx:737
@ kLabelsCmpSame
Both axes have the same labels, mapping to the same bins.
Definition RAxis.hxx:799
LabelsCmpFlags CompareBinLabels(const RAxisLabels &other) const noexcept
Compare the labels of this axis with those of another axis.
Definition RAxis.hxx:812
A log configuration for a channel, e.g.
Definition RLogger.hxx:101
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:126
RLogChannel & HistLog()
Log channel for Hist diagnostics.
Definition RAxis.cxx:25
@ 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.