Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RVariation.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, CERN 10/2021
2
3/*************************************************************************
4 * Copyright (C) 1995-2021, 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_RDF_RVARIATION
12#define ROOT_RDF_RVARIATION
13
14#include "ColumnReaderUtils.hxx"
15#include "RColumnReaderBase.hxx"
16#include "RLoopManager.hxx"
17#include "RVariationBase.hxx"
18
19#include <string_view>
20#include <ROOT/TypeTraits.hxx>
21#include <Rtypes.h> // R__CLING_PTRCHECK, Long64_t
22
23#include <array>
24#include <deque>
25#include <map>
26#include <string>
27#include <type_traits> // std::is_same, std::conditional_t
28#include <utility> // std::index_sequence
29#include <vector>
30
31class TTreeReader;
32
33namespace ROOT {
34
35namespace RDF {
36class RDataSource;
37}
38
39namespace Internal {
40namespace RDF {
41
42using namespace ROOT::TypeTraits;
43
44/// @name Helper functions for the case of a single column being varied.
45///@{
46template <typename T>
47bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t nColumns, std::true_type /*isSingleColumn*/)
48{
49 assert(nColumns == 1);
50 (void)nColumns;
51
52 return results.size() == expected;
53}
54
55template <typename T>
56std::size_t GetNVariations(const RVec<T> &results)
57{
58 return results.size();
59}
60
61template <typename T>
62void ResizeResults(ROOT::RVec<T> &results, std::size_t /*nCols*/, std::size_t nVariations)
63{
64 results.resize(nVariations);
65}
66
67/// Assign into fLastResults[slot] without changing the addresses of its elements (we gave those addresses away in
68/// GetValuePtr)
69/// The callee is responsible of making sure that `resStorage` has the correct size.
70template <typename T>
71void AssignResults(ROOT::RVec<T> &resStorage, ROOT::RVec<T> &&tmpResults)
72{
73 const auto nVariations = resStorage.size(); // we have already checked that tmpResults has the same size
74
75 for (auto i = 0u; i < nVariations; ++i)
76 resStorage[i] = std::move(tmpResults[i]);
77}
78
79template <typename T>
80void *GetValuePtrHelper(ROOT::RVec<T> &v, std::size_t /*colIdx*/, std::size_t varIdx)
81{
82 return static_cast<void *>(&v[varIdx]);
83}
84///@}
85
86/// @name Helper functions for the case of multiple columns being varied simultaneously.
87///@{
88template <typename T>
89bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t /*nColumns*/, std::false_type /*isSingleColumn*/)
90{
91 return std::all_of(results.begin(), results.end(),
92 [expected](const auto &inner) { return inner.size() == expected; });
93}
94
95template <typename T>
96std::size_t GetNVariations(const std::vector<RVec<T>> &results)
97{
98 assert(!results.empty());
99 return results[0].size();
100}
101
102template <typename T>
103void ResizeResults(std::vector<ROOT::RVec<T>> &results, std::size_t nCols, std::size_t nVariations)
104{
105 results.resize(nCols);
106 for (auto &rvecOverVariations : results)
107 rvecOverVariations.resize(nVariations);
108}
109
110// The callee is responsible of making sure that `resStorage` has the correct outer and inner sizes.
111template <typename T>
112void AssignResults(std::vector<ROOT::RVec<T>> &resStorage, ROOT::RVec<ROOT::RVec<T>> &&tmpResults)
113{
114 const auto nCols = resStorage.size();
115 const auto nVariations = resStorage[0].size();
116 for (auto colIdx = 0u; colIdx < nCols; ++colIdx)
117 for (auto varIdx = 0u; varIdx < nVariations; ++varIdx)
118 resStorage[colIdx][varIdx] = std::move(tmpResults[colIdx][varIdx]);
119}
120
121template <typename T>
122void *GetValuePtrHelper(std::vector<ROOT::RVec<T>> &v, std::size_t colIdx, std::size_t varIdx)
123{
124 return static_cast<void *>(&v[colIdx][varIdx]);
125}
126///@}
127
128template <typename VaryExpressionRet_t, bool IsSingleColumn>
130};
131
132template <typename T>
133struct ColumnType<ROOT::RVec<T>, true> {
134 using type = T;
135};
136
137template <typename T>
138struct ColumnType<ROOT::RVec<ROOT::RVec<T>>, false> {
139 using type = T;
140};
141
142/// When varying a single column, Ret_t is RVec<T> and ColumnType_t is T.
143/// When varying multiple columns, Ret_t is RVec<RVec<T>> and ColumnType_t is T.
144template <bool IsSingleColumn, typename Ret_t>
146
147template <typename F, bool IsSingleColumn>
148class R__CLING_PTRCHECK(off) RVariation final : public RVariationBase {
150 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
153 using Result_t = std::conditional_t<IsSingleColumn, ROOT::RVec<VariedCol_t>, std::vector<ROOT::RVec<VariedCol_t>>>;
154
156 /// Per-slot storage for varied column values (for one or multiple columns depending on IsSingleColumn).
157 std::vector<Result_t> fLastResults;
158
159 /// Column readers per slot and per input column
160 std::vector<std::array<RColumnReaderBase *, ColumnTypes_t::list_size>> fValues;
161
162 template <typename ColType>
163 auto GetValueChecked(unsigned int slot, std::size_t readerIdx, Long64_t entry) -> ColType &
164 {
165 if (auto *val = fValues[slot][readerIdx]->template TryGet<ColType>(entry))
166 return *val;
167
168 throw std::out_of_range{"RDataFrame: Could not retrieve value for variation '" + fColNames[readerIdx] +
169 "' for entry " + std::to_string(entry) +
170 ". You can use the DefaultValueFor operation to provide a default value, or "
171 "FilterAvailable/FilterMissing to discard/keep entries with missing values instead."};
172 }
173
174 template <typename... ColTypes, std::size_t... S>
175 void UpdateHelper(unsigned int slot, Long64_t entry, TypeList<ColTypes...>, std::index_sequence<S...>)
176 {
177 // fExpression must return an RVec<T>
178 auto &&results = fExpression(GetValueChecked<ColTypes>(slot, S, entry)...);
179 (void)entry; // avoid unused parameter warnings (gcc 12.1)
180
181 if (!ResultsSizeEq(results, fVariationNames.size(), fColNames.size(),
182 std::integral_constant<bool, IsSingleColumn>{})) {
183 std::string variationName = fVariationNames[0].substr(0, fVariationNames[0].find_first_of(':'));
184 throw std::runtime_error("The evaluation of the expression for variation \"" + variationName +
185 "\" resulted in " + std::to_string(GetNVariations(results)) + " values, but " +
186 std::to_string(fVariationNames.size()) + " were expected.");
187 }
188
189 AssignResults(fLastResults[slot * CacheLineStep<Result_t>()], std::move(results));
190 }
191
192public:
193 RVariation(const std::vector<std::string> &colNames, std::string_view variationName, F expression,
194 const std::vector<std::string> &variationTags, std::string_view type, const RColumnRegister &defines,
195 RLoopManager &lm, const ColumnNames_t &inputColNames)
196 : RVariationBase(colNames, variationName, variationTags, type, defines, lm, inputColNames),
197 fExpression(std::move(expression)),
198 fLastResults(lm.GetNSlots() * CacheLineStep<Result_t>()),
199 fValues(lm.GetNSlots())
200 {
201 fLoopManager->Register(this);
202
203 for (auto i = 0u; i < lm.GetNSlots(); ++i)
204 ResizeResults(fLastResults[i * CacheLineStep<Result_t>()], colNames.size(), variationTags.size());
205 }
206
207 RVariation(const RVariation &) = delete;
208 RVariation &operator=(const RVariation &) = delete;
209 ~RVariation() { fLoopManager->Deregister(this); }
210
211 void InitSlot(TTreeReader *r, unsigned int slot) final
212 {
213 RColumnReadersInfo info{fInputColumns, fColumnRegister, fIsDefine.data(), *fLoopManager};
214 fValues[slot] = GetColumnReaders(slot, r, ColumnTypes_t{}, info);
215 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = -1;
216 }
217
218 /// Return the (type-erased) address of the value for the given processing slot.
219 void *GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
220 {
221 const auto colIt = std::find(fColNames.begin(), fColNames.end(), column);
222 assert(colIt != fColNames.end());
223 const auto colIdx = std::distance(fColNames.begin(), colIt);
224
225 const auto varIt = std::find(fVariationNames.begin(), fVariationNames.end(), variation);
226 assert(varIt != fVariationNames.end());
227 const auto varIdx = std::distance(fVariationNames.begin(), varIt);
228
229 return GetValuePtrHelper(fLastResults[slot * CacheLineStep<Result_t>()], colIdx, varIdx);
230 }
231
232 /// Update the value at the address returned by GetValuePtr with the content corresponding to the given entry
233 void Update(unsigned int slot, Long64_t entry) final
234 {
235 if (entry != fLastCheckedEntry[slot * CacheLineStep<Long64_t>()]) {
236 // evaluate this filter, cache the result
237 UpdateHelper(slot, entry, ColumnTypes_t{}, TypeInd_t{});
238 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = entry;
239 }
240 }
241
242 const std::type_info &GetTypeId() const final { return typeid(VariedCol_t); }
243
244 /// Clean-up operations to be performed at the end of a task.
245 void FinalizeSlot(unsigned int slot) final { fValues[slot].fill(nullptr); }
246};
247
248} // namespace RDF
249} // namespace Internal
250} // namespace ROOT
251
252#endif // ROOT_RDF_RVARIATION
long long Long64_t
Definition RtypesCore.h:69
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
The head node of a RDF computation graph.
void resize(size_type N)
Definition RVec.hxx:596
A binder for user-defined columns, variations and aliases.
This type includes all parts of RVariation that do not depend on the callable signature.
void Update(unsigned int slot, Long64_t entry) final
Update the value at the address returned by GetValuePtr with the content corresponding to the given e...
std::conditional_t< IsSingleColumn, ROOT::RVec< VariedCol_t >, std::vector< ROOT::RVec< VariedCol_t > > > Result_t
const std::type_info & GetTypeId() const final
void FinalizeSlot(unsigned int slot) final
Clean-up operations to be performed at the end of a task.
void * GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
Return the (type-erased) address of the value for the given processing slot.
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
auto GetValueChecked(unsigned int slot, std::size_t readerIdx, Long64_t entry) -> ColType &
ColumnType_t< IsSingleColumn, Ret_t > VariedCol_t
RVariation(const std::vector< std::string > &colNames, std::string_view variationName, F expression, const std::vector< std::string > &variationTags, std::string_view type, const RColumnRegister &defines, RLoopManager &lm, const ColumnNames_t &inputColNames)
void InitSlot(TTreeReader *r, unsigned int slot) final
RVariation & operator=(const RVariation &)=delete
typename CallableTraits< F >::ret_type Ret_t
std::vector< std::array< RColumnReaderBase *, ColumnTypes_t::list_size > > fValues
Column readers per slot and per input column.
void UpdateHelper(unsigned int slot, Long64_t entry, TypeList< ColTypes... >, std::index_sequence< S... >)
typename CallableTraits< F >::arg_types ColumnTypes_t
std::vector< Result_t > fLastResults
Per-slot storage for varied column values (for one or multiple columns depending on IsSingleColumn).
RVariation(const RVariation &)=delete
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1529
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
#define F(x, y, z)
typename ColumnType< Ret_t, IsSingleColumn >::type ColumnType_t
When varying a single column, Ret_t is RVec<T> and ColumnType_t is T.
std::size_t GetNVariations(const RVec< T > &results)
unsigned int GetNSlots()
Definition RDFUtils.cxx:301
void ResizeResults(ROOT::RVec< T > &results, std::size_t, std::size_t nVariations)
void * GetValuePtrHelper(ROOT::RVec< T > &v, std::size_t, std::size_t varIdx)
constexpr std::size_t CacheLineStep()
Stepping through CacheLineStep<T> values in a vector<T> brings you to a new cache line.
Definition Utils.hxx:222
void AssignResults(ROOT::RVec< T > &resStorage, ROOT::RVec< T > &&tmpResults)
Assign into fLastResults[slot] without changing the addresses of its elements (we gave those addresse...
std::array< RDFDetail::RColumnReaderBase *, sizeof...(ColTypes)> GetColumnReaders(unsigned int slot, TTreeReader *r, TypeList< ColTypes... >, const RColumnReadersInfo &colInfo, const std::string &variationName="nominal")
Create a group of column readers, one per type in the parameter pack.
bool ResultsSizeEq(const T &results, std::size_t expected, std::size_t nColumns, std::true_type)
std::vector< std::string > ColumnNames_t
ROOT type_traits extensions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Extract types from the signature of a callable object. See CallableTraits.
This type aggregates some of the arguments passed to GetColumnReaders.
Lightweight storage for a collection of types.