ROOT  6.06/09
Reference Guide
THist.h
Go to the documentation of this file.
1 /// \file ROOT/THist.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 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_THist
16 #define ROOT7_THist
17 
18 #include "ROOT/RArrayView.h"
19 #include "ROOT/TAxis.h"
20 #include "ROOT/TDrawable.h"
21 #include "ROOT/THistBinIter.h"
22 #include "ROOT/THistDrawable.h"
23 #include "ROOT/THistImpl.h"
24 #include "ROOT/THistStats.h"
25 #include "ROOT/TCoopPtr.h"
26 #include <initializer_list>
27 
28 namespace ROOT {
29 
30 // fwd declare for fwd declare for friend declaration in THist...
31 template <int DIMENSIONS, class PRECISION> class THist;
32 
33 // fwd declare for friend declaration in THist.
34 template <int DIMENSIONS, class PRECISION>
35 class ROOT::THist<DIMENSIONS, PRECISION>
36 HistFromImpl(std::unique_ptr<typename ROOT::THist<DIMENSIONS, PRECISION>::ImplBase_t> pHistImpl);
37 
38 template <int DIMENSIONS, class PRECISION>
39 void swap(ROOT::THist<DIMENSIONS, PRECISION> &a,
40  ROOT::THist<DIMENSIONS, PRECISION> &b) noexcept;
41 
42 
43 /**
44  \class THist
45  Histogram class for histograms with `DIMENSIONS` dimensions, where each bin
46  count is stored by a value of type `PRECISION`.
47 
48  A histogram counts occurrences of values or n-dimensional combinations thereof.
49  Contrary to for instance a `TTree`, a histogram combines adjacent values. The
50  resolution of this combination is defined by the binning, see e.g.
51  http://www.wikiwand.com/en/Histogram
52  */
53 
54 template<int DIMENSIONS, class PRECISION>
55 class THist {
56 public:
57  /// The type of the `Detail::THistImplBase` of this histogram.
59  /// The coordinates type: a `DIMENSIONS`-dimensional `std::array` of `double`.
60  using Coord_t = typename ImplBase_t::Coord_t;
61  /// The type of weights (`PRECISION`)
62  using Weight_t = typename ImplBase_t::Weight_t;
63  /// Pointer type to `HistImpl_t::Fill`, for faster access.
65 
67 
68  THist() = default;
69 
70  /// Create a histogram from an `array` of axes (`TAxisConfig`s) and possibly
71  /// an initial `STATISTICS` object. The latter is usually just fine when
72  /// not passed (i.e. default-constructed). Example code:
73  ///
74  /// Construct a 1-dimensional histogram that can be filled with `floats`s.
75  /// The axis has 10 bins between 0. and 1. The two outermost sets of curly
76  /// braces are to reach the initialization of the `std::array` elements; the
77  /// inner one is for the initialization of a `TAxisCoordinate`.
78  ///
79  /// THist<1,float> h1f({{ {10, 0., 1.} }});
80  ///
81  /// Construct a 2-dimensional histogram, with the first axis as before, and
82  /// the second axis having non-uniform ("irregular") binning, where all bin-
83  /// edges are specified. As this is itself an array it must be enclosed by
84  /// double curlies.
85  ///
86  /// THist<2,int> h2i({{ {10, 0., 1.}, {{-1., 0., 1., 10., 100.}} }});
87  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>>
88  THist(std::array<TAxisConfig, DIMENSIONS> axes,
89  STATISTICS statConfig = STATISTICS());
90 
91  /// Constructor overload taking histogram and axis titles
92  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>>
93  THist(std::array<TAxisConfig, DIMENSIONS> axes,
94  std::string_view histTitle,
95  std::array<std::string_view, DIMENSIONS> axisTitles,
96  STATISTICS statConfig = STATISTICS());
97 
98  /// Constructor overload that's only available for DIMENSIONS == 1.
99  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
100  class = typename std::enable_if<DIMENSIONS == 1>>
101  THist(const TAxisConfig& xaxis, STATISTICS statConfig = STATISTICS()):
102  THist({{xaxis}}, statConfig) {}
103 
104  /// Constructor overload that's only available for DIMENSIONS == 1, also
105  /// passing histogram and axis title.
106  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
107  class = typename std::enable_if<DIMENSIONS == 1>>
108  THist(const TAxisConfig& xaxis, std::string_view histTitle,
109  std::string_view xAxisTitle,
110  STATISTICS statConfig = STATISTICS()):
111  THist({{xaxis}}, histTitle, {{xAxisTitle}}, statConfig) {}
112 
113  /// Constructor overload that's only available for DIMENSIONS == 2.
114  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
115  class = typename std::enable_if<DIMENSIONS == 2>>
116  THist(const TAxisConfig& xaxis, const TAxisConfig& yaxis,
117  STATISTICS statConfig = STATISTICS()):
118  THist({{xaxis, yaxis}}, statConfig) {}
119 
120  /// Constructor overload that's only available for DIMENSIONS == 2, also
121  /// passing histogram and axis titles.
122  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
123  class = typename std::enable_if<DIMENSIONS == 2>>
124  THist(const TAxisConfig& xaxis, const TAxisConfig& yaxis,
125  std::string_view histTitle,
126  std::string_view xAxisTitle, std::string_view yAxisTitle,
127  STATISTICS statConfig = STATISTICS()):
128  THist({{xaxis, yaxis}}, histTitle, {{xAxisTitle, yAxisTitle}}, statConfig) {}
129 
130  /// Constructor overload that's only available for DIMENSIONS == 3.
131  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
132  class = typename std::enable_if<DIMENSIONS == 3>>
133  THist(const TAxisConfig& xaxis, const TAxisConfig& yaxis,
134  const TAxisConfig& zaxis, STATISTICS statConfig = STATISTICS()):
135  THist({{xaxis, yaxis, zaxis}}, statConfig) {}
136 
137 
138  template<class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>,
139  class = typename std::enable_if<DIMENSIONS == 3>>
140  THist(const TAxisConfig& xaxis, const TAxisConfig& yaxis,
141  const TAxisConfig& zaxis,
142  std::string_view histTitle,
143  std::string_view xAxisTitle, std::string_view yAxisTitle,
144  std::string_view zAxisTitle,
145  STATISTICS statConfig = STATISTICS()):
146  THist({{xaxis, yaxis, zaxis}}, {{xAxisTitle, yAxisTitle, zAxisTitle}},
147  statConfig) {}
148 
149 
150  /// Number of dimensions of the coordinates
151  static constexpr int GetNDim() noexcept { return DIMENSIONS; }
152 
153  /// Access the ImplBase_t this THist points to.
154  ImplBase_t* GetImpl() const noexcept { return fImpl.get(); }
155 
156  /// Add `weight` to the bin containing coordinate `x`.
157  void Fill(const Coord_t &x, Weight_t weight = 1.) noexcept {
158  (fImpl.get()->*fFillFunc)(x, weight);
159  }
160 
161  /// For each coordinate in `xN`, add `weightN[i]` to the bin at coordinate
162  /// `xN[i]`. The sizes of `xN` and `weightN` must be the same. This is more
163  /// efficient than many separate calls to `Fill()`.
165  const std::array_view<Weight_t> weightN) noexcept {
166  fImpl->FillN(xN, weightN);
167  }
168 
169  /// Convenience overload: `FillN()` with weight 1.
170  void FillN(const std::array_view<Coord_t> xN) noexcept {
171  fImpl->FillN(xN);
172  }
173 
174  /// Get the number of entries this histogram was filled with.
175  int64_t GetEntries() const noexcept { return fImpl->GetStat().GetEntries(); }
176 
177  const_iterator begin() const { return const_iterator(0); }
178  const_iterator end() const { return const_iterator(fImpl->GetNBins()); }
179 
180 private:
181  FillFunc_t fFillFunc = nullptr; ///< Pinter to THistImpl::Fill() member function
182  std::unique_ptr<ImplBase_t> fImpl; ///< The actual histogram implementation
183  std::string fTitle; ///< Title of this histogram
184  std::array<std::string, DIMENSIONS> fAxisTitles; ///< Title of each axis
185 
186  friend THist HistFromImpl<>(std::unique_ptr<ImplBase_t>);
187  friend void swap<>(THist<DIMENSIONS, PRECISION> &a,
188  THist<DIMENSIONS, PRECISION> &b) noexcept;
189 
190 };
191 
192 /// Swap two histograms.
193 ///
194 /// Very efficient; swaps the `fImpl` pointers.
195 template <int DIMENSIONS, class PRECISION>
197  THist<DIMENSIONS, PRECISION> &b) noexcept {
198  std::swap(a.fImpl, b.fImpl);
199  std::swap(a.fFillFunc, b.fFillFunc);
200 };
201 
202 
203 /// Create a TCoopPtr of a THist.
204 //
205 // As make_xyz cannot deal with initializer_lists, we need to expose THist's
206 // constructor arguments and take THist's template arguments.
207 template <int DIMENSIONS, class PRECISION, class STATISTICS = THistStatUncertainty<DIMENSIONS, PRECISION>>
208 TCoopPtr<THist<DIMENSIONS, PRECISION>>
209 MakeCoOwnedHist(std::array<TAxisConfig, DIMENSIONS> axes, STATISTICS statConfig = STATISTICS()) {
210  THist<DIMENSIONS, PRECISION> hist(axes, statConfig);
211  return MakeCoop(std::move(hist));
212 };
213 
214 
215 /// Adopt an external, stand-alone THistImpl. The THist will take ownership.
216 template <int DIMENSIONS, class PRECISION>
217 THist<DIMENSIONS, PRECISION>
218 HistFromImpl(std::unique_ptr<typename THist<DIMENSIONS, PRECISION>::ImplBase_t> pHistImpl) {
220  ret.fFillFunc = pHistImpl->GetFillFunc();
221  std::swap(ret.fImpl, pHistImpl);
222  return ret;
223 };
224 
225 
226 namespace Internal {
227 /**
228  Generate THist::fImpl from THist constructor arguments.
229  */
230 template<int DIMENSIONS, int IDIM, class PRECISION, class STATISTICS,
231  class... PROCESSEDAXISCONFIG>
233  /// Select the template argument for the next axis type, and "recurse" into
234  /// HistImplGen_t for the next axis.
235  template<TAxisConfig::EKind KIND>
236  std::unique_ptr<Detail::THistImplBase<DIMENSIONS, PRECISION>>
237  MakeNextAxis(const std::array<TAxisConfig, DIMENSIONS> &axes,
238  const STATISTICS& statConfig,
239  PROCESSEDAXISCONFIG... processedAxisArgs) {
240  typename AxisConfigToType<KIND>::Axis_t nextAxis
241  = AxisConfigToType<KIND>()(axes[IDIM]);
242  return HistImplGen_t<DIMENSIONS, IDIM + 1, PRECISION, STATISTICS,
243  PROCESSEDAXISCONFIG..., typename AxisConfigToType<KIND>::Axis_t>()
244  (axes, statConfig, processedAxisArgs..., nextAxis);
245  }
246 
247  /// Make a THistImpl-derived object reflecting the TAxisConfig array.
248  ///
249  /// Delegate to the appropriate MakeNextAxis instantiation, depending on the
250  /// axis type selected in the TAxisConfig.
251  /// \param axes - `TAxisConfig` objects describing the axis of the resulting
252  /// THistImpl.
253  /// \param statConfig - the statConfig parameter to be passed to the THistImpl
254  /// \param processedAxisArgs - the TAxisBase-derived axis objects describing the
255  /// axes of the resulting THistImpl. There are `IDIM` of those; in the end
256  /// (`IDIM` == `DIMENSIONS`), all `axes` have been converted to
257  /// `processedAxisArgs` and the THistImpl constructor can be invoked, passing
258  /// the `processedAxisArgs`.
259  std::unique_ptr<Detail::THistImplBase<DIMENSIONS, PRECISION>>
260  operator()(const std::array<TAxisConfig, DIMENSIONS> &axes,
261  const STATISTICS& statConfig,
262  PROCESSEDAXISCONFIG... processedAxisArgs) {
263  switch (axes[IDIM].GetKind()) {
265  return MakeNextAxis<TAxisConfig::kEquidistant>(axes, statConfig,
266  processedAxisArgs...);
267  case TAxisConfig::kGrow:
268  return MakeNextAxis<TAxisConfig::kGrow>(axes, statConfig,
269  processedAxisArgs...);
271  return MakeNextAxis<TAxisConfig::kIrregular>(axes, statConfig,
272  processedAxisArgs...);
273  default:
274  R__ERROR_HERE("HIST") << "Unhandled axis kind";
275  }
276  return nullptr;
277  }
278 };
279 
280 /// Generate THist::fImpl from constructor arguments; recursion end.
281 template<int DIMENSIONS, class PRECISION, class STATISTICS,
282  class... PROCESSEDAXISCONFIG>
283 /// Create the histogram, now that all axis types and initializier objects are
284 /// determined.
285 struct HistImplGen_t<DIMENSIONS, DIMENSIONS, PRECISION, STATISTICS,
286  PROCESSEDAXISCONFIG...> {
287  std::unique_ptr<Detail::THistImplBase<DIMENSIONS, PRECISION>>
288  operator()(const std::array<TAxisConfig, DIMENSIONS> &, const STATISTICS& statConfig,
289  PROCESSEDAXISCONFIG... axisArgs) {
290  using HistImplt_t
291  = Detail::THistImpl<DIMENSIONS, PRECISION, STATISTICS, PROCESSEDAXISCONFIG...>;
292  return std::make_unique<HistImplt_t>(statConfig, axisArgs...);
293  }
294 };
295 } // namespace Internal
296 
297 
298 template<int DIMENSIONS, class PRECISION>
299 template<class STATISTICS /*= THistStatUncertainty<DIMENSIONS, PRECISION>*/>
300 THist<DIMENSIONS, PRECISION>::THist(std::array<TAxisConfig, DIMENSIONS> axes,
301  STATISTICS statConfig /*= STATISTICS()*/):
302  fImpl{std::move(
304  statConfig))},
305  fFillFunc{} {
306  fFillFunc = fImpl->GetFillFunc();
307 }
308 
309 /// \name THist Typedefs
310 ///\{ Convenience typedefs (ROOT6-compatible type names)
311 
312 // Keep them as typedefs, to make sure old-style documentation tools can
313 // understand them.
319 
325 
331 ///\}
332 
333 
334 template <int DIMENSION, class PRECISIONA, class PRECISIONB>
336  using ImplTo_t = typename THist<DIMENSION, PRECISIONA>::ImplBase_t;
337  using ImplFrom_t = typename THist<DIMENSION, PRECISIONB>::ImplBase_t;
338  ImplTo_t* implTo = to.GetImpl();
339  ImplFrom_t* implFrom = from.GetImpl();
340  // TODO: move into THistImpl; the loop iteration should not go through virt interfaces!
341  for (auto&& bin: from) {
342  to.Fill(implFrom->GetBinCenter(*bin), implFrom->GetBinContent(*bin));
343  }
344 };
345 
346 template <int DIMENSION, class PRECISION>
347 std::unique_ptr<Internal::TDrawable>
349  THistDrawOptions<DIMENSION> opts = {}) {
350  return std::make_unique<Internal::THistDrawable<DIMENSION, PRECISION>>(hist, opts);
351 }
352 
353 } // namespace ROOT
354 
355 #endif
Generate THist::fImpl from THist constructor arguments.
Definition: THist.h:232
void FillN(const std::array_view< Coord_t > xN) noexcept
Convenience overload: FillN() with weight 1.
Definition: THist.h:170
PRECISION Weight_t
Type of the bin content (and thus weights).
Definition: THistImpl.h:119
std::unique_ptr< Internal::TDrawable > GetDrawable(TCoopPtr< THist< DIMENSION, PRECISION >> hist, THistDrawOptions< DIMENSION > opts={})
Definition: THist.h:348
void Add(THist< DIMENSION, PRECISIONA > &to, THist< DIMENSION, PRECISIONB > &from)
Definition: THist.h:335
THist< 2, double > TH2D
Definition: THist.h:320
Small helper to encapsulate whether to return the value pointed to by the iterator or its address...
Objects used to configure the different axis types.
Definition: TAxis.h:562
FillFunc_t fFillFunc
Pinter to THistImpl::Fill() member function.
Definition: THist.h:181
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
THist< 2, float > TH2F
Definition: THist.h:321
void swap(ROOT::THist< DIMENSIONS, PRECISION > &a, ROOT::THist< DIMENSIONS, PRECISION > &b) noexcept
Swap two histograms.
Definition: THist.h:196
void FillN(const std::array_view< Coord_t > xN, const std::array_view< Weight_t > weightN) noexcept
For each coordinate in xN, add weightN[i] to the bin at coordinate xN[i].
Definition: THist.h:164
THist< 1, float > TH1F
Definition: THist.h:315
THist< 1, int > TH1I
Definition: THist.h:317
THist< 3, int > TH3I
Definition: THist.h:329
Converts a TAxisConfig of whatever kind to the corresponding TAxisBase-derived object.
Definition: TAxis.h:659
TArc * a
Definition: textangle.C:12
class ROOT::THist< DIMENSIONS, PRECISION > HistFromImpl(std::unique_ptr< typename ROOT::THist< DIMENSIONS, PRECISION >::ImplBase_t > pHistImpl)
Adopt an external, stand-alone THistImpl. The THist will take ownership.
Definition: THist.h:218
TCoopPtr< POINTEE > MakeCoop(ARGS &&...args)
Create an object of type POINTEE on the heap, and build a TCoopPtr for it.
Definition: TCoopPtr.h:120
std::unique_ptr< ImplBase_t > fImpl
The actual histogram implementation.
Definition: THist.h:182
STL namespace.
int64_t GetEntries() const noexcept
Get the number of entries this histogram was filled with.
Definition: THist.h:175
THist< 1, double > TH1D
Definition: THist.h:314
ImplBase_t * GetImpl() const noexcept
Access the ImplBase_t this THist points to.
Definition: THist.h:154
THist(const TAxisConfig &xaxis, const TAxisConfig &yaxis, std::string_view histTitle, std::string_view xAxisTitle, std::string_view yAxisTitle, STATISTICS statConfig=STATISTICS())
Constructor overload that's only available for DIMENSIONS == 2, also passing histogram and axis title...
Definition: THist.h:124
std::unique_ptr< Detail::THistImplBase< DIMENSIONS, PRECISION > > operator()(const std::array< TAxisConfig, DIMENSIONS > &, const STATISTICS &statConfig, PROCESSEDAXISCONFIG...axisArgs)
Definition: THist.h:288
typename THistImplPrecisionAgnosticBase< DIMENSIONS >::Coord_t Coord_t
Type of a coordinate: an array of DIMENSIONS doubles.
Definition: THistImpl.h:117
THist< 3, float > TH3F
Definition: THist.h:327
THist(const TAxisConfig &xaxis, const TAxisConfig &yaxis, const TAxisConfig &zaxis, STATISTICS statConfig=STATISTICS())
Constructor overload that's only available for DIMENSIONS == 3.
Definition: THist.h:133
const_iterator begin() const
Definition: THist.h:177
Double_t x[n]
Definition: legend1.C:17
#define PRECISION
Definition: MnPrint.cxx:26
typename ImplBase_t::Weight_t Weight_t
The type of weights (PRECISION)
Definition: THist.h:62
THist(const TAxisConfig &xaxis, const TAxisConfig &yaxis, STATISTICS statConfig=STATISTICS())
Constructor overload that's only available for DIMENSIONS == 2.
Definition: THist.h:116
THist< 2, char > TH2C
Definition: THist.h:322
std::array< std::string, DIMENSIONS > fAxisTitles
Title of each axis.
Definition: THist.h:184
represents a TAxisEquidistant
Definition: TAxis.h:565
void(THistImplBase::*)(const Coord_t &x, Weight_t w) FillFunc_t
Type of the Fill(x, w) function.
Definition: THistImpl.h:121
std::unique_ptr< Detail::THistImplBase< DIMENSIONS, PRECISION > > operator()(const std::array< TAxisConfig, DIMENSIONS > &axes, const STATISTICS &statConfig, PROCESSEDAXISCONFIG...processedAxisArgs)
Make a THistImpl-derived object reflecting the TAxisConfig array.
Definition: THist.h:260
THist(const TAxisConfig &xaxis, STATISTICS statConfig=STATISTICS())
Constructor overload that's only available for DIMENSIONS == 1.
Definition: THist.h:101
THist(const TAxisConfig &xaxis, const TAxisConfig &yaxis, const TAxisConfig &zaxis, std::string_view histTitle, std::string_view xAxisTitle, std::string_view yAxisTitle, std::string_view zAxisTitle, STATISTICS statConfig=STATISTICS())
Definition: THist.h:140
represents a TAxisGrow
Definition: TAxis.h:566
THist< 1, char > TH1C
Definition: THist.h:316
THist< 2, int > TH2I
Definition: THist.h:323
THist< 3, double > TH3D
Definition: THist.h:326
typename ImplBase_t::Coord_t Coord_t
The coordinates type: a DIMENSIONS-dimensional std::array of double.
Definition: THist.h:60
THist()=default
std::string fTitle
Title of this histogram.
Definition: THist.h:183
const_iterator end() const
Definition: THist.h:178
Drawing options for a histogram with DIMENSIONS.
std::unique_ptr< Detail::THistImplBase< DIMENSIONS, PRECISION > > MakeNextAxis(const std::array< TAxisConfig, DIMENSIONS > &axes, const STATISTICS &statConfig, PROCESSEDAXISCONFIG...processedAxisArgs)
Select the template argument for the next axis type, and "recurse" into HistImplGen_t for the next ax...
Definition: THist.h:237
typedef void((*Func_t)())
A bin iterator taking a predicate whether it should skip a bin.
Definition: THistBinIter.h:89
THist< 1, int64_t > TH1LL
Definition: THist.h:318
#define R__ERROR_HERE(GROUP)
Definition: TLogger.h:125
typename ImplBase_t::FillFunc_t FillFunc_t
Pointer type to HistImpl_t::Fill, for faster access.
Definition: THist.h:64
void Fill(const Coord_t &x, Weight_t weight=1.) noexcept
Add weight to the bin containing coordinate x.
Definition: THist.h:157
THist< 3, char > TH3C
Definition: THist.h:328
represents a TAxisIrregular
Definition: TAxis.h:567
TCoopPtr< THist< DIMENSIONS, PRECISION > > MakeCoOwnedHist(std::array< TAxisConfig, DIMENSIONS > axes, STATISTICS statConfig=STATISTICS())
Create a TCoopPtr of a THist.
Definition: THist.h:209
Interface class for THistImpl.
Definition: THistImpl.h:114
THist< 3, int64_t > TH3LL
Definition: THist.h:330
THist< 2, int64_t > TH2LL
Definition: THist.h:324
Histogram class for histograms with DIMENSIONS dimensions, where each bin count is stored by a value ...
Definition: THist.h:31
Internal::THistBinIter< Internal::HistIterFullRange_t > const_iterator
Definition: THist.h:66
Several pointers point to the same object, any of them can delete the object, setting all of them to ...
Definition: TCoopPtr.h:46
static constexpr int GetNDim() noexcept
Number of dimensions of the coordinates.
Definition: THist.h:151
THist(const TAxisConfig &xaxis, std::string_view histTitle, std::string_view xAxisTitle, STATISTICS statConfig=STATISTICS())
Constructor overload that's only available for DIMENSIONS == 1, also passing histogram and axis title...
Definition: THist.h:108