Logo ROOT   6.12/07
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/TDataSource.hxx" // ColumnName2ColumnTypeName
15 #include "ROOT/TypeTraits.hxx"
16 #include "ROOT/TArrayBranch.hxx"
17 #include "Compression.h"
18 #include "TH1.h"
19 #include "TTreeReaderArray.h"
20 #include "TTreeReaderValue.h"
21 
22 #include <array>
23 #include <cstddef> // std::size_t
24 #include <deque>
25 #include <functional>
26 #include <memory>
27 #include <string>
28 #include <type_traits> // std::decay
29 #include <vector>
30 
31 class TTree;
32 class TTreeReader;
33 
34 namespace ROOT {
35 namespace Experimental {
36 namespace TDF {
37 /// A collection of options to steer the creation of the dataset on file
40  TSnapshotOptions() = default;
41  TSnapshotOptions(const TSnapshotOptions &) = default;
42  TSnapshotOptions(TSnapshotOptions &&) = default;
43  TSnapshotOptions(std::string_view mode, ECAlgo comprAlgo, int comprLevel, int autoFlush, int splitLevel)
44  : fMode(mode), fCompressionAlgorithm(comprAlgo), fCompressionLevel{comprLevel}, fAutoFlush(autoFlush),
45  fSplitLevel(splitLevel)
46  {
47  }
48  std::string fMode = "RECREATE"; //< Mode of creation of output file
49  ECAlgo fCompressionAlgorithm = ROOT::kZLIB; //< Compression algorithm of output file
50  int fCompressionLevel = 1; //< Compression level of output file
51  int fAutoFlush = 0; //< AutoFlush value for output tree
52  int fSplitLevel = 99; //< Split level of output tree
53 };
54 }
55 }
56 }
57 
58 /// \cond HIDDEN_SYMBOLS
59 
60 namespace ROOT {
61 
62 // fwd declaration for IsV7Hist
63 namespace Experimental {
64 template <int D, typename P, template <int, typename, template <typename> class> class... S>
65 class THist;
66 
67 } // ns Experimental
68 
69 namespace Detail {
70 namespace TDF {
71 using ColumnNames_t = std::vector<std::string>;
72 
73 // fwd decl for ColumnName2ColumnTypeName
74 class TCustomColumnBase;
75 // fwd decl for FindUnknownColumns
76 class TLoopManager;
77 
78 // type used for tag dispatching
79 struct TInferType {
80 };
81 
82 } // end ns Detail
83 } // end ns TDF
84 
85 namespace Internal {
86 namespace TDF {
87 using namespace ROOT::TypeTraits;
88 using namespace ROOT::Detail::TDF;
89 using namespace ROOT::Experimental::TDF;
90 
91 class TIgnoreErrorLevelRAII {
92 private:
93  int fCurIgnoreErrorLevel = gErrorIgnoreLevel;
94 
95 public:
96  TIgnoreErrorLevelRAII(int errorIgnoreLevel);
97  ~TIgnoreErrorLevelRAII();
98 };
99 
100 /// Compile-time integer sequence generator
101 /// e.g. calling GenStaticSeq<3>::type() instantiates a StaticSeq<0,1,2>
102 template <int...>
103 struct StaticSeq {
104 };
105 
106 template <int N, int... S>
107 struct GenStaticSeq : GenStaticSeq<N - 1, N - 1, S...> {
108 };
109 
110 template <int... S>
111 struct GenStaticSeq<0, S...> {
112  using type = StaticSeq<S...>;
113 };
114 
115 template <int... S>
116 using GenStaticSeq_t = typename GenStaticSeq<S...>::type;
117 
118 // return wrapper around f that prepends an `unsigned int slot` parameter
119 template <typename R, typename F, typename... Args>
120 std::function<R(unsigned int, Args...)> AddSlotParameter(F &f, TypeList<Args...>)
121 {
122  return [f](unsigned int, Args... a) -> R { return f(a...); };
123 }
124 
125 template <typename BranchType, typename... Rest>
126 struct TNeedJitting {
127  static constexpr bool value = TNeedJitting<Rest...>::value;
128 };
129 
130 template <typename... Rest>
131 struct TNeedJitting<TInferType, Rest...> {
132  static constexpr bool value = true;
133 };
134 
135 template <typename T>
136 struct TNeedJitting<T> {
137  static constexpr bool value = false;
138 };
139 
140 template <>
141 struct TNeedJitting<TInferType> {
142  static constexpr bool value = true;
143 };
144 
145 using TVBPtr_t = std::shared_ptr<TTreeReaderValueBase>;
146 using TVBVec_t = std::vector<TVBPtr_t>;
147 
148 const std::type_info &TypeName2TypeID(const std::string &name);
149 
150 std::string TypeID2TypeName(const std::type_info &id);
151 
152 std::string
153 ColumnName2ColumnTypeName(const std::string &colName, TTree *, TCustomColumnBase *, TDataSource * = nullptr);
154 
155 char TypeName2ROOTTypeName(const std::string &b);
156 
157 const char *ToConstCharPtr(const char *s);
158 const char *ToConstCharPtr(const std::string &s);
159 unsigned int GetNSlots();
160 
161 /// Choose between TTreeReader{Array,Value} depending on whether the branch type
162 /// T is a `TArrayBranch<T>` or any other type (respectively).
163 template <typename T>
164 struct TReaderValueOrArray {
165  using Proxy_t = TTreeReaderValue<T>;
166 };
167 
168 template <typename T>
169 struct TReaderValueOrArray<TArrayBranch<T>> {
170  using Proxy_t = TTreeReaderArray<T>;
171 };
172 
173 template <typename T>
174 using ReaderValueOrArray_t = typename TReaderValueOrArray<T>::Proxy_t;
175 
176 /// Initialize a tuple of TColumnValues.
177 /// For real TTree branches a TTreeReader{Array,Value} is built and passed to the
178 /// TColumnValue. For temporary columns a pointer to the corresponding variable
179 /// is passed instead.
180 template <typename TDFValueTuple, int... S>
181 void InitTDFValues(unsigned int slot, TDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn,
182  const ColumnNames_t &tmpbn,
183  const std::map<std::string, std::shared_ptr<TCustomColumnBase>> &customCols, StaticSeq<S...>)
184 {
185  // isTmpBranch has length bn.size(). Elements are true if the corresponding
186  // branch is a temporary branch created with Define, false if they are
187  // actual branches present in the TTree.
188  std::array<bool, sizeof...(S)> isTmpColumn;
189  for (auto i = 0u; i < isTmpColumn.size(); ++i)
190  isTmpColumn[i] = std::find(tmpbn.begin(), tmpbn.end(), bn.at(i)) != tmpbn.end();
191 
192  // hack to expand a parameter pack without c++17 fold expressions.
193  // The statement defines a variable with type std::initializer_list<int>, containing all zeroes, and SetTmpColumn or
194  // SetProxy are conditionally executed as the braced init list is expanded. The final ... expands S.
195  std::initializer_list<int> expander{(isTmpColumn[S]
196  ? std::get<S>(valueTuple).SetTmpColumn(slot, customCols.at(bn.at(S)).get())
197  : std::get<S>(valueTuple).MakeProxy(r, bn.at(S)),
198  0)...};
199  (void)expander; // avoid "unused variable" warnings for expander on gcc4.9
200  (void)slot; // avoid _bogus_ "unused variable" warnings for slot on gcc 4.9
201  (void)r; // avoid "unused variable" warnings for r on gcc5.2
202 }
203 
204 template <typename Filter>
205 void CheckFilter(Filter &)
206 {
207  using FilterRet_t = typename TDF::CallableTraits<Filter>::ret_type;
208  static_assert(std::is_same<FilterRet_t, bool>::value, "filter functions must return a bool");
209 }
210 
211 ColumnNames_t GetBranchNames(TTree &t);
212 
213 void CheckCustomColumn(std::string_view definedCol, TTree *treePtr, const ColumnNames_t &customCols,
214  const ColumnNames_t &dataSourceColumns);
215 
216 ///////////////////////////////////////////////////////////////////////////////
217 /// Check that the callable passed to TInterface::Reduce:
218 /// - takes exactly two arguments of the same type
219 /// - has a return value of the same type as the arguments
220 template <typename F, typename T>
221 void CheckReduce(F &, TypeList<T, T>)
222 {
223  using ret_type = typename CallableTraits<F>::ret_type;
224  static_assert(std::is_same<ret_type, T>::value, "reduce function must have return type equal to argument type");
225  return;
226 }
227 
228 ///////////////////////////////////////////////////////////////////////////////
229 /// This overload of CheckReduce is called if T is not a TypeList<T,T>
230 template <typename F, typename T>
231 void CheckReduce(F &, T)
232 {
233  static_assert(sizeof(F) == 0, "reduce function must take exactly two arguments of the same type");
234 }
235 
236 ///////////////////////////////////////////////////////////////////////////////
237 /// Check as many template parameters were passed as the number of column names, throw if this is not the case.
238 void CheckSnapshot(unsigned int nTemplateParams, unsigned int nColumnNames);
239 
240 /// Return local BranchNames or default BranchNames according to which one should be used
241 const ColumnNames_t SelectColumns(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl);
242 
243 /// Check whether column names refer to a valid branch of a TTree or have been `Define`d. Return invalid column names.
244 ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, TTree *tree, const ColumnNames_t &definedCols,
245  const ColumnNames_t &dataSourceColumns);
246 
247 // clang-format off
248 namespace ActionTypes {
249 struct Histo1D {};
250 struct Histo2D {};
251 struct Histo3D {};
252 struct Profile1D {};
253 struct Profile2D {};
254 struct Min {};
255 struct Max {};
256 struct Sum {};
257 struct Mean {};
258 struct Fill {};
259 }
260 // clang-format on
261 
262 /// Check whether a histogram type is a classic or v7 histogram.
263 template <typename T>
264 struct IsV7Hist : public std::false_type {
265  static_assert(std::is_base_of<TH1, T>::value, "not implemented for this type");
266 };
267 
268 template <int D, typename P, template <int, typename, template <typename> class> class... S>
269 struct IsV7Hist<ROOT::Experimental::THist<D, P, S...>> : public std::true_type {
270 };
271 
272 template <typename T, bool ISV7HISTO = IsV7Hist<T>::value>
273 struct HistoUtils {
274  static void SetCanExtendAllAxes(T &h) { h.SetCanExtend(::TH1::kAllAxes); }
275  static bool HasAxisLimits(T &h)
276  {
277  auto xaxis = h.GetXaxis();
278  return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
279  }
280 };
281 
282 template <typename T>
283 struct HistoUtils<T, true> {
284  static void SetCanExtendAllAxes(T &) {}
285  static bool HasAxisLimits(T &) { return true; }
286 };
287 
288 /// `type` is TypeList if MustRemove is false, otherwise it is a TypeList with the first type removed
289 template <bool MustRemove, typename TypeList>
290 struct RemoveFirstParameterIf {
291  using type = TypeList;
292 };
293 
294 template <typename TypeList>
295 struct RemoveFirstParameterIf<true, TypeList> {
296  using type = RemoveFirstParameter_t<TypeList>;
297 };
298 
299 template <bool MustRemove, typename TypeList>
300 struct RemoveFirstTwoParametersIf {
301  using type = TypeList;
302 };
303 
304 template <typename TypeList>
305 struct RemoveFirstTwoParametersIf<true, TypeList> {
306  using typeTmp = typename RemoveFirstParameterIf<true, TypeList>::type;
308 };
309 
310 bool IsInternalColumn(std::string_view colName);
311 
312 // Check if a condition is true for all types
313 template <bool...>
314 struct TBoolPack;
315 template <bool... bs>
316 using IsTrueForAllImpl_t = typename std::is_same<TBoolPack<bs..., true>, TBoolPack<true, bs...>>;
317 
318 template <bool... Conditions>
319 struct TEvalAnd {
320  static constexpr bool value = IsTrueForAllImpl_t<Conditions...>::value;
321 };
322 
323 // Check if a class is a specialisation of stl containers templates
324 
325 template <typename>
326 struct IsVector_t : std::false_type {
327 };
328 
329 template <typename T>
330 struct IsVector_t<std::vector<T>> : std::true_type {
331 };
332 
333 template <typename>
334 struct IsList_t : std::false_type {
335 };
336 
337 template <typename T>
338 struct IsList_t<std::list<T>> : std::true_type {
339 };
340 
341 template <typename>
342 struct IsDeque_t : std::false_type {
343 };
344 
345 template <typename T>
346 struct IsDeque_t<std::deque<T>> : std::true_type {
347 };
348 
349 template <typename>
350 struct IsTArrayBranch_t : std::false_type {
351 };
352 
353 template <typename T>
354 struct IsTArrayBranch_t<ROOT::Experimental::TDF::TArrayBranch<T>> : std::true_type {
355 };
356 
357 // Check the value_type type of a type with a SFINAE to allow compilation in presence
358 // fundamental types
360 struct ValueType {
361  using value_type = typename T::value_type;
362 };
363 
364 template <typename T>
365 struct ValueType<T, false> {
366  using value_type = T;
367 };
368 
369 template <typename T>
370 struct ValueType<ROOT::Experimental::TDF::TArrayBranch<T>, false> {
371  using value_type = T;
372 };
373 
374 } // end NS TDF
375 } // end NS Internal
376 } // end NS ROOT
377 
378 /// \endcond
379 
380 #endif // TDFUTILS
std::string TypeID2TypeName(const std::type_info &id)
Returns the name of a type starting from its type_info An empty string is returned in case of failure...
Definition: TDFUtils.cxx:85
A collection of options to steer the creation of the dataset on file.
Definition: TDFUtils.hxx:38
const std::type_info & TypeName2TypeID(const std::string &name)
Return the type_info associated to a name.
Definition: TDFUtils.cxx:43
char TypeName2ROOTTypeName(const std::string &b)
Convert type name (e.g.
Definition: TDFUtils.cxx:185
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:105
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:43
basic_string_view< char > string_view
Definition: RStringView.h:35
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, TTree *tree, const ColumnNames_t &definedCols, const ColumnNames_t &dataSourceColumns)
Definition: TDFUtils.cxx:339
double T(double x)
Definition: ChebyshevPol.h:34
TH1 * h
Definition: legend2.C:5
void CheckCustomColumn(std::string_view definedCol, TTree *treePtr, const ColumnNames_t &customCols, const ColumnNames_t &dataSourceColumns)
Definition: TDFUtils.cxx:274
#define N
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
Definition: RExports.h:146
bool IsInternalColumn(std::string_view colName)
Definition: TDFUtils.cxx:359
Extracts data from a TTree.
ECompressionAlgorithm
The global settings depend on a global variable named R__ZipMode which can be modified by a global fu...
Definition: Compression.h:34
When using TDataFrame to read data from a ROOT file, users can specify that the type of a branch is T...
const ColumnNames_t SelectColumns(unsigned int nRequiredNames, const ColumnNames_t &names, const ColumnNames_t &defaultNames)
Choose between local column names or default column names, throw in case of errors.
Definition: TDFUtils.cxx:314
RooArgSet S(const RooAbsArg &v1)
#define F(x, y, z)
::ROOT::ECompressionAlgorithm ECAlgo
Definition: TDFUtils.hxx:39
ROOT::R::TRInterface & r
Definition: Object.C:4
TDataSource defines an API that TDataFrame can use to read arbitrary data formats.
Definition: TDataSource.hxx:51
Use ZLIB compression.
Definition: Compression.h:38
auto * a
Definition: textangle.C:12
Double_t Mean(Long64_t n, const T *a, const Double_t *w=0)
Definition: TMath.h:972
const char * ToConstCharPtr(const char *s)
Definition: TDFUtils.cxx:212
Histogram class for histograms with DIMENSIONS dimensions, where each bin count is stored by a value ...
Definition: THist.hxx:33
Lightweight storage for a collection of types.
Definition: TypeTraits.hxx:27
Extracts array data from a TTree.
int type
Definition: TGX11.cxx:120
ROOT type_traits extensions.
Definition: TypeTraits.hxx:23
static constexpr double s
typedef void((*Func_t)())
void CheckSnapshot(unsigned int nTemplateParams, unsigned int nColumnNames)
Definition: TDFUtils.cxx:300
std::string ColumnName2ColumnTypeName(const std::string &colName, TTree *tree, TCustomColumnBase *tmpBranch, TDataSource *ds)
Return a string containing the type of the given branch.
Definition: TDFUtils.cxx:123
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
unsigned int GetNSlots()
Definition: TDFUtils.cxx:222
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Definition: tree.py:1
A TTree object has a header with a name and a title.
Definition: TTree.h:70
constexpr Double_t R()
Definition: TMath.h:213
ColumnNames_t GetBranchNames(TTree &t)
Get all the branches names, including the ones of the friend trees.
Definition: TDFUtils.cxx:265
char name[80]
Definition: TGX11.cxx:109
TSnapshotOptions(std::string_view mode, ECAlgo comprAlgo, int comprLevel, int autoFlush, int splitLevel)
Definition: TDFUtils.hxx:43