Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RHist.hxx
Go to the documentation of this file.
1/// \file ROOT/RHist.hxx
2/// \ingroup HistV7
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
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#ifndef ROOT7_RHist
17#define ROOT7_RHist
18
19#include "ROOT/RSpan.hxx"
20#include "ROOT/RAxis.hxx"
21#include "ROOT/RHistBinIter.hxx"
22#include "ROOT/RHistImpl.hxx"
23#include "ROOT/RHistData.hxx"
24#include "ROOT/RLogger.hxx"
25#include <initializer_list>
26#include <stdexcept>
27
28namespace ROOT {
29namespace Experimental {
30
31// fwd declare for fwd declare for friend declaration in RHist...
32template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
33class RHist;
34
35// fwd declare for friend declaration in RHist.
36template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
37class RHist<DIMENSIONS, PRECISION, STAT...>
38HistFromImpl(std::unique_ptr<typename RHist<DIMENSIONS, PRECISION, STAT...>::ImplBase_t> pHistImpl);
39
40/**
41 \class RHist
42 Histogram class for histograms with `DIMENSIONS` dimensions, where each
43 bin count is stored by a value of type `PRECISION`. STAT stores statistical
44 data of the entries filled into the histogram (bin content, uncertainties etc).
45
46 A histogram counts occurrences of values or n-dimensional combinations thereof.
47 Contrary to for instance a `RTree`, a histogram combines adjacent values. The
48 resolution of this combination is defined by the axis binning, see e.g.
49 http://www.wikiwand.com/en/Histogram
50 */
51
52template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
53class RHist {
54public:
55 /// The type of the `Detail::RHistImplBase` of this histogram.
56 using ImplBase_t =
58 /// The coordinates type: a `DIMENSIONS`-dimensional `std::array` of `double`.
60 /// The type of weights
62 /// Pointer type to `HistImpl_t::Fill`, for faster access.
64 /// Range.
66
68
69 /// Number of dimensions of the coordinates
70 static constexpr int GetNDim() noexcept { return DIMENSIONS; }
71
72 RHist() = default;
73 RHist(RHist &&) = default;
74 RHist(const RHist &other): fImpl(other.fImpl->Clone()), fFillFunc(other.fFillFunc)
75 {}
76
77 /// Create a histogram from an `array` of axes (`RAxisConfig`s). Example code:
78 ///
79 /// Construct a 1-dimensional histogram that can be filled with `floats`s.
80 /// The axis has 10 bins between 0. and 1. The two outermost sets of curly
81 /// braces are to reach the initialization of the `std::array` elements; the
82 /// inner one is for the initialization of a `RAxisCoordinate`.
83 ///
84 /// RHist<1,float> h1f({{ {10, 0., 1.} }});
85 ///
86 /// Construct a 2-dimensional histogram, with the first axis as before, and
87 /// the second axis having non-uniform ("irregular") binning, where all bin-
88 /// edges are specified. As this is itself an array it must be enclosed by
89 /// double curlies.
90 ///
91 /// RHist<2,int> h2i({{ {10, 0., 1.}, {{-1., 0., 1., 10., 100.}} }});
92 explicit RHist(std::array<RAxisConfig, DIMENSIONS> axes);
93
94 /// Constructor overload taking the histogram title.
95 RHist(std::string_view histTitle, std::array<RAxisConfig, DIMENSIONS> axes);
96
97 /// Constructor overload that's only available for a 1-dimensional histogram.
98 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 1>::type>
99 explicit RHist(const RAxisConfig &xaxis): RHist(std::array<RAxisConfig, 1>{{xaxis}})
100 {}
101
102 /// Constructor overload that's only available for a 1-dimensional histogram,
103 /// also passing the histogram title.
104 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 1>::type>
105 RHist(std::string_view histTitle, const RAxisConfig &xaxis): RHist(histTitle, std::array<RAxisConfig, 1>{{xaxis}})
106 {}
107
108 /// Constructor overload that's only available for a 2-dimensional histogram.
109 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 2>::type>
110 RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis): RHist(std::array<RAxisConfig, 2>{{xaxis, yaxis}})
111 {}
112
113 /// Constructor overload that's only available for a 2-dimensional histogram,
114 /// also passing the histogram title.
115 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 2>::type>
116 RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis)
117 : RHist(histTitle, std::array<RAxisConfig, 2>{{xaxis, yaxis}})
118 {}
119
120 /// Constructor overload that's only available for a 3-dimensional histogram.
121 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 3>::type>
122 RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
123 : RHist(std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
124 {}
125
126 /// Constructor overload that's only available for a 3-dimensional histogram,
127 /// also passing the histogram title.
128 template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 3>::type>
129 RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
130 : RHist(histTitle, std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
131 {}
132
133 /// Access the ImplBase_t this RHist points to.
134 ImplBase_t *GetImpl() const noexcept { return fImpl.get(); }
135
136 /// "Steal" the ImplBase_t this RHist points to.
137 std::unique_ptr<ImplBase_t> TakeImpl() && noexcept { return std::move(fImpl); }
138
139 /// Add `weight` to the bin containing coordinate `x`.
140 void Fill(const CoordArray_t &x, Weight_t weight = (Weight_t)1) noexcept { (fImpl.get()->*fFillFunc)(x, weight); }
141
142 /// For each coordinate in `xN`, add `weightN[i]` to the bin at coordinate
143 /// `xN[i]`. The sizes of `xN` and `weightN` must be the same. This is more
144 /// efficient than many separate calls to `Fill()`.
145 void FillN(const std::span<const CoordArray_t> xN, const std::span<const Weight_t> weightN) noexcept
146 {
147 fImpl->FillN(xN, weightN);
148 }
149
150 /// For each coordinate in `xN`, add `weightN[i]` to the bin at coordinate
151 /// `xN[i]`. The sizes of `xN` and `weightN` must be the same. This is more
152 /// efficient than many separate calls to `Fill()`.
153 /// Overload for passing initializer lists.
154 void FillN(std::initializer_list<const CoordArray_t> xN, std::initializer_list<const Weight_t> weightN) noexcept
155 {
156 fImpl->FillN(std::span<const CoordArray_t>(xN.begin(), xN.end()), std::span<const Weight_t>(weightN.begin(), weightN.end()));
157 }
158
159 /// Convenience overload: `FillN()` with weight 1.
160 void FillN(const std::span<const CoordArray_t> xN) noexcept { fImpl->FillN(xN); }
161
162 /// Convenience overload: `FillN()` with weight 1.
163 /// Overload for passing initializer lists.
164 void FillN(std::initializer_list<const CoordArray_t> xN) noexcept {
165 fImpl->FillN(std::span<const CoordArray_t>(xN.begin(), xN.end()));
166 }
167
168 /// Get the number of entries this histogram was filled with.
169 int64_t GetEntries() const noexcept { return fImpl->GetStat().GetEntries(); }
170
171 /// Get the content of the bin at `x`.
172 Weight_t GetBinContent(const CoordArray_t &x) const { return fImpl->GetBinContent(x); }
173
174 /// Get the uncertainty on the content of the bin at `x`.
175 double GetBinUncertainty(const CoordArray_t &x) const { return fImpl->GetBinUncertainty(x); }
176
177 const_iterator begin() const { return const_iterator(*fImpl, 1); }
178
179 const_iterator end() const { return const_iterator(*fImpl, fImpl->GetNBinsNoOver() + 1); }
180
181 /// Swap *this and other.
182 ///
183 /// Very efficient; swaps the `fImpl` pointers.
185 {
186 std::swap(fImpl, other.fImpl);
187 std::swap(fFillFunc, other.fFillFunc);
188 }
189
190private:
191 /// The actual histogram implementation.
192 std::unique_ptr<ImplBase_t> fImpl;
193
194 /// Pointer to RHistImpl::Fill() member function.
195 FillFunc_t fFillFunc = nullptr; //!
196
197 friend RHist HistFromImpl<>(std::unique_ptr<ImplBase_t>);
198};
199
200/// RHist with no STAT parameter uses RHistStatContent by default.
201template <int DIMENSIONS, class PRECISION>
202class RHist<DIMENSIONS, PRECISION>: public RHist<DIMENSIONS, PRECISION, RHistStatContent> {
203 using RHist<DIMENSIONS, PRECISION, RHistStatContent>::RHist;
204};
205
206/// Swap two histograms.
207///
208/// Very efficient; swaps the `fImpl` pointers.
209template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
211{
212 a.swap(b);
213}
214
215namespace Internal {
216/**
217 Generate RHist::fImpl from RHist constructor arguments.
218 */
219template <int NDIM, int IDIM, class DATA, class... PROCESSEDAXISCONFIG>
221 /// Select the template argument for the next axis type, and "recurse" into
222 /// RHistImplGen for the next axis.
223 template <RAxisConfig::EKind KIND>
224 std::unique_ptr<Detail::RHistImplBase<DATA>>
225 MakeNextAxis(std::string_view title, const std::array<RAxisConfig, NDIM> &axes,
226 PROCESSEDAXISCONFIG... processedAxisArgs)
227 {
228 using NextAxis_t = typename AxisConfigToType<KIND>::Axis_t;
229 NextAxis_t nextAxis = AxisConfigToType<KIND>()(axes[IDIM]);
230 using HistImpl_t = RHistImplGen<NDIM, IDIM + 1, DATA, PROCESSEDAXISCONFIG..., NextAxis_t>;
231 return HistImpl_t()(title, axes, processedAxisArgs..., nextAxis);
232 }
233
234 /// Make a RHistImpl-derived object reflecting the RAxisConfig array.
235 ///
236 /// Delegate to the appropriate MakeNextAxis instantiation, depending on the
237 /// axis type selected in the RAxisConfig.
238 /// \param title - title of the derived object.
239 /// \param axes - `RAxisConfig` objects describing the axis of the resulting
240 /// RHistImpl.
241 /// \param processedAxisArgs - the RAxisBase-derived axis objects describing the
242 /// axes of the resulting RHistImpl. There are `IDIM` of those; in the end
243 /// (`IDIM` == `GetNDim()`), all `axes` have been converted to
244 /// `processedAxisArgs` and the RHistImpl constructor can be invoked, passing
245 /// the `processedAxisArgs`.
246 std::unique_ptr<Detail::RHistImplBase<DATA>> operator()(std::string_view title,
247 const std::array<RAxisConfig, NDIM> &axes,
248 PROCESSEDAXISCONFIG... processedAxisArgs)
249 {
250 switch (axes[IDIM].GetKind()) {
251 case RAxisConfig::kEquidistant: return MakeNextAxis<RAxisConfig::kEquidistant>(title, axes, processedAxisArgs...);
252 case RAxisConfig::kGrow: return MakeNextAxis<RAxisConfig::kGrow>(title, axes, processedAxisArgs...);
253 case RAxisConfig::kIrregular: return MakeNextAxis<RAxisConfig::kIrregular>(title, axes, processedAxisArgs...);
254 default: R__LOG_ERROR(HistLog()) << "Unhandled axis kind";
255 }
256 return nullptr;
257 }
258};
259
260/// Generate RHist::fImpl from constructor arguments; recursion end.
261template <int NDIM, class DATA, class... PROCESSEDAXISCONFIG>
262/// Create the histogram, now that all axis types and initializer objects are
263/// determined.
264struct RHistImplGen<NDIM, NDIM, DATA, PROCESSEDAXISCONFIG...> {
266 std::unique_ptr<HistImplBase_t>
267 operator()(std::string_view title, const std::array<RAxisConfig, DATA::GetNDim()> &, PROCESSEDAXISCONFIG... axisArgs)
268 {
269 using HistImplt_t = Detail::RHistImpl<DATA, PROCESSEDAXISCONFIG...>;
270 return std::make_unique<HistImplt_t>(title, axisArgs...);
271 }
272};
273} // namespace Internal
274
275template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
276RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::string_view title, std::array<RAxisConfig, DIMENSIONS> axes)
277 : fImpl{std::move(
278 Internal::RHistImplGen<RHist::GetNDim(), 0,
279 Detail::RHistData<DIMENSIONS, PRECISION, std::vector<PRECISION>, STAT...>>()(
280 title, axes))}
281{
282 fFillFunc = fImpl->GetFillFunc();
283}
284
285template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
286RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::array<RAxisConfig, DIMENSIONS> axes): RHist("", axes)
287{}
288
289/// Adopt an external, stand-alone RHistImpl. The RHist will take ownership.
290template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
291RHist<DIMENSIONS, PRECISION, STAT...>
293{
294 RHist<DIMENSIONS, PRECISION, STAT...> ret;
295 ret.fFillFunc = pHistImpl->GetFillFunc();
296 std::swap(ret.fImpl, pHistImpl);
297 return ret;
298}
299
300/// \name RHist Typedefs
301///\{ Convenience typedefs (ROOT6-compatible type names)
302
303// Keep them as typedefs, to make sure old-style documentation tools can understand them.
309
315
321///\}
322
323/// Add two histograms.
324///
325/// This operation may currently only be performed if the two histograms have
326/// the same axis configuration, use the same precision, and if `from` records
327/// at least the same statistics as `to` (recording more stats is fine).
328///
329/// Adding histograms with incompatible axis binning will be reported at runtime
330/// with an `std::runtime_error`. Insufficient statistics in the source
331/// histogram will be detected at compile-time and result in a compiler error.
332///
333/// In the future, we may either adopt a more relaxed definition of histogram
334/// addition or provide a mechanism to convert from one histogram type to
335/// another. We currently favor the latter path.
336template <int DIMENSIONS, class PRECISION,
337 template <int D_, class P_> class... STAT_TO,
338 template <int D_, class P_> class... STAT_FROM>
340{
341 // Enforce "same axis configuration" policy.
342 auto& toImpl = *to.GetImpl();
343 const auto& fromImpl = *from.GetImpl();
344 for (int dim = 0; dim < DIMENSIONS; ++dim) {
345 if (!toImpl.GetAxis(dim).HasSameBinningAs(fromImpl.GetAxis(dim))) {
346 throw std::runtime_error("Attempted to add RHists with incompatible axis binning");
347 }
348 }
349
350 // Now that we know that the two axes have the same binning, we can just add
351 // the statistics directly.
352 toImpl.GetStat().Add(fromImpl.GetStat());
353}
354
355} // namespace Experimental
356} // namespace ROOT
357
358#endif
constexpr int PRECISION
Definition MnPrint.cxx:30
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
Iterates over the bins of a RHist or RHistImpl.
Interface class for RHistImpl.
void(RHistImplBase::*)(const CoordArray_t &x, Weight_t w) FillFunc_t
Type of the Fill(x, w) function.
Hist::CoordArray_t< DATA::GetNDim()> CoordArray_t
Type of the coordinates.
Hist::AxisIterRange_t< DIMENSIONS > AxisIterRange_t
Range type.
Definition RHistImpl.hxx:79
Objects used to configure the different axis types.
@ kGrow
represents a RAxisGrow
@ kEquidistant
represents a RAxisEquidistant
@ kIrregular
represents a RAxisIrregular
Basic histogram statistics, keeping track of the bin content and the total number of calls to Fill().
Definition RHistData.hxx:36
Histogram class for histograms with DIMENSIONS dimensions, where each bin count is stored by a value ...
Definition RHist.hxx:53
ImplBase_t * GetImpl() const noexcept
Access the ImplBase_t this RHist points to.
Definition RHist.hxx:134
static constexpr int GetNDim() noexcept
Number of dimensions of the coordinates.
Definition RHist.hxx:70
void FillN(const std::span< const CoordArray_t > xN) noexcept
Convenience overload: FillN() with weight 1.
Definition RHist.hxx:160
PRECISION Weight_t
The type of weights.
Definition RHist.hxx:61
Weight_t GetBinContent(const CoordArray_t &x) const
Get the content of the bin at x.
Definition RHist.hxx:172
int64_t GetEntries() const noexcept
Get the number of entries this histogram was filled with.
Definition RHist.hxx:169
double GetBinUncertainty(const CoordArray_t &x) const
Get the uncertainty on the content of the bin at x.
Definition RHist.hxx:175
RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis)
Constructor overload that's only available for a 2-dimensional histogram, also passing the histogram ...
Definition RHist.hxx:116
const_iterator end() const
Definition RHist.hxx:179
RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis)
Constructor overload that's only available for a 2-dimensional histogram.
Definition RHist.hxx:110
void FillN(std::initializer_list< const CoordArray_t > xN, std::initializer_list< const Weight_t > weightN) noexcept
For each coordinate in xN, add weightN[i] to the bin at coordinate xN[i].
Definition RHist.hxx:154
typename ImplBase_t::FillFunc_t FillFunc_t
Pointer type to HistImpl_t::Fill, for faster access.
Definition RHist.hxx:63
RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
Constructor overload that's only available for a 3-dimensional histogram.
Definition RHist.hxx:122
void FillN(const std::span< const CoordArray_t > xN, const std::span< const Weight_t > weightN) noexcept
For each coordinate in xN, add weightN[i] to the bin at coordinate xN[i].
Definition RHist.hxx:145
typename ImplBase_t::AxisIterRange_t AxisRange_t
Range.
Definition RHist.hxx:65
void Fill(const CoordArray_t &x, Weight_t weight=(Weight_t) 1) noexcept
Add weight to the bin containing coordinate x.
Definition RHist.hxx:140
RHist(std::string_view histTitle, std::array< RAxisConfig, DIMENSIONS > axes)
Constructor overload taking the histogram title.
Definition RHist.hxx:276
Detail::RHistBinIter< ImplBase_t > const_iterator
Definition RHist.hxx:67
const_iterator begin() const
Definition RHist.hxx:177
RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
Constructor overload that's only available for a 3-dimensional histogram, also passing the histogram ...
Definition RHist.hxx:129
void swap(RHist< DIMENSIONS, PRECISION, STAT... > &other) noexcept
Swap *this and other.
Definition RHist.hxx:184
std::unique_ptr< ImplBase_t > fImpl
The actual histogram implementation.
Definition RHist.hxx:192
std::unique_ptr< ImplBase_t > TakeImpl() &&noexcept
"Steal" the ImplBase_t this RHist points to.
Definition RHist.hxx:137
RHist(const RHist &other)
Definition RHist.hxx:74
void FillN(std::initializer_list< const CoordArray_t > xN) noexcept
Convenience overload: FillN() with weight 1.
Definition RHist.hxx:164
RHist(RHist &&)=default
RHist(const RAxisConfig &xaxis)
Constructor overload that's only available for a 1-dimensional histogram.
Definition RHist.hxx:99
RHist(std::array< RAxisConfig, DIMENSIONS > axes)
Create a histogram from an array of axes (RAxisConfigs).
Definition RHist.hxx:286
FillFunc_t fFillFunc
Pointer to RHistImpl::Fill() member function.
Definition RHist.hxx:195
typename ImplBase_t::CoordArray_t CoordArray_t
The coordinates type: a DIMENSIONS-dimensional std::array of double.
Definition RHist.hxx:59
RHist(std::string_view histTitle, const RAxisConfig &xaxis)
Constructor overload that's only available for a 1-dimensional histogram, also passing the histogram ...
Definition RHist.hxx:105
Double_t x[n]
Definition legend1.C:17
class RHist< DIMENSIONS, PRECISION, STAT... > HistFromImpl(std::unique_ptr< typename RHist< DIMENSIONS, PRECISION, STAT... >::ImplBase_t > pHistImpl)
Adopt an external, stand-alone RHistImpl. The RHist will take ownership.
Definition RHist.hxx:292
void Add(RHist< DIMENSIONS, PRECISION, STAT_TO... > &to, const RHist< DIMENSIONS, PRECISION, STAT_FROM... > &from)
Add two histograms.
Definition RHist.hxx:339
RLogChannel & HistLog()
Log channel for Hist diagnostics.
Definition RAxis.cxx:25
void swap(RHist< DIMENSIONS, PRECISION, STAT... > &a, RHist< DIMENSIONS, PRECISION, STAT... > &b) noexcept
Swap two histograms.
Definition RHist.hxx:210
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Converts a RAxisConfig of whatever kind to the corresponding RAxisBase-derived object.
std::unique_ptr< HistImplBase_t > operator()(std::string_view title, const std::array< RAxisConfig, DATA::GetNDim()> &, PROCESSEDAXISCONFIG... axisArgs)
Definition RHist.hxx:267
Generate RHist::fImpl from RHist constructor arguments.
Definition RHist.hxx:220
std::unique_ptr< Detail::RHistImplBase< DATA > > MakeNextAxis(std::string_view title, const std::array< RAxisConfig, NDIM > &axes, PROCESSEDAXISCONFIG... processedAxisArgs)
Select the template argument for the next axis type, and "recurse" into RHistImplGen for the next axi...
Definition RHist.hxx:225
std::unique_ptr< Detail::RHistImplBase< DATA > > operator()(std::string_view title, const std::array< RAxisConfig, NDIM > &axes, PROCESSEDAXISCONFIG... processedAxisArgs)
Make a RHistImpl-derived object reflecting the RAxisConfig array.
Definition RHist.hxx:246