Logo ROOT  
Reference Guide
 
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> CreateFilterNode(const RFilterBase *filterPtr);
40
41std::shared_ptr<GraphNode> AddDefinesToGraph(std::shared_ptr<GraphNode> node,
42 const RDFInternal::RColumnRegister &colRegister,
43 const std::vector<std::string> &prevNodeDefines);
44} // ns GraphDrawing
45
46} // ns RDF
47} // ns Internal
48
49namespace Detail {
50namespace RDF {
51using namespace ROOT::TypeTraits;
53class RJittedFilter;
54
55template <typename FilterF, typename PrevNodeRaw>
56class R__CLING_PTRCHECK(off) RFilter final : public RFilterBase {
58 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
59 // If the PrevNode is a RJittedFilter, treat it as a more generic RFilterBase: when dealing with systematic
60 // variations we'll have a RJittedFilter node for the nominal case but other "universes" will use concrete filters,
61 // so we normalize the "previous node type" to the base type RFilterBase.
62 using PrevNode_t = std::conditional_t<std::is_same<PrevNodeRaw, RJittedFilter>::value, RFilterBase, PrevNodeRaw>;
63
64 FilterF fFilter;
65 /// Column readers per slot and per input column
66 std::vector<std::array<std::unique_ptr<RColumnReaderBase>, ColumnTypes_t::list_size>> fValues;
67 const std::shared_ptr<PrevNode_t> fPrevNodePtr;
69
70public:
71 RFilter(FilterF f, const ROOT::RDF::ColumnNames_t &columns, std::shared_ptr<PrevNode_t> pd,
72 const RDFInternal::RColumnRegister &colRegister, std::string_view name = "",
73 const std::string &variationName = "nominal")
74 : RFilterBase(pd->GetLoopManagerUnchecked(), name, pd->GetLoopManagerUnchecked()->GetNSlots(), colRegister,
75 columns, pd->GetVariations(), variationName),
76 fFilter(std::move(f)), fValues(pd->GetLoopManagerUnchecked()->GetNSlots()), fPrevNodePtr(std::move(pd)),
77 fPrevNode(*fPrevNodePtr)
78 {
79 fLoopManager->Book(this);
80 }
81
82 RFilter(const RFilter &) = delete;
83 RFilter &operator=(const RFilter &) = delete;
85 // must Deregister objects from the RLoopManager here, before the fPrevNode data member is destroyed:
86 // otherwise if fPrevNode is the RLoopManager, it will be destroyed before the calls to Deregister happen.
87 fColRegister.Clear(); // triggers RDefine deregistration
88 fLoopManager->Deregister(this);
89 }
90
91 bool CheckFilters(unsigned int slot, Long64_t entry) final
92 {
93 if (entry != fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()]) {
94 if (!fPrevNode.CheckFilters(slot, entry)) {
95 // a filter upstream returned false, cache the result
96 fLastResult[slot * RDFInternal::CacheLineStep<int>()] = false;
97 } else {
98 // evaluate this filter, cache the result
99 auto passed = CheckFilterHelper(slot, entry, ColumnTypes_t{}, TypeInd_t{});
100 passed ? ++fAccepted[slot * RDFInternal::CacheLineStep<ULong64_t>()]
101 : ++fRejected[slot * RDFInternal::CacheLineStep<ULong64_t>()];
102 fLastResult[slot * RDFInternal::CacheLineStep<int>()] = passed;
103 }
104 fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = entry;
105 }
106 return fLastResult[slot * RDFInternal::CacheLineStep<int>()];
107 }
108
109 template <typename... ColTypes, std::size_t... S>
110 bool CheckFilterHelper(unsigned int slot, Long64_t entry, TypeList<ColTypes...>, std::index_sequence<S...>)
111 {
112 // silence "unused parameter" warnings in gcc
113 (void)slot;
114 (void)entry;
115 return fFilter(fValues[slot][S]->template Get<ColTypes>(entry)...);
116 }
117
118 void InitSlot(TTreeReader *r, unsigned int slot) final
119 {
120 RDFInternal::RColumnReadersInfo info{fColumnNames, fColRegister, fIsDefine.data(), fLoopManager->GetDSValuePtrs(),
121 fLoopManager->GetDataSource()};
122 fValues[slot] = RDFInternal::MakeColumnReaders(slot, r, ColumnTypes_t{}, info, fVariation);
123 fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = -1;
124 }
125
126 // recursive chain of `Report`s
127 void Report(ROOT::RDF::RCutFlowReport &rep) const final { PartialReport(rep); }
128
130 {
131 fPrevNode.PartialReport(rep);
132 FillReport(rep);
133 }
134
135 void StopProcessing() final
136 {
137 ++fNStopsReceived;
138 if (fNStopsReceived == fNChildren)
139 fPrevNode.StopProcessing();
140 }
141
142 void IncrChildrenCount() final
143 {
144 ++fNChildren;
145 // propagate "children activation" upstream. named filters do the propagation via `TriggerChildrenCount`.
146 if (fNChildren == 1 && fName.empty())
147 fPrevNode.IncrChildrenCount();
148 }
149
151 {
152 assert(!fName.empty()); // this method is to only be called on named filters
153 fPrevNode.IncrChildrenCount();
154 }
155
156 void AddFilterName(std::vector<std::string> &filters)
157 {
158 fPrevNode.AddFilterName(filters);
159 auto name = (HasName() ? fName : "Unnamed Filter");
160 filters.push_back(name);
161 }
162
163 /// Clean-up operations to be performed at the end of a task.
164 virtual void FinaliseSlot(unsigned int slot) final
165 {
166 for (auto &v : fValues[slot])
167 v.reset();
168 }
169
170 std::shared_ptr<RDFGraphDrawing::GraphNode> GetGraph()
171 {
172 // Recursively call for the previous node.
173 auto prevNode = fPrevNode.GetGraph();
174 auto prevColumns = prevNode->GetDefinedColumns();
175
176 auto thisNode = RDFGraphDrawing::CreateFilterNode(this);
177
178 /* If the returned node is not new, there is no need to perform any other operation.
179 * This is a likely scenario when building the entire graph in which branches share
180 * some nodes. */
181 if (!thisNode->GetIsNew()) {
182 return thisNode;
183 }
184
185 auto upmostNode = AddDefinesToGraph(thisNode, fColRegister, prevColumns);
186
187 // Keep track of the columns defined up to this point.
188 thisNode->AddDefinedColumns(fColRegister.GetNames());
189
190 upmostNode->SetPrevNode(prevNode);
191 return thisNode;
192 }
193
194 /// Return a clone of this Filter that works with values in the variationName "universe".
195 std::shared_ptr<RNodeBase> GetVariedFilter(const std::string &variationName) final
196 {
197 // nobody should ask for a varied filter for the nominal variation: they can just
198 // use the nominal filter!
199 assert(variationName != "nominal");
200 // nobody should ask for a varied filter for a variation on which this filter does not depend:
201 // they can just use the nominal filter.
202 assert(RDFInternal::IsStrInVec(variationName, fVariations));
203
204 auto it = fVariedFilters.find(variationName);
205 if (it != fVariedFilters.end())
206 return it->second;
207
208 auto prevNode = fPrevNodePtr;
209 if (static_cast<RNodeBase *>(fPrevNodePtr.get()) != static_cast<RNodeBase *>(fLoopManager) &&
210 RDFInternal::IsStrInVec(variationName, prevNode->GetVariations()))
211 prevNode = std::static_pointer_cast<PrevNode_t>(prevNode->GetVariedFilter(variationName));
212
213 // the varied filters get a copy of the callable object.
214 // TODO document this
215 auto variedFilter = std::unique_ptr<RFilterBase>(
216 new RFilter(fFilter, fColumnNames, std::move(prevNode), fColRegister, fName, variationName));
217 auto e = fVariedFilters.insert({variationName, std::move(variedFilter)});
218 return e.first->second;
219 }
220};
221
222} // ns RDF
223} // ns Detail
224} // ns ROOT
225
226#endif // ROOT_RFILTER
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
ROOT::R::TRInterface & r
Definition Object.C:4
#define f(i)
Definition RSha256.hxx:104
#define e(i)
Definition RSha256.hxx:103
long long Long64_t
Definition RtypesCore.h:80
const char * filters[]
char name[80]
Definition TGX11.cxx:110
void InitSlot(TTreeReader *r, unsigned int slot) final
Definition RFilter.hxx:118
bool CheckFilterHelper(unsigned int slot, Long64_t entry, TypeList< ColTypes... >, std::index_sequence< S... >)
Definition RFilter.hxx:110
void Report(ROOT::RDF::RCutFlowReport &rep) const final
Definition RFilter.hxx:127
void AddFilterName(std::vector< std::string > &filters)
Definition RFilter.hxx:156
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:71
bool CheckFilters(unsigned int slot, Long64_t entry) final
Definition RFilter.hxx:91
RFilter & operator=(const RFilter &)=delete
void IncrChildrenCount() final
Definition RFilter.hxx:142
virtual void FinaliseSlot(unsigned int slot) final
Clean-up operations to be performed at the end of a task.
Definition RFilter.hxx:164
const std::shared_ptr< PrevNode_t > fPrevNodePtr
Definition RFilter.hxx:67
std::conditional_t< std::is_same< PrevNodeRaw, RJittedFilter >::value, RFilterBase, PrevNodeRaw > PrevNode_t
Definition RFilter.hxx:62
RFilter(const RFilter &)=delete
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
Definition RFilter.hxx:58
void StopProcessing() final
Definition RFilter.hxx:135
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:195
typename CallableTraits< FilterF >::arg_types ColumnTypes_t
Definition RFilter.hxx:57
void TriggerChildrenCount() final
Definition RFilter.hxx:150
std::vector< std::array< std::unique_ptr< RColumnReaderBase >, ColumnTypes_t::list_size > > fValues
Column readers per slot and per input column.
Definition RFilter.hxx:66
std::shared_ptr< RDFGraphDrawing::GraphNode > GetGraph()
Definition RFilter.hxx:170
void PartialReport(ROOT::RDF::RCutFlowReport &rep) const final
Definition RFilter.hxx:129
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:42
A binder for user-defined columns and aliases.
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:44
std::shared_ptr< GraphNode > AddDefinesToGraph(std::shared_ptr< GraphNode > node, const RColumnRegister &colRegister, const std::vector< std::string > &prevNodeDefines)
Add the Defines that have been added between this node and the previous to the graph.
std::shared_ptr< GraphNode > CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr)
bool IsStrInVec(const std::string &str, const std::vector< std::string > &vec)
Definition RDFUtils.cxx:419
std::array< std::unique_ptr< RDFDetail::RColumnReaderBase >, sizeof...(ColTypes)> MakeColumnReaders(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.
std::vector< std::string > ColumnNames_t
Definition Utils.hxx:35
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 MakeColumnReaders.
Lightweight storage for a collection of types.