Logo ROOT   6.10/09
Reference Guide
TDFUtils.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_TDFUTILS
12 #define ROOT_TDFUTILS
13 
14 #include "ROOT/RArrayView.hxx"
15 #include "TH1.h"
16 #include "TTreeReaderArray.h"
17 #include "TTreeReaderValue.h"
18 
19 #include <array>
20 #include <cstddef> // std::size_t
21 #include <functional>
22 #include <memory>
23 #include <string>
24 #include <type_traits> // std::decay
25 #include <vector>
26 class TTree;
27 class TTreeReader;
28 
29 /// \cond HIDDEN_SYMBOLS
30 
31 namespace ROOT {
32 
33 namespace Detail {
34 namespace TDF {
35 using ColumnNames_t = std::vector<std::string>;
36 class TCustomColumnBase; // fwd decl for ColumnName2ColumnTypeName
37 struct TInferType {
38 };
39 } // end ns Detail
40 } // end ns TDF
41 
42 namespace Internal {
43 namespace TDF {
44 using namespace ROOT::Detail::TDF;
45 
46 template <typename... Types>
47 struct TTypeList {
48  static constexpr std::size_t fgSize = sizeof...(Types);
49 };
50 
51 // extract parameter types from a callable object
52 template <typename T>
53 struct TFunctionTraits {
54  using Args_t = typename TFunctionTraits<decltype(&T::operator())>::Args_t;
55  using ArgsNoDecay_t = typename TFunctionTraits<decltype(&T::operator())>::ArgsNoDecay_t;
56  using Ret_t = typename TFunctionTraits<decltype(&T::operator())>::Ret_t;
57 };
58 
59 // lambdas and std::function
60 template <typename R, typename T, typename... Args>
61 struct TFunctionTraits<R (T::*)(Args...) const> {
63  using ArgsNoDecay_t = TTypeList<Args...>;
64  using Ret_t = R;
65 };
66 
67 // mutable lambdas and functor classes
68 template <typename R, typename T, typename... Args>
69 struct TFunctionTraits<R (T::*)(Args...)> {
71  using ArgsNoDecay_t = TTypeList<Args...>;
72  using Ret_t = R;
73 };
74 
75 // function pointers
76 template <typename R, typename... Args>
77 struct TFunctionTraits<R (*)(Args...)> {
79  using ArgsNoDecay_t = TTypeList<Args...>;
80  using Ret_t = R;
81 };
82 
83 // free functions
84 template <typename R, typename... Args>
85 struct TFunctionTraits<R(Args...)> {
87  using ArgsNoDecay_t = TTypeList<Args...>;
88  using Ret_t = R;
89 };
90 
91 // remove first type from TTypeList
92 template <typename>
93 struct TRemoveFirst {
94 };
95 
96 template <typename T, typename... Args>
97 struct TRemoveFirst<TTypeList<T, Args...>> {
98  using Types_t = TTypeList<Args...>;
99 };
100 
101 // return wrapper around f that prepends an `unsigned int slot` parameter
102 template <typename R, typename F, typename... Args>
103 std::function<R(unsigned int, Args...)> AddSlotParameter(F &f, TTypeList<Args...>)
104 {
105  return [f](unsigned int, Args... a) -> R { return f(a...); };
106 }
107 
108 // compile-time integer sequence generator
109 // e.g. calling TGenStaticSeq<3>::type() instantiates a TStaticSeq<0,1,2>
110 template <int...>
111 struct TStaticSeq {
112 };
113 
114 template <int N, int... S>
115 struct TGenStaticSeq : TGenStaticSeq<N - 1, N - 1, S...> {
116 };
117 
118 template <int... S>
119 struct TGenStaticSeq<0, S...> {
120  using Type_t = TStaticSeq<S...>;
121 };
122 
123 template <typename T>
124 struct TIsContainer {
125  using Test_t = typename std::decay<T>::type;
126 
127  template <typename A>
128  static constexpr bool Test(A *pt, A const *cpt = nullptr, decltype(pt->begin()) * = nullptr,
129  decltype(pt->end()) * = nullptr, decltype(cpt->begin()) * = nullptr,
130  decltype(cpt->end()) * = nullptr, typename A::iterator *pi = nullptr,
131  typename A::const_iterator *pci = nullptr)
132  {
133  using It_t = typename A::iterator;
134  using CIt_t = typename A::const_iterator;
135  using V_t = typename A::value_type;
136  return std::is_same<Test_t, std::vector<bool>>::value ||
137  (std::is_same<decltype(pt->begin()), It_t>::value && std::is_same<decltype(pt->end()), It_t>::value &&
138  std::is_same<decltype(cpt->begin()), CIt_t>::value && std::is_same<decltype(cpt->end()), CIt_t>::value &&
139  std::is_same<decltype(**pi), V_t &>::value && std::is_same<decltype(**pci), V_t const &>::value);
140  }
141 
142  template <typename A>
143  static constexpr bool Test(...)
144  {
145  return false;
146  }
147 
148  static const bool fgValue = Test<Test_t>(nullptr);
149 };
150 
151 // Extract first of possibly many template parameters. For non-template types, the result is the type itself
152 template <typename T>
153 struct TExtractType {
154  using type = T;
155 };
156 
157 template <typename T, template <typename...> class U, typename... Extras>
158 struct TExtractType<U<T, Extras...>> {
159  using type = T;
160 };
161 
162 template <typename T>
163 using ExtractType_t = typename TExtractType<T>::type;
164 
165 template <typename BranchType, typename... Rest>
166 struct TNeedJitting {
167  static constexpr bool value = TNeedJitting<Rest...>::value;
168 };
169 
170 template <typename... Rest>
171 struct TNeedJitting<TInferType, Rest...> {
172  static constexpr bool value = true;
173 };
174 
175 template <typename T>
176 struct TNeedJitting<T> {
177  static constexpr bool value = false;
178 };
179 
180 template <>
181 struct TNeedJitting<TInferType> {
182  static constexpr bool value = true;
183 };
184 
185 using TVBPtr_t = std::shared_ptr<TTreeReaderValueBase>;
186 using TVBVec_t = std::vector<TVBPtr_t>;
187 
188 std::string ColumnName2ColumnTypeName(const std::string &colName, TTree *, TCustomColumnBase *);
189 
190 const char *ToConstCharPtr(const char *s);
191 const char *ToConstCharPtr(const std::string s);
192 unsigned int GetNSlots();
193 
194 /// Choose between TTreeReader{Array,Value} depending on whether the branch type
195 /// T is a `std::array_view<T>` or any other type (respectively).
196 template <typename T>
197 struct TReaderValueOrArray {
198  using Proxy_t = TTreeReaderValue<T>;
199 };
200 
201 template <typename T>
202 struct TReaderValueOrArray<std::array_view<T>> {
203  using Proxy_t = TTreeReaderArray<T>;
204 };
205 
206 template <typename T>
207 using ReaderValueOrArray_t = typename TReaderValueOrArray<T>::Proxy_t;
208 
209 /// Initialize a tuple of TColumnValues.
210 /// For real TTree branches a TTreeReader{Array,Value} is built and passed to the
211 /// TColumnValue. For temporary columns a pointer to the corresponding variable
212 /// is passed instead.
213 template <typename TDFValueTuple, int... S>
214 void InitTDFValues(unsigned int slot, TDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn,
215  const ColumnNames_t &tmpbn,
216  const std::map<std::string, std::shared_ptr<TCustomColumnBase>> &tmpBranches, TStaticSeq<S...>)
217 {
218  // isTmpBranch has length bn.size(). Elements are true if the corresponding
219  // branch is a temporary branch created with Define, false if they are
220  // actual branches present in the TTree.
221  std::array<bool, sizeof...(S)> isTmpColumn;
222  for (auto i = 0u; i < isTmpColumn.size(); ++i)
223  isTmpColumn[i] = std::find(tmpbn.begin(), tmpbn.end(), bn.at(i)) != tmpbn.end();
224 
225  // hack to expand a parameter pack without c++17 fold expressions.
226  // The statement defines a variable with type std::initializer_list<int>, containing all zeroes, and SetTmpColumn or
227  // SetProxy are conditionally executed as the braced init list is expanded. The final ... expands S.
228  std::initializer_list<int> expander{(isTmpColumn[S]
229  ? std::get<S>(valueTuple).SetTmpColumn(slot, tmpBranches.at(bn.at(S)).get())
230  : std::get<S>(valueTuple).MakeProxy(r, bn.at(S)),
231  0)...};
232  (void)expander; // avoid "unused variable" warnings for expander on gcc4.9
233  (void)slot; // avoid _bogus_ "unused variable" warnings for slot on gcc 4.9
234  (void)r; // avoid "unused variable" warnings for r on gcc5.2
235 }
236 
237 template <typename Filter>
238 void CheckFilter(Filter &)
239 {
240  using FilterRet_t = typename TDF::TFunctionTraits<Filter>::Ret_t;
241  static_assert(std::is_same<FilterRet_t, bool>::value, "filter functions must return a bool");
242 }
243 
244 void CheckTmpBranch(std::string_view branchName, TTree *treePtr);
245 
246 ///////////////////////////////////////////////////////////////////////////////
247 /// Check that the callable passed to TInterface::Reduce:
248 /// - takes exactly two arguments of the same type
249 /// - has a return value of the same type as the arguments
250 template <typename F, typename T>
251 void CheckReduce(F &, TTypeList<T, T>)
252 {
253  using Ret_t = typename TFunctionTraits<F>::Ret_t;
254  static_assert(std::is_same<Ret_t, T>::value, "reduce function must have return type equal to argument type");
255  return;
256 }
257 
258 ///////////////////////////////////////////////////////////////////////////////
259 /// This overload of CheckReduce is called if T is not a TTypeList<T,T>
260 template <typename F, typename T>
261 void CheckReduce(F &, T)
262 {
263  static_assert(sizeof(F) == 0, "reduce function must take exactly two arguments of the same type");
264 }
265 
266 /// Returns local BranchNames or default BranchNames according to which one should be used
267 const ColumnNames_t &PickBranchNames(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl);
268 
269 namespace ActionTypes {
270 struct Histo1D {
271 };
272 struct Histo2D {
273 };
274 struct Histo3D {
275 };
276 struct Profile1D {
277 };
278 struct Profile2D {
279 };
280 struct Min {
281 };
282 struct Max {
283 };
284 struct Mean {
285 };
286 struct Fill {
287 };
288 }
289 
290 template <typename T, bool ISV7HISTO = !std::is_base_of<TH1, T>::value>
291 struct TIsV7Histo {
292  const static bool fgValue = ISV7HISTO;
293 };
294 
295 template <typename T, bool ISV7HISTO = TIsV7Histo<T>::fgValue>
296 struct HistoUtils {
297  static void SetCanExtendAllAxes(T &h) { h.SetCanExtend(::TH1::kAllAxes); }
298  static bool HasAxisLimits(T &h)
299  {
300  auto xaxis = h.GetXaxis();
301  return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
302  }
303 };
304 
305 template <typename T>
306 struct HistoUtils<T, true> {
307  static void SetCanExtendAllAxes(T &) {}
308  static bool HasAxisLimits(T &) { return true; }
309 };
310 
311 } // end NS TDF
312 } // end NS Internal
313 } // end NS ROOT
314 
315 /// \endcond
316 
317 #endif // TDFUTILS
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:43
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
const double pi
double T(double x)
Definition: ChebyshevPol.h:34
TH1 * h
Definition: legend2.C:5
#define N
const ColumnNames_t & PickBranchNames(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl)
Returns local BranchNames or default BranchNames according to which one should be used...
Definition: TDFUtils.cxx:147
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
TArc * a
Definition: textangle.C:12
STL namespace.
static double A[]
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
Definition: RExports.h:146
Extracts data from a TTree.
RooArgSet S(const RooAbsArg &v1)
#define F(x, y, z)
TPaveText * pt
TRandom2 r(17)
Double_t Mean(Long64_t n, const T *a, const Double_t *w=0)
Definition: TMath.h:973
const char * ToConstCharPtr(const char *s)
Definition: TDFUtils.cxx:115
std::string ColumnName2ColumnTypeName(const std::string &colName, TTree *tree, TCustomColumnBase *tmpBranch)
Return a string containing the type of the given branch.
Definition: TDFUtils.cxx:30
Extracts array data from a TTree.
double f(double x)
int type
Definition: TGX11.cxx:120
typedef void((*Func_t)())
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
unsigned int GetNSlots()
Definition: TDFUtils.cxx:125
void CheckTmpBranch(std::string_view branchName, TTree *treePtr)
Definition: TDFUtils.cxx:134
A TTree object has a header with a name and a title.
Definition: TTree.h:78
static void Fill(TTree *tree, int init, int count)
TRandom3 R
a TMatrixD.
Definition: testIO.cxx:28