Logo ROOT   6.10/00
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TDFActionHelpers.hxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Danilo Piparo CERN 12/2016
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_TDFOPERATIONS
12 #define ROOT_TDFOPERATIONS
13 
14 #include "ROOT/TDFUtils.hxx"
15 #include "ROOT/TThreadedObject.hxx"
16 #include "TH1.h"
17 
18 #include <algorithm>
19 #include <memory>
20 #include <stdexcept>
21 #include <type_traits>
22 #include <vector>
23 
24 /// \cond HIDDEN_SYMBOLS
25 
26 namespace ROOT {
27 namespace Internal {
28 namespace TDF {
29 
30 using Count_t = unsigned long;
31 using Hist_t = ::TH1F;
32 
33 template <typename F>
34 class ForeachSlotHelper {
35  F fCallable;
36 
37 public:
38  using BranchTypes_t = typename TRemoveFirst<typename TFunctionTraits<F>::Args_t>::Types_t;
39  ForeachSlotHelper(F &&f) : fCallable(f) {}
40 
41  void Init(TTreeReader*, unsigned int) {}
42 
43  template <typename... Args>
44  void Exec(unsigned int slot, Args &&... args)
45  {
46  // check that the decayed types of Args are the same as the branch types
47  static_assert(std::is_same<TTypeList<typename std::decay<Args>::type...>, BranchTypes_t>::value, "");
48  fCallable(slot, std::forward<Args>(args)...);
49  }
50 
51  void Finalize() { /* noop */}
52 };
53 
54 class CountHelper {
55  std::shared_ptr<unsigned int> fResultCount;
56  std::vector<Count_t> fCounts;
57 
58 public:
59  using BranchTypes_t = TTypeList<>;
60  CountHelper(const std::shared_ptr<unsigned int> &resultCount, unsigned int nSlots);
61  void Init(TTreeReader*, unsigned int) {}
62  void Exec(unsigned int slot);
63  void Finalize();
64 };
65 
66 class FillHelper {
67  // this sets a total initial size of 16 MB for the buffers (can increase)
68  static constexpr unsigned int fgTotalBufSize = 2097152;
69  using BufEl_t = double;
70  using Buf_t = std::vector<BufEl_t>;
71 
72  std::vector<Buf_t> fBuffers;
73  std::vector<Buf_t> fWBuffers;
74  std::shared_ptr<Hist_t> fResultHist;
75  unsigned int fNSlots;
76  unsigned int fBufSize;
77  Buf_t fMin;
78  Buf_t fMax;
79 
80  void UpdateMinMax(unsigned int slot, double v);
81 
82 public:
83  FillHelper(const std::shared_ptr<Hist_t> &h, unsigned int nSlots);
84  void Init(TTreeReader*, unsigned int) {}
85  void Exec(unsigned int slot, double v);
86  void Exec(unsigned int slot, double v, double w);
87 
88  template <typename T, typename std::enable_if<TIsContainer<T>::fgValue, int>::type = 0>
89  void Exec(unsigned int slot, const T &vs)
90  {
91  auto &thisBuf = fBuffers[slot];
92  for (auto &v : vs) {
93  UpdateMinMax(slot, v);
94  thisBuf.emplace_back(v); // TODO: Can be optimised in case T == BufEl_t
95  }
96  }
97 
98  template <typename T, typename W,
99  typename std::enable_if<TIsContainer<T>::fgValue && TIsContainer<W>::fgValue, int>::type = 0>
100  void Exec(unsigned int slot, const T &vs, const W &ws)
101  {
102  auto &thisBuf = fBuffers[slot];
103  for (auto &v : vs) {
104  UpdateMinMax(slot, v);
105  thisBuf.emplace_back(v); // TODO: Can be optimised in case T == BufEl_t
106  }
107 
108  auto &thisWBuf = fWBuffers[slot];
109  for (auto &w : ws) {
110  thisWBuf.emplace_back(w); // TODO: Can be optimised in case T == BufEl_t
111  }
112  }
113 
114  void Finalize();
115 };
116 
117 extern template void FillHelper::Exec(unsigned int, const std::vector<float> &);
118 extern template void FillHelper::Exec(unsigned int, const std::vector<double> &);
119 extern template void FillHelper::Exec(unsigned int, const std::vector<char> &);
120 extern template void FillHelper::Exec(unsigned int, const std::vector<int> &);
121 extern template void FillHelper::Exec(unsigned int, const std::vector<unsigned int> &);
122 extern template void FillHelper::Exec(unsigned int, const std::vector<float> &, const std::vector<float> &);
123 extern template void FillHelper::Exec(unsigned int, const std::vector<double> &, const std::vector<double> &);
124 extern template void FillHelper::Exec(unsigned int, const std::vector<char> &, const std::vector<char> &);
125 extern template void FillHelper::Exec(unsigned int, const std::vector<int> &, const std::vector<int> &);
126 extern template void FillHelper::Exec(unsigned int, const std::vector<unsigned int> &,
127  const std::vector<unsigned int> &);
128 
129 template <typename HIST = Hist_t>
130 class FillTOHelper {
131  std::unique_ptr<TThreadedObject<HIST>> fTo;
132 
133 public:
134  FillTOHelper(FillTOHelper &&) = default;
135 
136  FillTOHelper(const std::shared_ptr<HIST> &h, unsigned int nSlots) : fTo(new TThreadedObject<HIST>(*h))
137  {
138  fTo->SetAtSlot(0, h);
139  // Initialise all other slots
140  for (unsigned int i = 0; i < nSlots; ++i) {
141  fTo->GetAtSlot(i);
142  }
143  }
144 
145  void Init(TTreeReader*, unsigned int) {}
146 
147  void Exec(unsigned int slot, double x0) // 1D histos
148  {
149  fTo->GetAtSlotUnchecked(slot)->Fill(x0);
150  }
151 
152  void Exec(unsigned int slot, double x0, double x1) // 1D weighted and 2D histos
153  {
154  fTo->GetAtSlotUnchecked(slot)->Fill(x0, x1);
155  }
156 
157  void Exec(unsigned int slot, double x0, double x1, double x2) // 2D weighted and 3D histos
158  {
159  fTo->GetAtSlotUnchecked(slot)->Fill(x0, x1, x2);
160  }
161 
162  void Exec(unsigned int slot, double x0, double x1, double x2, double x3) // 3D weighted histos
163  {
164  fTo->GetAtSlotUnchecked(slot)->Fill(x0, x1, x2, x3);
165  }
166 
167  template <typename X0, typename std::enable_if<TIsContainer<X0>::fgValue, int>::type = 0>
168  void Exec(unsigned int slot, const X0 &x0s)
169  {
170  auto thisSlotH = fTo->GetAtSlotUnchecked(slot);
171  for (auto &x0 : x0s) {
172  thisSlotH->Fill(x0); // TODO: Can be optimised in case T == vector<double>
173  }
174  }
175 
176  template <typename X0, typename X1,
177  typename std::enable_if<TIsContainer<X0>::fgValue && TIsContainer<X1>::fgValue, int>::type = 0>
178  void Exec(unsigned int slot, const X0 &x0s, const X1 &x1s)
179  {
180  auto thisSlotH = fTo->GetAtSlotUnchecked(slot);
181  if (x0s.size() != x1s.size()) {
182  throw std::runtime_error("Cannot fill histogram with values in containers of different sizes.");
183  }
184  auto x0sIt = std::begin(x0s);
185  const auto x0sEnd = std::end(x0s);
186  auto x1sIt = std::begin(x1s);
187  for (; x0sIt != x0sEnd; x0sIt++, x1sIt++) {
188  thisSlotH->Fill(*x0sIt, *x1sIt); // TODO: Can be optimised in case T == vector<double>
189  }
190  }
191 
192  template <typename X0, typename X1, typename X2,
193  typename std::enable_if<
194  TIsContainer<X0>::fgValue && TIsContainer<X1>::fgValue && TIsContainer<X2>::fgValue, int>::type = 0>
195  void Exec(unsigned int slot, const X0 &x0s, const X1 &x1s, const X2 &x2s)
196  {
197  auto thisSlotH = fTo->GetAtSlotUnchecked(slot);
198  if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size())) {
199  throw std::runtime_error("Cannot fill histogram with values in containers of different sizes.");
200  }
201  auto x0sIt = std::begin(x0s);
202  const auto x0sEnd = std::end(x0s);
203  auto x1sIt = std::begin(x1s);
204  auto x2sIt = std::begin(x2s);
205  for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++) {
206  thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt); // TODO: Can be optimised in case T == vector<double>
207  }
208  }
209  template <typename X0, typename X1, typename X2, typename X3,
210  typename std::enable_if<TIsContainer<X0>::fgValue && TIsContainer<X1>::fgValue &&
211  TIsContainer<X2>::fgValue && TIsContainer<X3>::fgValue,
212  int>::type = 0>
213  void Exec(unsigned int slot, const X0 &x0s, const X1 &x1s, const X2 &x2s, const X3 &x3s)
214  {
215  auto thisSlotH = fTo->GetAtSlotUnchecked(slot);
216  if (!(x0s.size() == x1s.size() && x1s.size() == x2s.size() && x1s.size() == x3s.size())) {
217  throw std::runtime_error("Cannot fill histogram with values in containers of different sizes.");
218  }
219  auto x0sIt = std::begin(x0s);
220  const auto x0sEnd = std::end(x0s);
221  auto x1sIt = std::begin(x1s);
222  auto x2sIt = std::begin(x2s);
223  auto x3sIt = std::begin(x3s);
224  for (; x0sIt != x0sEnd; x0sIt++, x1sIt++, x2sIt++, x3sIt++) {
225  thisSlotH->Fill(*x0sIt, *x1sIt, *x2sIt, *x3sIt); // TODO: Can be optimised in case T == vector<double>
226  }
227  }
228  void Finalize() { fTo->Merge(); }
229 };
230 
231 // note: changes to this class should probably be replicated in its partial
232 // specialization below
233 template <typename T, typename COLL>
234 class TakeHelper {
235  std::vector<std::shared_ptr<COLL>> fColls;
236 
237 public:
238  using BranchTypes_t = TTypeList<T>;
239  TakeHelper(const std::shared_ptr<COLL> &resultColl, unsigned int nSlots)
240  {
241  fColls.emplace_back(resultColl);
242  for (unsigned int i = 1; i < nSlots; ++i) fColls.emplace_back(std::make_shared<COLL>());
243  }
244 
245  void Init(TTreeReader*, unsigned int) {}
246 
247  template <typename V, typename std::enable_if<!TIsContainer<V>::fgValue, int>::type = 0>
248  void Exec(unsigned int slot, V v)
249  {
250  fColls[slot]->emplace_back(v);
251  }
252 
253  template <typename V, typename std::enable_if<TIsContainer<V>::fgValue, int>::type = 0>
254  void Exec(unsigned int slot, const V &vs)
255  {
256  auto thisColl = fColls[slot];
257  thisColl.insert(std::begin(thisColl), std::begin(vs), std::begin(vs));
258  }
259 
260  void Finalize()
261  {
262  auto rColl = fColls[0];
263  for (unsigned int i = 1; i < fColls.size(); ++i) {
264  auto &coll = fColls[i];
265  for (T &v : *coll) {
266  rColl->emplace_back(v);
267  }
268  }
269  }
270 };
271 
272 // note: changes to this class should probably be replicated in its unspecialized
273 // declaration above
274 template <typename T>
275 class TakeHelper<T, std::vector<T>> {
276  std::vector<std::shared_ptr<std::vector<T>>> fColls;
277 
278 public:
279  using BranchTypes_t = TTypeList<T>;
280  TakeHelper(const std::shared_ptr<std::vector<T>> &resultColl, unsigned int nSlots)
281  {
282  fColls.emplace_back(resultColl);
283  for (unsigned int i = 1; i < nSlots; ++i) {
284  auto v = std::make_shared<std::vector<T>>();
285  v->reserve(1024);
286  fColls.emplace_back(v);
287  }
288  }
289 
290  void Init(TTreeReader*, unsigned int) {}
291 
292  template <typename V, typename std::enable_if<!TIsContainer<V>::fgValue, int>::type = 0>
293  void Exec(unsigned int slot, V v)
294  {
295  fColls[slot]->emplace_back(v);
296  }
297 
298  template <typename V, typename std::enable_if<TIsContainer<V>::fgValue, int>::type = 0>
299  void Exec(unsigned int slot, const V &vs)
300  {
301  auto thisColl = fColls[slot];
302  thisColl->insert(std::begin(thisColl), std::begin(vs), std::begin(vs));
303  }
304 
305  void Finalize()
306  {
307  ULong64_t totSize = 0;
308  for (auto &coll : fColls) totSize += coll->size();
309  auto rColl = fColls[0];
310  rColl->reserve(totSize);
311  for (unsigned int i = 1; i < fColls.size(); ++i) {
312  auto &coll = fColls[i];
313  rColl->insert(rColl->end(), coll->begin(), coll->end());
314  }
315  }
316 };
317 
318 template <typename F, typename T>
319 class ReduceHelper {
320  F fReduceFun;
321  std::shared_ptr<T> fReduceRes;
322  std::vector<T> fReduceObjs;
323 
324 public:
325  using BranchTypes_t = TTypeList<T>;
326  ReduceHelper(F &&f, const std::shared_ptr<T> &reduceRes, unsigned int nSlots)
327  : fReduceFun(std::move(f)), fReduceRes(reduceRes), fReduceObjs(nSlots, *reduceRes)
328  {
329  }
330 
331  void Init(TTreeReader*, unsigned int) {}
332 
333  void Exec(unsigned int slot, const T &value) { fReduceObjs[slot] = fReduceFun(fReduceObjs[slot], value); }
334 
335  void Finalize()
336  {
337  for (auto &t : fReduceObjs) *fReduceRes = fReduceFun(*fReduceRes, t);
338  }
339 };
340 
341 class MinHelper {
342  std::shared_ptr<double> fResultMin;
343  std::vector<double> fMins;
344 
345 public:
346  MinHelper(const std::shared_ptr<double> &minVPtr, unsigned int nSlots);
347 
348  void Init(TTreeReader*, unsigned int) {}
349 
350  void Exec(unsigned int slot, double v);
351 
352  template <typename T, typename std::enable_if<TIsContainer<T>::fgValue, int>::type = 0>
353  void Exec(unsigned int slot, const T &vs)
354  {
355  for (auto &&v : vs) fMins[slot] = std::min((double)v, fMins[slot]);
356  }
357 
358  void Finalize();
359 };
360 
361 extern template void MinHelper::Exec(unsigned int, const std::vector<float> &);
362 extern template void MinHelper::Exec(unsigned int, const std::vector<double> &);
363 extern template void MinHelper::Exec(unsigned int, const std::vector<char> &);
364 extern template void MinHelper::Exec(unsigned int, const std::vector<int> &);
365 extern template void MinHelper::Exec(unsigned int, const std::vector<unsigned int> &);
366 
367 class MaxHelper {
368  std::shared_ptr<double> fResultMax;
369  std::vector<double> fMaxs;
370 
371 public:
372  MaxHelper(const std::shared_ptr<double> &maxVPtr, unsigned int nSlots);
373  void Init(TTreeReader*, unsigned int) {}
374  void Exec(unsigned int slot, double v);
375 
376  template <typename T, typename std::enable_if<TIsContainer<T>::fgValue, int>::type = 0>
377  void Exec(unsigned int slot, const T &vs)
378  {
379  for (auto &&v : vs) fMaxs[slot] = std::max((double)v, fMaxs[slot]);
380  }
381 
382  void Finalize();
383 };
384 
385 extern template void MaxHelper::Exec(unsigned int, const std::vector<float> &);
386 extern template void MaxHelper::Exec(unsigned int, const std::vector<double> &);
387 extern template void MaxHelper::Exec(unsigned int, const std::vector<char> &);
388 extern template void MaxHelper::Exec(unsigned int, const std::vector<int> &);
389 extern template void MaxHelper::Exec(unsigned int, const std::vector<unsigned int> &);
390 
391 class MeanHelper {
392  std::shared_ptr<double> fResultMean;
393  std::vector<Count_t> fCounts;
394  std::vector<double> fSums;
395 
396 public:
397  MeanHelper(const std::shared_ptr<double> &meanVPtr, unsigned int nSlots);
398  void Init(TTreeReader*, unsigned int) {}
399  void Exec(unsigned int slot, double v);
400 
401  template <typename T, typename std::enable_if<TIsContainer<T>::fgValue, int>::type = 0>
402  void Exec(unsigned int slot, const T &vs)
403  {
404  for (auto &&v : vs) {
405  fSums[slot] += v;
406  fCounts[slot]++;
407  }
408  }
409 
410  void Finalize();
411 };
412 
413 extern template void MeanHelper::Exec(unsigned int, const std::vector<float> &);
414 extern template void MeanHelper::Exec(unsigned int, const std::vector<double> &);
415 extern template void MeanHelper::Exec(unsigned int, const std::vector<char> &);
416 extern template void MeanHelper::Exec(unsigned int, const std::vector<int> &);
417 extern template void MeanHelper::Exec(unsigned int, const std::vector<unsigned int> &);
418 
419 template <typename F1, typename F2>
420 class SnapshotHelper {
421  F1 fInitFunc;
422  F2 fExecFunc;
423 
424 public:
425  using BranchTypes_t = typename TRemoveFirst<typename TFunctionTraits<F2>::Args_t>::Types_t;
426  SnapshotHelper(F1 &&f1, F2 &&f2) : fInitFunc(f1), fExecFunc(f2) {}
427 
428  void Init(TTreeReader *r, unsigned int slot) { fInitFunc(r, slot); }
429 
430  template <typename... Args>
431  void Exec(unsigned int slot, Args &&... args)
432  {
433  // check that the decayed types of Args are the same as the branch types
434  static_assert(std::is_same<TTypeList<typename std::decay<Args>::type...>, BranchTypes_t>::value, "");
435  fExecFunc(slot, std::forward<Args>(args)...);
436  }
437 
438  void Finalize() { /* noop */}
439 };
440 
441 } // end of NS TDF
442 } // end of NS Internal
443 } // end of NS ROOT
444 
445 /// \endcond
446 
447 #endif
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:42
double T(double x)
Definition: ChebyshevPol.h:34
THist< 1, float, THistStatContent, THistStatUncertainty > TH1F
Definition: THist.hxx:311
TH1 * h
Definition: legend2.C:5
static const double x2[5]
#define F1(x, y, z)
Definition: TMD5.cxx:267
#define F(x, y, z)
TRandom2 r(17)
SVector< double, 2 > v
Definition: Dict.h:5
#define F2(x, y, z)
Definition: TMD5.cxx:268
static const double x1[5]
double f(double x)
fNSlots(TDFInternal::GetNSlots())
Definition: TDFNodes.cxx:132
int type
Definition: TGX11.cxx:120
unsigned long long ULong64_t
Definition: RtypesCore.h:70
double f2(const double *x)
TF1 * f1
Definition: legend1.C:11
static const double x3[11]