Logo ROOT   6.18/05
Reference Guide
RHist.hxx
Go to the documentation of this file.
1/// \file ROOT/RHist.h
2/// \ingroup Hist ROOT7
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/RDrawable.hxx"
22#include "ROOT/RHistBinIter.hxx"
23#include "ROOT/RHistImpl.hxx"
24#include "ROOT/RHistData.hxx"
25#include <initializer_list>
26
27namespace ROOT {
28namespace Experimental {
29
30// fwd declare for fwd declare for friend declaration in RHist...
31template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
32class RHist;
33
34// fwd declare for friend declaration in RHist.
35template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
36class RHist<DIMENSIONS, PRECISION, STAT...>
37HistFromImpl(std::unique_ptr<typename RHist<DIMENSIONS, PRECISION, STAT...>::ImplBase_t> pHistImpl);
38
39/**
40 \class RHist
41 Histogram class for histograms with `DIMENSIONS` dimensions, where each
42 bin count is stored by a value of type `PRECISION`. STAT stores statistical
43 data of the entries filled into the histogram (bin content, uncertainties etc).
44
45 A histogram counts occurrences of values or n-dimensional combinations thereof.
46 Contrary to for instance a `RTree`, a histogram combines adjacent values. The
47 resolution of this combination is defined by the axis binning, see e.g.
48 http://www.wikiwand.com/en/Histogram
49 */
50
51template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
52class RHist {
53public:
54 /// The type of the `Detail::RHistImplBase` of this histogram.
55 using ImplBase_t =
57 /// The coordinates type: a `DIMENSIONS`-dimensional `std::array` of `double`.
59 /// The type of weights
61 /// Pointer type to `HistImpl_t::Fill`, for faster access.
63 /// Range.
65
67
68 /// Number of dimensions of the coordinates
69 static constexpr int GetNDim() noexcept { return DIMENSIONS; }
70
71 RHist() = default;
72 RHist(RHist &&) = default;
73 RHist(const RHist &other): fImpl(other.fImpl->Clone()), fFillFunc(other.fFillFunc)
74 {}
75
76 /// Create a histogram from an `array` of axes (`RAxisConfig`s). Example code:
77 ///
78 /// Construct a 1-dimensional histogram that can be filled with `floats`s.
79 /// The axis has 10 bins between 0. and 1. The two outermost sets of curly
80 /// braces are to reach the initialization of the `std::array` elements; the
81 /// inner one is for the initialization of a `RAxisCoordinate`.
82 ///
83 /// RHist<1,float> h1f({{ {10, 0., 1.} }});
84 ///
85 /// Construct a 2-dimensional histogram, with the first axis as before, and
86 /// the second axis having non-uniform ("irregular") binning, where all bin-
87 /// edges are specified. As this is itself an array it must be enclosed by
88 /// double curlies.
89 ///
90 /// RHist<2,int> h2i({{ {10, 0., 1.}, {{-1., 0., 1., 10., 100.}} }});
91 explicit RHist(std::array<RAxisConfig, DIMENSIONS> axes);
92
93 /// Constructor overload taking the histogram title
94 RHist(std::string_view histTitle, std::array<RAxisConfig, DIMENSIONS> axes);
95
96 /// Constructor overload that's only available for a 1-dimensional histogram.
98 explicit RHist(const RAxisConfig &xaxis): RHist(std::array<RAxisConfig, 1>{{xaxis}})
99 {}
100
101 /// Constructor overload that's only available for a 1-dimensional histogram,
102 /// also passing the histogram title.
104 RHist(std::string_view histTitle, const RAxisConfig &xaxis): RHist(histTitle, std::array<RAxisConfig, 1>{{xaxis}})
105 {}
106
107 /// Constructor overload that's only available for a 2-dimensional histogram.
109 RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis): RHist(std::array<RAxisConfig, 2>{{xaxis, yaxis}})
110 {}
111
112 /// Constructor overload that's only available for a 2-dimensional histogram,
113 /// also passing the histogram title.
115 RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis)
116 : RHist(histTitle, std::array<RAxisConfig, 2>{{xaxis, yaxis}})
117 {}
118
119 /// Constructor overload that's only available for a 3-dimensional histogram.
121 RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
122 : RHist(std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
123 {}
124
125 /// Constructor overload that's only available for a 3-dimensional histogram,
126 /// also passing the histogram title.
128 RHist(std::string_view histTitle, const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
129 : RHist(histTitle, std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
130 {}
131
132 /// Access the ImplBase_t this RHist points to.
133 ImplBase_t *GetImpl() const noexcept { return fImpl.get(); }
134
135 /// "Steal" the ImplBase_t this RHist points to.
136 std::unique_ptr<ImplBase_t> TakeImpl() && noexcept { return std::move(fImpl); }
137
138 /// Add `weight` to the bin containing coordinate `x`.
139 void Fill(const CoordArray_t &x, Weight_t weight = (Weight_t)1) noexcept { (fImpl.get()->*fFillFunc)(x, weight); }
140
141 /// For each coordinate in `xN`, add `weightN[i]` to the bin at coordinate
142 /// `xN[i]`. The sizes of `xN` and `weightN` must be the same. This is more
143 /// efficient than many separate calls to `Fill()`.
144 void FillN(const std::span<CoordArray_t> xN, const std::span<Weight_t> weightN) noexcept
145 {
146 fImpl->FillN(xN, weightN);
147 }
148
149 /// Convenience overload: `FillN()` with weight 1.
150 void FillN(const std::span<CoordArray_t> xN) noexcept { fImpl->FillN(xN); }
151
152 /// Get the number of entries this histogram was filled with.
153 int64_t GetEntries() const noexcept { return fImpl->GetStat().GetEntries(); }
154
155 /// Get the content of the bin at `x`.
156 Weight_t GetBinContent(const CoordArray_t &x) const { return fImpl->GetBinContent(x); }
157
158 /// Get the uncertainty on the content of the bin at `x`.
159 double GetBinUncertainty(const CoordArray_t &x) const { return fImpl->GetBinUncertainty(x); }
160
162
163 const_iterator end() const { return const_iterator(*fImpl, fImpl->GetNBins()); }
164
165 /// Swap *this and other.
166 ///
167 /// Very efficient; swaps the `fImpl` pointers.
169 {
170 std::swap(fImpl, other.fImpl);
171 std::swap(fFillFunc, other.fFillFunc);
172 }
173
174private:
175 std::unique_ptr<ImplBase_t> fImpl; ///< The actual histogram implementation
176 FillFunc_t fFillFunc = nullptr; ///<! Pinter to RHistImpl::Fill() member function
177
178 friend RHist HistFromImpl<>(std::unique_ptr<ImplBase_t>);
179};
180
181/// RHist with no STAT parameter uses RHistStatContent by default.
182template <int DIMENSIONS, class PRECISION>
183class RHist<DIMENSIONS, PRECISION>: public RHist<DIMENSIONS, PRECISION, RHistStatContent> {
185};
186
187/// Swap two histograms.
188///
189/// Very efficient; swaps the `fImpl` pointers.
190template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
192{
193 a.swap(b);
194};
195
196namespace Internal {
197/**
198 Generate RHist::fImpl from RHist constructor arguments.
199 */
200template <int NDIM, int IDIM, class DATA, class... PROCESSEDAXISCONFIG>
202 /// Select the template argument for the next axis type, and "recurse" into
203 /// RHistImplGen for the next axis.
204 template <RAxisConfig::EKind KIND>
205 std::unique_ptr<Detail::RHistImplBase<DATA>>
206 MakeNextAxis(std::string_view title, const std::array<RAxisConfig, NDIM> &axes,
207 PROCESSEDAXISCONFIG... processedAxisArgs)
208 {
209 using NextAxis_t = typename AxisConfigToType<KIND>::Axis_t;
210 NextAxis_t nextAxis = AxisConfigToType<KIND>()(axes[IDIM]);
211 using HistImpl_t = RHistImplGen<NDIM, IDIM + 1, DATA, PROCESSEDAXISCONFIG..., NextAxis_t>;
212 return HistImpl_t()(title, axes, processedAxisArgs..., nextAxis);
213 }
214
215 /// Make a RHistImpl-derived object reflecting the RAxisConfig array.
216 ///
217 /// Delegate to the appropriate MakeNextAxis instantiation, depending on the
218 /// axis type selected in the RAxisConfig.
219 /// \param axes - `RAxisConfig` objects describing the axis of the resulting
220 /// RHistImpl.
221 /// \param statConfig - the statConfig parameter to be passed to the RHistImpl
222 /// \param processedAxisArgs - the RAxisBase-derived axis objects describing the
223 /// axes of the resulting RHistImpl. There are `IDIM` of those; in the end
224 /// (`IDIM` == `GetNDim()`), all `axes` have been converted to
225 /// `processedAxisArgs` and the RHistImpl constructor can be invoked, passing
226 /// the `processedAxisArgs`.
227 std::unique_ptr<Detail::RHistImplBase<DATA>> operator()(std::string_view title,
228 const std::array<RAxisConfig, NDIM> &axes,
229 PROCESSEDAXISCONFIG... processedAxisArgs)
230 {
231 switch (axes[IDIM].GetKind()) {
232 case RAxisConfig::kEquidistant: return MakeNextAxis<RAxisConfig::kEquidistant>(title, axes, processedAxisArgs...);
233 case RAxisConfig::kGrow: return MakeNextAxis<RAxisConfig::kGrow>(title, axes, processedAxisArgs...);
234 case RAxisConfig::kIrregular: return MakeNextAxis<RAxisConfig::kIrregular>(title, axes, processedAxisArgs...);
235 default: R__ERROR_HERE("HIST") << "Unhandled axis kind";
236 }
237 return nullptr;
238 }
239};
240
241/// Generate RHist::fImpl from constructor arguments; recursion end.
242template <int NDIM, class DATA, class... PROCESSEDAXISCONFIG>
243/// Create the histogram, now that all axis types and initializer objects are
244/// determined.
245struct RHistImplGen<NDIM, NDIM, DATA, PROCESSEDAXISCONFIG...> {
247 std::unique_ptr<HistImplBase_t>
248 operator()(std::string_view title, const std::array<RAxisConfig, DATA::GetNDim()> &, PROCESSEDAXISCONFIG... axisArgs)
249 {
250 using HistImplt_t = Detail::RHistImpl<DATA, PROCESSEDAXISCONFIG...>;
251 return std::make_unique<HistImplt_t>(title, axisArgs...);
252 }
253};
254} // namespace Internal
255
256template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
257RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::string_view title, std::array<RAxisConfig, DIMENSIONS> axes)
258 : fImpl{std::move(
259 Internal::RHistImplGen<RHist::GetNDim(), 0,
260 Detail::RHistData<DIMENSIONS, PRECISION, std::vector<PRECISION>, STAT...>>()(
261 title, axes))}
262{
263 fFillFunc = fImpl->GetFillFunc();
264}
265
266template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
267RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::array<RAxisConfig, DIMENSIONS> axes): RHist("", axes)
268{}
269
270/// Adopt an external, stand-alone RHistImpl. The RHist will take ownership.
271template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
272RHist<DIMENSIONS, PRECISION, STAT...>
274{
275 RHist<DIMENSIONS, PRECISION, STAT...> ret;
276 ret.fFillFunc = pHistImpl->GetFillFunc();
277 std::swap(ret.fImpl, pHistImpl);
278 return ret;
279};
280
281/// \name RHist Typedefs
282///\{ Convenience typedefs (ROOT6-compatible type names)
283
284// Keep them as typedefs, to make sure old-style documentation tools can understand them.
290
296
302///\}
303
304/// Add two histograms. This is the generic, inefficient version for now; it
305/// assumes no matching axes.
306template <int DIMENSIONS, class PRECISION_TO, class PRECISION_FROM,
307 template <int D_, class P_> class... STAT_TO,
308 template <int D_, class P_> class... STAT_FROM>
310{
311 auto toImpl = to.GetImpl();
312 auto fillFuncTo = toImpl->GetFillFunc();
313 using HistFrom_t = RHist<DIMENSIONS, PRECISION_FROM, STAT_FROM...>;
314 using FromCoord_t = typename HistFrom_t::CoordArray_t;
315 using FromWeight_t = typename HistFrom_t::Weight_t;
316 auto add = [fillFuncTo, toImpl](const FromCoord_t &x, FromWeight_t c) {
317 (toImpl->*fillFuncTo)(x, c);
318 // RODO: something nice with the uncertainty - depending on whether `to` cares
319 };
320 from.GetImpl()->ApplyXC(add);
321}
322
323} // namespace Experimental
324} // namespace ROOT
325
326#endif
#define PRECISION
Definition: MnPrint.cxx:26
#define R__ERROR_HERE(GROUP)
Definition: RLogger.hxx:183
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
int type
Definition: TGX11.cxx:120
Iterates over the bins of a RHist or RHistImpl.
Interface class for RHistImpl.
Definition: RHistImpl.hxx:141
virtual void ApplyXC(std::function< void(const CoordArray_t &, Weight_t)>) const =0
Apply a function (lambda) to all bins of the histogram.
void(RHistImplBase::*)(const CoordArray_t &x, Weight_t w) FillFunc_t
Type of the Fill(x, w) function.
Definition: RHistImpl.hxx:151
Hist::CoordArray_t< DATA::GetNDim()> CoordArray_t
Type of the coordinate: a DIMENSIONS-dimensional array of doubles.
Definition: RHistImpl.hxx:146
virtual FillFunc_t GetFillFunc() const =0
Retrieve the pointer to the overridden Fill(x, w) function.
Hist::AxisIterRange_t< DIMENSIONS > AxisIterRange_t
Range type.
Definition: RHistImpl.hxx:75
Objects used to configure the different axis types.
Definition: RAxis.hxx:300
@ kGrow
represents a RAxisGrow
Definition: RAxis.hxx:304
@ kEquidistant
represents a RAxisEquidistant
Definition: RAxis.hxx:303
@ kIrregular
represents a RAxisIrregular
Definition: RAxis.hxx:305
Histogram class for histograms with DIMENSIONS dimensions, where each bin count is stored by a value ...
Definition: RHist.hxx:52
ImplBase_t * GetImpl() const noexcept
Access the ImplBase_t this RHist points to.
Definition: RHist.hxx:133
static constexpr int GetNDim() noexcept
Number of dimensions of the coordinates.
Definition: RHist.hxx:69
PRECISION Weight_t
The type of weights.
Definition: RHist.hxx:60
Weight_t GetBinContent(const CoordArray_t &x) const
Get the content of the bin at x.
Definition: RHist.hxx:156
int64_t GetEntries() const noexcept
Get the number of entries this histogram was filled with.
Definition: RHist.hxx:153
double GetBinUncertainty(const CoordArray_t &x) const
Get the uncertainty on the content of the bin at x.
Definition: RHist.hxx:159
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:115
const_iterator end() const
Definition: RHist.hxx:163
RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis)
Constructor overload that's only available for a 2-dimensional histogram.
Definition: RHist.hxx:109
typename ImplBase_t::FillFunc_t FillFunc_t
Pointer type to HistImpl_t::Fill, for faster access.
Definition: RHist.hxx:62
RHist(const RAxisConfig &xaxis, const RAxisConfig &yaxis, const RAxisConfig &zaxis)
Constructor overload that's only available for a 3-dimensional histogram.
Definition: RHist.hxx:121
typename ImplBase_t::AxisIterRange_t AxisRange_t
Range.
Definition: RHist.hxx:64
void Fill(const CoordArray_t &x, Weight_t weight=(Weight_t) 1) noexcept
Add weight to the bin containing coordinate x.
Definition: RHist.hxx:139
RHist(std::string_view histTitle, std::array< RAxisConfig, DIMENSIONS > axes)
Constructor overload taking the histogram title.
Definition: RHist.hxx:257
Detail::RHistBinIter< ImplBase_t > const_iterator
Definition: RHist.hxx:66
void FillN(const std::span< CoordArray_t > xN) noexcept
Convenience overload: FillN() with weight 1.
Definition: RHist.hxx:150
const_iterator begin() const
Definition: RHist.hxx:161
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:128
void FillN(const std::span< CoordArray_t > xN, const std::span< Weight_t > weightN) noexcept
For each coordinate in xN, add weightN[i] to the bin at coordinate xN[i].
Definition: RHist.hxx:144
void swap(RHist< DIMENSIONS, PRECISION, STAT... > &other) noexcept
Swap *this and other.
Definition: RHist.hxx:168
std::unique_ptr< ImplBase_t > fImpl
The actual histogram implementation.
Definition: RHist.hxx:175
std::unique_ptr< ImplBase_t > TakeImpl() &&noexcept
"Steal" the ImplBase_t this RHist points to.
Definition: RHist.hxx:136
RHist(const RHist &other)
Definition: RHist.hxx:73
RHist(RHist &&)=default
RHist(const RAxisConfig &xaxis)
Constructor overload that's only available for a 1-dimensional histogram.
Definition: RHist.hxx:98
RHist(std::array< RAxisConfig, DIMENSIONS > axes)
Create a histogram from an array of axes (RAxisConfigs).
Definition: RHist.hxx:267
FillFunc_t fFillFunc
! Pinter to RHistImpl::Fill() member function
Definition: RHist.hxx:176
typename ImplBase_t::CoordArray_t CoordArray_t
The coordinates type: a DIMENSIONS-dimensional std::array of double.
Definition: RHist.hxx:58
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:104
Double_t x[n]
Definition: legend1.C:17
basic_string_view< char > string_view
RCoordArray< DIMENSIONS > CoordArray_t
Definition: RHistUtils.hxx:49
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:273
void Add(RHist< DIMENSIONS, PRECISION_TO, STAT_TO... > &to, const RHist< DIMENSIONS, PRECISION_FROM, STAT_FROM... > &from)
Add two histograms.
Definition: RHist.hxx:309
void swap(RHist< DIMENSIONS, PRECISION, STAT... > &a, RHist< DIMENSIONS, PRECISION, STAT... > &b) noexcept
Swap two histograms.
Definition: RHist.hxx:191
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Converts a RAxisConfig of whatever kind to the corresponding RAxisBase-derived object.
Definition: RAxis.hxx:798
std::unique_ptr< HistImplBase_t > operator()(std::string_view title, const std::array< RAxisConfig, DATA::GetNDim()> &, PROCESSEDAXISCONFIG... axisArgs)
Definition: RHist.hxx:248
Generate RHist::fImpl from RHist constructor arguments.
Definition: RHist.hxx:201
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:206
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:227
auto * a
Definition: textangle.C:12