Logo ROOT   6.21/01
Reference Guide
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 
16 #include "ROOT/RDF/NodesUtils.hxx"
17 #include "ROOT/RDF/Utils.hxx"
18 #include "ROOT/RDF/RFilterBase.hxx"
21 #include "ROOT/TypeTraits.hxx"
22 #include "RtypesCore.h"
23 
24 #include <algorithm>
25 #include <memory>
26 #include <string>
27 #include <vector>
28 
29 namespace ROOT {
30 
31 namespace Internal {
32 namespace RDF {
33 using namespace ROOT::Detail::RDF;
34 
35 // fwd decl for RFilter
36 namespace GraphDrawing {
37 std::shared_ptr<GraphNode> CreateFilterNode(const RFilterBase *filterPtr);
38 
39 bool CheckIfDefaultOrDSColumn(const std::string &name, const std::shared_ptr<RCustomColumnBase> &column);
40 
41 std::shared_ptr<GraphNode>
42 CreateDefineNode(const std::string &columnName, const RDFDetail::RCustomColumnBase *columnPtr);
43 } // ns GraphDrawing
44 
45 } // ns RDF
46 } // ns Internal
47 
48 namespace Detail {
49 namespace RDF {
50 using namespace ROOT::TypeTraits;
52 
53 template <typename FilterF, typename PrevDataFrame>
54 class RFilter final : public RFilterBase {
55  using ColumnTypes_t = typename CallableTraits<FilterF>::arg_types;
56  using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
57 
58  FilterF fFilter;
60  const std::shared_ptr<PrevDataFrame> fPrevDataPtr;
61  PrevDataFrame &fPrevData;
62  std::vector<RDFInternal::RDFValueTuple_t<ColumnTypes_t>> fValues;
63  /// The nth flag signals whether the nth input column is a custom column or not.
64  std::array<bool, ColumnTypes_t::list_size> fIsCustomColumn;
65 
66 public:
67  RFilter(FilterF &&f, const ColumnNames_t &columns, std::shared_ptr<PrevDataFrame> pd,
68  const RDFInternal::RBookedCustomColumns &customColumns, std::string_view name = "")
69  : RFilterBase(pd->GetLoopManagerUnchecked(), name, pd->GetLoopManagerUnchecked()->GetNSlots(), customColumns),
70  fFilter(std::forward<FilterF>(f)), fColumnNames(columns), fPrevDataPtr(std::move(pd)), fPrevData(*fPrevDataPtr),
71  fValues(fNSlots), fIsCustomColumn()
72  {
73  const auto nColumns = fColumnNames.size();
74  for (auto i = 0u; i < nColumns; ++i)
75  fIsCustomColumn[i] = fCustomColumns.HasName(fColumnNames[i]);
76  }
77 
78  RFilter(const RFilter &) = delete;
79  RFilter &operator=(const RFilter &) = delete;
80  // must call Deregister here, before fPrevDataFrame is destroyed,
81  // otherwise if fPrevDataFrame is fLoopManager we get a use after delete
82  ~RFilter() { fLoopManager->Deregister(this); }
83 
84  bool CheckFilters(unsigned int slot, Long64_t entry) final
85  {
86  if (entry != fLastCheckedEntry[slot]) {
87  if (!fPrevData.CheckFilters(slot, entry)) {
88  // a filter upstream returned false, cache the result
89  fLastResult[slot] = false;
90  } else {
91  // evaluate this filter, cache the result
92  auto passed = CheckFilterHelper(slot, entry, TypeInd_t());
93  passed ? ++fAccepted[slot] : ++fRejected[slot];
94  fLastResult[slot] = passed;
95  }
96  fLastCheckedEntry[slot] = entry;
97  }
98  return fLastResult[slot];
99  }
100 
101  template <std::size_t... S>
102  bool CheckFilterHelper(unsigned int slot, Long64_t entry, std::index_sequence<S...>)
103  {
104  // silence "unused parameter" warnings in gcc
105  (void)slot;
106  (void)entry;
107  return fFilter(std::get<S>(fValues[slot]).Get(entry)...);
108  }
109 
110  void InitSlot(TTreeReader *r, unsigned int slot) final
111  {
112  for (auto &bookedBranch : fCustomColumns.GetColumns())
113  bookedBranch.second->InitSlot(r, slot);
114  RDFInternal::InitRDFValues(slot, fValues[slot], r, fColumnNames, fCustomColumns, TypeInd_t(), fIsCustomColumn);
115  }
116 
117  // recursive chain of `Report`s
118  void Report(ROOT::RDF::RCutFlowReport &rep) const final { PartialReport(rep); }
119 
121  {
122  fPrevData.PartialReport(rep);
123  FillReport(rep);
124  }
125 
126  void StopProcessing() final
127  {
128  ++fNStopsReceived;
129  if (fNStopsReceived == fNChildren)
130  fPrevData.StopProcessing();
131  }
132 
133  void IncrChildrenCount() final
134  {
135  ++fNChildren;
136  // propagate "children activation" upstream. named filters do the propagation via `TriggerChildrenCount`.
137  if (fNChildren == 1 && fName.empty())
138  fPrevData.IncrChildrenCount();
139  }
140 
141  void TriggerChildrenCount() final
142  {
143  R__ASSERT(!fName.empty()); // this method is to only be called on named filters
144  fPrevData.IncrChildrenCount();
145  }
146 
147  virtual void ClearValueReaders(unsigned int slot) final
148  {
149  RDFInternal::ResetRDFValueTuple(fValues[slot], TypeInd_t());
150  }
151 
152  void AddFilterName(std::vector<std::string> &filters)
153  {
154  fPrevData.AddFilterName(filters);
155  auto name = (HasName() ? fName : "Unnamed Filter");
156  filters.push_back(name);
157  }
158 
159  virtual void ClearTask(unsigned int slot) final
160  {
161  for (auto &column : fCustomColumns.GetColumns()) {
162  column.second->ClearValueReaders(slot);
163  }
164 
165  ClearValueReaders(slot);
166  }
167 
168  std::shared_ptr<RDFGraphDrawing::GraphNode> GetGraph()
169  {
170  // Recursively call for the previous node.
171  auto prevNode = fPrevData.GetGraph();
172  auto prevColumns = prevNode->GetDefinedColumns();
173 
174  auto thisNode = RDFGraphDrawing::CreateFilterNode(this);
175 
176  /* If the returned node is not new, there is no need to perform any other operation.
177  * This is a likely scenario when building the entire graph in which branches share
178  * some nodes. */
179  if (!thisNode->GetIsNew()) {
180  return thisNode;
181  }
182 
183  auto evaluatedNode = thisNode;
184  /* Each column that this node has but the previous hadn't has been defined in between,
185  * so it has to be built and appended. */
186 
187  for (auto &column : fCustomColumns.GetColumns()) {
188  // Even if treated as custom columns by the Dataframe, datasource columns must not be in the graph.
189  if (RDFGraphDrawing::CheckIfDefaultOrDSColumn(column.first, column.second))
190  continue;
191  if (std::find(prevColumns.begin(), prevColumns.end(), column.first) == prevColumns.end()) {
192  auto defineNode = RDFGraphDrawing::CreateDefineNode(column.first, column.second.get());
193  evaluatedNode->SetPrevNode(defineNode);
194  evaluatedNode = defineNode;
195  }
196  }
197 
198  // Keep track of the columns defined up to this point.
199  thisNode->AddDefinedColumns(fCustomColumns.GetNames());
200 
201  evaluatedNode->SetPrevNode(prevNode);
202  return thisNode;
203  }
204 };
205 
206 } // ns RDF
207 } // ns Detail
208 } // ns ROOT
209 
210 #endif // ROOT_RFILTER
std::vector< RDFInternal::RDFValueTuple_t< ColumnTypes_t > > fValues
Definition: RFilter.hxx:62
virtual void ClearTask(unsigned int slot) final
Definition: RFilter.hxx:159
long long Long64_t
Definition: RtypesCore.h:69
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree...
Definition: TTreeReader.h:43
Returns the available number of logical cores.
Definition: StringConv.hxx:21
std::shared_ptr< RDFGraphDrawing::GraphNode > GetGraph()
Definition: RFilter.hxx:168
PrevDataFrame & fPrevData
Definition: RFilter.hxx:61
RFilter(FilterF &&f, const ColumnNames_t &columns, std::shared_ptr< PrevDataFrame > pd, const RDFInternal::RBookedCustomColumns &customColumns, std::string_view name="")
Definition: RFilter.hxx:67
#define R__ASSERT(e)
Definition: TError.h:96
#define f(i)
Definition: RSha256.hxx:104
unsigned int GetNSlots()
Definition: RDFUtils.cxx:257
STL namespace.
std::array< bool, ColumnTypes_t::list_size > fIsCustomColumn
The nth flag signals whether the nth input column is a custom column or not.
Definition: RFilter.hxx:64
typename CallableTraits< FilterF >::arg_types ColumnTypes_t
Definition: RFilter.hxx:55
void TriggerChildrenCount() final
Definition: RFilter.hxx:141
RooArgSet S(const RooAbsArg &v1)
void AddFilterName(std::vector< std::string > &filters)
Definition: RFilter.hxx:152
const char * filters[]
ROOT::R::TRInterface & r
Definition: Object.C:4
bool CheckFilters(unsigned int slot, Long64_t entry) final
Definition: RFilter.hxx:84
bool CheckIfDefaultOrDSColumn(const std::string &name, const std::shared_ptr< RCustomColumnBase > &column)
void StopProcessing() final
Definition: RFilter.hxx:126
void InitRDFValues(unsigned int slot, RDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn, const RBookedCustomColumns &customCols, std::index_sequence< S... >, const std::array< bool, sizeof...(S)> &isCustomColumn)
Initialize a tuple of RColumnValues.
Definition: NodesUtils.hxx:54
std::shared_ptr< GraphNode > CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RCustomColumnBase *columnPtr)
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
Definition: RFilter.hxx:56
bool CheckFilterHelper(unsigned int slot, Long64_t entry, std::index_sequence< S... >)
Definition: RFilter.hxx:102
ROOT type_traits extensions.
Definition: TypeTraits.hxx:23
void ResetRDFValueTuple(std::vector< RTypeErasedColumnValue > &values, std::index_sequence< S... >, ROOT::TypeTraits::TypeList< ColTypes... >)
This overload is specialized to act on RTypeErasedColumnValues instead of RColumnValues.
Definition: RAction.hxx:88
void forward(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData)
apply the weights (and functions) in forward direction of the DNN
Definition: NeuralNet.icc:546
const std::shared_ptr< PrevDataFrame > fPrevDataPtr
Definition: RFilter.hxx:60
virtual void ClearValueReaders(unsigned int slot) final
Definition: RFilter.hxx:147
void Report(ROOT::RDF::RCutFlowReport &rep) const final
Definition: RFilter.hxx:118
Binding & operator=(OUT(*fun)(void))
typedef void((*Func_t)())
std::shared_ptr< GraphNode > CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr)
void IncrChildrenCount() final
Definition: RFilter.hxx:133
Encapsulates the columns defined by the user.
const ColumnNames_t fColumnNames
Definition: RFilter.hxx:59
void InitSlot(TTreeReader *r, unsigned int slot) final
Definition: RFilter.hxx:110
char name[80]
Definition: TGX11.cxx:109
ROOT::Detail::RDF::ColumnNames_t ColumnNames_t
Definition: RDataFrame.cxx:797
void PartialReport(ROOT::RDF::RCutFlowReport &rep) const final
Definition: RFilter.hxx:120