Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RFilter.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, Danilo Piparo CERN 09/2018
2
3/*************************************************************************
4 * Copyright (C) 1995-2018, 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_RFILTER
12#define ROOT_RFILTER
13
17#include "ROOT/RDF/Utils.hxx"
20#include "ROOT/TypeTraits.hxx"
21#include "RtypesCore.h"
22
23#include <algorithm>
24#include <cassert>
25#include <memory>
26#include <string>
27#include <unordered_map>
28#include <utility> // std::index_sequence
29#include <vector>
30
31namespace ROOT {
32
33namespace Internal {
34namespace RDF {
35using namespace ROOT::Detail::RDF;
36
37// fwd decl for RFilter
38namespace GraphDrawing {
39std::shared_ptr<GraphNode>
40CreateFilterNode(const RFilterBase *filterPtr, std::unordered_map<void *, std::shared_ptr<GraphNode>> &visitedMap);
41
42std::shared_ptr<GraphNode> AddDefinesToGraph(std::shared_ptr<GraphNode> node, const RColumnRegister &colRegister,
43 const std::vector<std::string> &prevNodeDefines,
44 std::unordered_map<void *, std::shared_ptr<GraphNode>> &visitedMap);
45} // ns GraphDrawing
46
47} // ns RDF
48} // ns Internal
49
50namespace Detail {
51namespace RDF {
52using namespace ROOT::TypeTraits;
54class RJittedFilter;
55
56template <typename FilterF, typename PrevNodeRaw>
59 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
60 // If the PrevNode is a RJittedFilter, treat it as a more generic RFilterBase: when dealing with systematic
61 // variations we'll have a RJittedFilter node for the nominal case but other "universes" will use concrete filters,
62 // so we normalize the "previous node type" to the base type RFilterBase.
63 using PrevNode_t = std::conditional_t<std::is_same<PrevNodeRaw, RJittedFilter>::value, RFilterBase, PrevNodeRaw>;
64
65 FilterF fFilter;
66 /// Column readers per slot and per input column
67 std::vector<std::array<RColumnReaderBase *, ColumnTypes_t::list_size>> fValues;
68 const std::shared_ptr<PrevNode_t> fPrevNodePtr;
70
71public:
72 RFilter(FilterF f, const ROOT::RDF::ColumnNames_t &columns, std::shared_ptr<PrevNode_t> pd,
73 const RDFInternal::RColumnRegister &colRegister, std::string_view name = "",
74 const std::string &variationName = "nominal")
75 : RFilterBase(pd->GetLoopManagerUnchecked(), name, pd->GetLoopManagerUnchecked()->GetNSlots(), colRegister,
76 columns, pd->GetVariations(), variationName),
77 fFilter(std::move(f)), fValues(pd->GetLoopManagerUnchecked()->GetNSlots()), fPrevNodePtr(std::move(pd)),
78 fPrevNode(*fPrevNodePtr)
79 {
80 fLoopManager->Register(this);
81 }
82
83 // Rule of five
84
85 RFilter(const RFilter &) = delete;
86 RFilter &operator=(const RFilter &) = delete;
87 RFilter(RFilter &&) = delete;
88 RFilter &operator=(RFilter &&) = delete;
90 {
91 // must Deregister objects from the RLoopManager here, before the fPrevNode data member is destroyed:
92 // otherwise if fPrevNode is the RLoopManager, it will be destroyed before the calls to Deregister happen.
93 fLoopManager->Deregister(this);
94 }
95
96 bool CheckFilters(unsigned int slot, Long64_t entry) final
97 {
98 if (entry != fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()]) {
99 if (!fPrevNode.CheckFilters(slot, entry)) {
100 // a filter upstream returned false, cache the result
101 fLastResult[slot * RDFInternal::CacheLineStep<int>()] = false;
102 } else {
103 // evaluate this filter, cache the result
104 auto passed = CheckFilterHelper(slot, entry, ColumnTypes_t{}, TypeInd_t{});
105 passed ? ++fAccepted[slot * RDFInternal::CacheLineStep<ULong64_t>()]
106 : ++fRejected[slot * RDFInternal::CacheLineStep<ULong64_t>()];
107 fLastResult[slot * RDFInternal::CacheLineStep<int>()] = passed;
108 }
109 fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = entry;
110 }
111 return fLastResult[slot * RDFInternal::CacheLineStep<int>()];
112 }
113
114 template <typename ColType>
115 auto GetValueChecked(unsigned int slot, std::size_t readerIdx, Long64_t entry) -> ColType &
116 {
117 if (auto *val = fValues[slot][readerIdx]->template TryGet<ColType>(entry))
118 return *val;
119
120 throw std::out_of_range{"RDataFrame: Filter could not retrieve value for column '" + fColumnNames[readerIdx] +
121 "' for entry " + std::to_string(entry) +
122 ". You can use the DefaultValueFor operation to provide a default value, or "
123 "FilterAvailable/FilterMissing to discard/keep entries with missing values instead."};
124 }
125
126 template <typename... ColTypes, std::size_t... S>
127 bool CheckFilterHelper(unsigned int slot, Long64_t entry, TypeList<ColTypes...>, std::index_sequence<S...>)
128 {
129 return fFilter(GetValueChecked<ColTypes>(slot, S, entry)...);
130 // avoid unused parameter warnings (gcc 12.1)
131 (void)slot;
132 (void)entry;
133 }
134
135 void InitSlot(TTreeReader *r, unsigned int slot) final
136 {
137 RDFInternal::RColumnReadersInfo info{fColumnNames, fColRegister, fIsDefine.data(), *fLoopManager};
138 fValues[slot] = RDFInternal::GetColumnReaders(slot, r, ColumnTypes_t{}, info, fVariation);
139 fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = -1;
140 }
141
142 // recursive chain of `Report`s
143 void Report(ROOT::RDF::RCutFlowReport &rep) const final { PartialReport(rep); }
144
146 {
147 fPrevNode.PartialReport(rep);
148 FillReport(rep);
149 }
150
152 {
153 ++fNStopsReceived;
154 if (fNStopsReceived == fNChildren)
155 fPrevNode.StopProcessing();
156 }
157
159 {
160 ++fNChildren;
161 // propagate "children activation" upstream. named filters do the propagation via `TriggerChildrenCount`.
162 if (fNChildren == 1 && fName.empty())
163 fPrevNode.IncrChildrenCount();
164 }
165
167 {
168 assert(!fName.empty()); // this method is to only be called on named filters
169 fPrevNode.IncrChildrenCount();
170 }
171
172 void AddFilterName(std::vector<std::string> &filters) final
173 {
174 fPrevNode.AddFilterName(filters);
175 auto name = (HasName() ? fName : "Unnamed Filter");
176 filters.push_back(name);
177 }
178
179 /// Clean-up operations to be performed at the end of a task.
180 void FinalizeSlot(unsigned int slot) final { fValues[slot].fill(nullptr); }
181
182 std::shared_ptr<RDFGraphDrawing::GraphNode>
183 GetGraph(std::unordered_map<void *, std::shared_ptr<RDFGraphDrawing::GraphNode>> &visitedMap) final
184 {
185 // Recursively call for the previous node.
186 auto prevNode = fPrevNode.GetGraph(visitedMap);
187 const auto &prevColumns = prevNode->GetDefinedColumns();
188
190
191 /* If the returned node is not new, there is no need to perform any other operation.
192 * This is a likely scenario when building the entire graph in which branches share
193 * some nodes. */
194 if (!thisNode->IsNew()) {
195 return thisNode;
196 }
197
198 auto upmostNode = AddDefinesToGraph(thisNode, fColRegister, prevColumns, visitedMap);
199
200 // Keep track of the columns defined up to this point.
201 thisNode->AddDefinedColumns(fColRegister.GenerateColumnNames());
202
203 upmostNode->SetPrevNode(prevNode);
204 return thisNode;
205 }
206
207 /// Return a clone of this Filter that works with values in the variationName "universe".
208 std::shared_ptr<RNodeBase> GetVariedFilter(const std::string &variationName) final
209 {
210 // Only the nominal filter should be asked to produce varied filters
211 assert(fVariation == "nominal");
212 // nobody should ask for a varied filter for the nominal variation: they can just
213 // use the nominal filter!
214 assert(variationName != "nominal");
215 // nobody should ask for a varied filter for a variation on which this filter does not depend:
216 // they can just use the nominal filter.
218
219 auto it = fVariedFilters.find(variationName);
220 if (it != fVariedFilters.end())
221 return it->second;
222
223 auto prevNode = fPrevNodePtr;
224 if (static_cast<RNodeBase *>(fPrevNodePtr.get()) != static_cast<RNodeBase *>(fLoopManager) &&
225 RDFInternal::IsStrInVec(variationName, prevNode->GetVariations()))
226 prevNode = std::static_pointer_cast<PrevNode_t>(prevNode->GetVariedFilter(variationName));
227
228 // the varied filters get a copy of the callable object.
229 // TODO document this
230 auto variedFilter = std::unique_ptr<RFilterBase>(
231 new RFilter(fFilter, fColumnNames, std::move(prevNode), fColRegister, fName, variationName));
232 auto e = fVariedFilters.insert({variationName, std::move(variedFilter)});
233 return e.first->second;
234 }
235};
236
237} // ns RDF
238} // ns Detail
239} // ns ROOT
240
241#endif // ROOT_RFILTER
#define f(i)
Definition RSha256.hxx:104
#define e(i)
Definition RSha256.hxx:103
long long Long64_t
Definition RtypesCore.h:69
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
const char * filters[]
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
char name[80]
Definition TGX11.cxx:110
void InitSlot(TTreeReader *r, unsigned int slot) final
Definition RFilter.hxx:135
auto GetValueChecked(unsigned int slot, std::size_t readerIdx, Long64_t entry) -> ColType &
Definition RFilter.hxx:115
bool CheckFilterHelper(unsigned int slot, Long64_t entry, TypeList< ColTypes... >, std::index_sequence< S... >)
Definition RFilter.hxx:127
void FinalizeSlot(unsigned int slot) final
Clean-up operations to be performed at the end of a task.
Definition RFilter.hxx:180
void Report(ROOT::RDF::RCutFlowReport &rep) const final
Definition RFilter.hxx:143
RFilter(FilterF f, const ROOT::RDF::ColumnNames_t &columns, std::shared_ptr< PrevNode_t > pd, const RDFInternal::RColumnRegister &colRegister, std::string_view name="", const std::string &variationName="nominal")
Definition RFilter.hxx:72
bool CheckFilters(unsigned int slot, Long64_t entry) final
Definition RFilter.hxx:96
RFilter & operator=(const RFilter &)=delete
void IncrChildrenCount() final
Definition RFilter.hxx:158
RFilter & operator=(RFilter &&)=delete
const std::shared_ptr< PrevNode_t > fPrevNodePtr
Definition RFilter.hxx:68
RFilter(RFilter &&)=delete
std::conditional_t< std::is_same< PrevNodeRaw, RJittedFilter >::value, RFilterBase, PrevNodeRaw > PrevNode_t
Definition RFilter.hxx:63
RFilter(const RFilter &)=delete
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
Definition RFilter.hxx:59
void StopProcessing() final
Definition RFilter.hxx:151
void AddFilterName(std::vector< std::string > &filters) final
Definition RFilter.hxx:172
std::shared_ptr< RNodeBase > GetVariedFilter(const std::string &variationName) final
Return a clone of this Filter that works with values in the variationName "universe".
Definition RFilter.hxx:208
std::shared_ptr< RDFGraphDrawing::GraphNode > GetGraph(std::unordered_map< void *, std::shared_ptr< RDFGraphDrawing::GraphNode > > &visitedMap) final
Definition RFilter.hxx:183
typename CallableTraits< FilterF >::arg_types ColumnTypes_t
Definition RFilter.hxx:58
void TriggerChildrenCount() final
Definition RFilter.hxx:166
std::vector< std::array< RColumnReaderBase *, ColumnTypes_t::list_size > > fValues
Column readers per slot and per input column.
Definition RFilter.hxx:67
void PartialReport(ROOT::RDF::RCutFlowReport &rep) const final
Definition RFilter.hxx:145
A wrapper around a concrete RFilter, which forwards all calls to it RJittedFilter is the type of the ...
Base class for non-leaf nodes of the computational graph.
Definition RNodeBase.hxx:43
A binder for user-defined columns, variations and aliases.
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
std::shared_ptr< GraphNode > CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr, std::unordered_map< void *, std::shared_ptr< GraphNode > > &visitedMap)
std::shared_ptr< GraphNode > AddDefinesToGraph(std::shared_ptr< GraphNode > node, const RColumnRegister &colRegister, const std::vector< std::string > &prevNodeDefines, std::unordered_map< void *, std::shared_ptr< GraphNode > > &visitedMap)
bool IsStrInVec(const std::string &str, const std::vector< std::string > &vec)
Definition RDFUtils.cxx:444
std::array< RDFDetail::RColumnReaderBase *, sizeof...(ColTypes)> GetColumnReaders(unsigned int slot, TTreeReader *treeReader, TypeList< ColTypes... >, const RColumnReadersInfo &colInfo, const std::string &variationName="nominal")
Create a group of column readers, one per type in the parameter pack.
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.