15 #include "ROOT/RArrayView.hxx"
35 namespace TDFInternal = ROOT::Internal::TDF;
49 class TLoopManager :
public std::enable_shared_from_this<TLoopManager> {
58 std::shared_ptr<TTree>
fTree{
nullptr};
77 std::shared_ptr<TLoopManager>
GetSharedPtr() {
return shared_from_this(); }
88 void Book(
const std::shared_ptr<bool> &branchPtr);
105 using namespace ROOT::Detail::TDF;
128 template <
typename T>
134 std::unique_ptr<TTreeReaderValue<T>> fReaderValue{
nullptr};
136 std::unique_ptr<TTreeReaderArray<ProxyParam_t>> fReaderArray{
nullptr};
139 T *fValuePtr{
nullptr};
141 unsigned int fSlot{0};
151 bool useReaderValue = std::is_same<ProxyParam_t, T>::value;
158 template <
typename U =
T,
159 typename std::enable_if<std::is_same<typename TColumnValue<U>::ProxyParam_t, U>::value,
int>
::type = 0>
162 template <typename U = T, typename std::enable_if<!std::is_same<ProxyParam_t, U>::value,
int>
::type = 0>
165 auto &readerArray = *fReaderArray;
166 if (readerArray.GetSize() > 1 && 1 != (&readerArray[1] - &readerArray[0])) {
167 std::string exceptionText =
"Branch ";
168 exceptionText += fReaderArray->GetBranchName();
169 exceptionText +=
" hangs from a non-split branch. For this reason, it cannot be accessed via an array_view."
170 " Please read the top level branch instead.";
171 throw std::runtime_error(exceptionText.c_str());
174 return std::array_view<ProxyParam_t>(fReaderArray->begin(), fReaderArray->end());
179 fReaderValue =
nullptr;
180 fReaderArray =
nullptr;
182 fTmpColumn =
nullptr;
187 template <
typename T>
191 template <
typename... BranchTypes>
193 using type = std::tuple<TColumnValue<BranchTypes>...>;
196 template <
typename BranchType>
209 virtual void Run(
unsigned int slot,
Long64_t entry) = 0;
210 virtual void Init(
TTreeReader *
r,
unsigned int slot) = 0;
211 virtual void CreateSlots(
unsigned int nSlots) = 0;
214 template <
typename Helper,
typename PrevDataFrame,
typename BranchTypes_t =
typename Helper::BranchTypes_t>
216 using TypeInd_t =
typename TGenStaticSeq<BranchTypes_t::fgSize>::Type_t;
221 std::vector<TDFValueTuple_t<BranchTypes_t>>
fValues;
224 TAction(Helper &&
h,
const ColumnNames_t &bl, PrevDataFrame &pd)
225 :
TActionBase(pd.GetImplPtr(), pd.GetTmpBranches()), fHelper(std::move(
h)), fBranches(bl), fPrevData(pd)
231 void CreateSlots(
unsigned int nSlots)
final { fValues.resize(nSlots); }
235 InitTDFValues(slot, fValues[slot],
r, fBranches, fTmpBranches, fImplPtr->GetBookedBranches(),
TypeInd_t());
236 fHelper.Init(
r, slot);
242 if (fPrevData.CheckFilters(slot, entry)) Exec(slot, entry,
TypeInd_t());
249 fHelper.Exec(slot, std::get<S>(fValues[slot]).Get(entry)...);
267 unsigned int fNChildren{0};
268 unsigned int fNStopsReceived{0};
273 virtual void Init(
TTreeReader *
r,
unsigned int slot) = 0;
274 virtual void CreateSlots(
unsigned int nSlots) = 0;
275 virtual void *GetValuePtr(
unsigned int slot) = 0;
276 virtual const std::type_info &GetTypeId()
const = 0;
277 virtual bool CheckFilters(
unsigned int slot,
Long64_t entry) = 0;
279 virtual void Report()
const = 0;
280 virtual void PartialReport()
const = 0;
282 ColumnNames_t GetTmpBranches()
const;
283 virtual void Update(
unsigned int slot,
Long64_t entry) = 0;
285 virtual void StopProcessing() = 0;
288 template <
typename F,
typename PrevData>
291 using TypeInd_t =
typename TDFInternal::TGenStaticSeq<BranchTypes_t::fgSize>::Type_t;
292 using Ret_t =
typename TDFInternal::TFunctionTraits<F>::Ret_t;
298 std::vector<Long64_t> fLastCheckedEntry = {-1};
300 std::vector<TDFInternal::TDFValueTuple_t<BranchTypes_t>>
fValues;
304 :
TCustomColumnBase(pd.GetImplPtr(), pd.GetTmpBranches(), name), fExpression(std::move(expression)),
305 fBranches(bl), fPrevData(pd)
307 fTmpBranches.emplace_back(name);
314 TDFInternal::InitTDFValues(slot, fValues[slot],
r, fBranches, fTmpBranches, fImplPtr->GetBookedBranches(),
318 void *
GetValuePtr(
unsigned int slot)
final {
return static_cast<void *
>(fLastResultPtr[slot].get()); }
322 if (entry != fLastCheckedEntry[slot]) {
325 fLastCheckedEntry[slot] = entry;
333 fValues.resize(nSlots);
334 fLastCheckedEntry.resize(nSlots, -1);
335 fLastResultPtr.resize(nSlots);
336 std::generate(fLastResultPtr.begin(), fLastResultPtr.end(), []() {
return std::unique_ptr<Ret_t>(
new Ret_t()); });
342 return fPrevData.CheckFilters(slot, entry);
345 template <
int...
S,
typename... BranchTypes>
347 TDFInternal::TTypeList<BranchTypes...>)
349 *fLastResultPtr[slot] = fExpression(std::get<S>(fValues[slot]).Get(entry)...);
354 void Report() const final { fPrevData.PartialReport(); }
361 if (fNStopsReceived == fNChildren) fPrevData.StopProcessing();
370 std::vector<Long64_t> fLastCheckedEntry = {-1};
371 std::vector<int> fLastResult = {
true};
372 std::vector<ULong64_t> fAccepted = {0};
373 std::vector<ULong64_t> fRejected = {0};
375 unsigned int fNChildren{0};
376 unsigned int fNStopsReceived{0};
381 virtual void Init(
TTreeReader *
r,
unsigned int slot) = 0;
382 virtual bool CheckFilters(
unsigned int slot,
Long64_t entry) = 0;
383 virtual void Report()
const = 0;
384 virtual void PartialReport()
const = 0;
386 ColumnNames_t GetTmpBranches()
const;
387 bool HasName()
const;
388 virtual void CreateSlots(
unsigned int nSlots) = 0;
389 void PrintReport()
const;
391 virtual void StopProcessing() = 0;
394 template <
typename FilterF,
typename PrevDataFrame>
396 using BranchTypes_t =
typename TDFInternal::TFunctionTraits<FilterF>::Args_t;
397 using TypeInd_t =
typename TDFInternal::TGenStaticSeq<BranchTypes_t::fgSize>::Type_t;
402 std::vector<TDFInternal::TDFValueTuple_t<BranchTypes_t>>
fValues;
405 TFilter(FilterF &&
f,
const ColumnNames_t &bl, PrevDataFrame &pd, std::string_view
name =
"")
406 :
TFilterBase(pd.GetImplPtr(), pd.GetTmpBranches(),
name), fFilter(std::move(
f)), fBranches(bl), fPrevData(pd)
414 fValues.resize(nSlots);
415 fLastCheckedEntry.resize(nSlots, -1);
416 fLastResult.resize(nSlots);
417 fAccepted.resize(nSlots);
418 fRejected.resize(nSlots);
421 std::fill(fAccepted.begin(), fAccepted.end(), 0);
422 std::fill(fRejected.begin(), fRejected.end(), 0);
427 if (entry != fLastCheckedEntry[slot]) {
428 if (!fPrevData.CheckFilters(slot, entry)) {
430 fLastResult[slot] =
false;
433 auto passed = CheckFilterHelper(slot, entry,
TypeInd_t());
434 passed ? ++fAccepted[slot] : ++fRejected[slot];
435 fLastResult[slot] = passed;
437 fLastCheckedEntry[slot] = entry;
439 return fLastResult[slot];
445 return fFilter(std::get<S>(fValues[slot]).Get(entry)...);
450 TDFInternal::InitTDFValues(slot, fValues[slot],
r, fBranches, fTmpBranches, fImplPtr->GetBookedBranches(),
455 void Report() const final { PartialReport(); }
459 fPrevData.PartialReport();
466 if (fNStopsReceived == fNChildren) fPrevData.StopProcessing();
479 bool fLastResult{
true};
481 unsigned int fNChildren{0};
482 unsigned int fNStopsReceived{0};
485 TRangeBase(
TLoopManager *implPtr,
const ColumnNames_t &tmpBranches,
unsigned int start,
unsigned int stop,
486 unsigned int stride);
489 ColumnNames_t GetTmpBranches()
const;
490 virtual bool CheckFilters(
unsigned int slot,
Long64_t entry) = 0;
491 virtual void Report()
const = 0;
492 virtual void PartialReport()
const = 0;
494 virtual void StopProcessing() = 0;
497 template <
typename PrevData>
502 TRange(
unsigned int start,
unsigned int stop,
unsigned int stride, PrevData &pd)
503 :
TRangeBase(pd.GetImplPtr(), pd.GetTmpBranches(), start, stop, stride), fPrevData(pd)
512 if (entry != fLastCheckedEntry) {
513 if (!fPrevData.CheckFilters(slot, entry)) {
518 ++fNProcessedEntries;
519 if (fNProcessedEntries <= fStart || (fStop > 0 && fNProcessedEntries > fStop) ||
520 (fStride != 1 && fNProcessedEntries % fStride != 0))
524 if (fNProcessedEntries == fStop) fPrevData.StopProcessing();
526 fLastCheckedEntry = entry;
533 void Report() const final { fPrevData.PartialReport(); }
540 if (fNStopsReceived == fNChildren) fPrevData.StopProcessing();
549 template <
typename T>
554 fTmpColumn = tmpColumn;
556 throw std::runtime_error(std::string(
"TColumnValue: type specified is ") +
typeid(
T).
name() +
557 " but temporary column has type " + tmpColumn->
GetTypeId().name());
558 fValuePtr =
static_cast<T *
>(tmpColumn->
GetValuePtr(slot));
566 template <
typename T>
567 template <
typename U,
568 typename std::enable_if<std::is_same<typename ROOT::Internal::TDF::TColumnValue<U>::ProxyParam_t, U>::value,
573 return *(fReaderValue->Get());
575 fTmpColumn->Update(fSlot, entry);
580 #endif // ROOT_TDFNODES
typename TTDFValueTuple< BranchType >::type TDFValueTuple_t
std::string GetName(const std::string &scope_name)
RangeBaseVec_t fBookedRanges
virtual ~TCustomColumnBase()
FilterBaseVec_t fBookedFilters
void Report() const final
bool CheckFilters(unsigned int slot, Long64_t entry) final
const std::type_info & GetTypeId() const
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
void Init(TTreeReader *r, unsigned int slot) final
PrevDataFrame & fPrevData
std::array_view< ProxyParam_t > Get(Long64_t)
bool CheckFilterHelper(unsigned int slot, Long64_t entry, TDFInternal::TStaticSeq< S...>)
std::vector< TDFValueTuple_t< BranchTypes_t > > fValues
void PartialReport() const final
typename std::conditional< std::is_same< ReaderValueOrArray_t< T >, TTreeReaderValue< T >>::value, T, ExtractType_t< T >>::type ProxyParam_t
std::vector< std::unique_ptr< Ret_t > > fLastResultPtr
void CreateSlots(unsigned int nSlots)
void PartialReport() const final
void Report() const
Call PrintReport on all booked filters.
::TDirectory * GetDirectory() const
void Update(unsigned int slot, Long64_t entry) final
void PartialReport() const
End of recursive chain of calls, does nothing.
TLoopManager(TTree *tree, const ColumnNames_t &defaultBranches)
const ColumnNames_t GetTmpBranches() const
std::vector< TDFInternal::TDFValueTuple_t< BranchTypes_t > > fValues
std::map< std::string, TmpBranchBasePtr_t > fBookedBranches
void generate(R &r, TH1D *h)
void Init(TTreeReader *r, unsigned int slot) final
const ColumnNames_t fBranches
unsigned int fNChildren
Number of nodes of the functional graph hanging from this object.
void InitAllNodes(TTreeReader *r, unsigned int slot)
Build TTreeReaderValues for all nodes.
void Book(const ActionBasePtr_t &actionPtr)
TAction(Helper &&h, const ColumnNames_t &bl, PrevDataFrame &pd)
void PartialReport() const final
const ColumnNames_t fTmpBranches
void MakeProxy(TTreeReader *r, const std::string &bn)
unsigned int GetNSlots() const
const std::map< std::string, TmpBranchBasePtr_t > & GetBookedBranches() const
std::shared_ptr< TFilterBase > FilterBasePtr_t
bool HasRunAtLeastOnce() const
typename TDFInternal::TFunctionTraits< FilterF >::Args_t BranchTypes_t
Helper class that updates and returns TTree branches as well as TDataFrame temporary columns...
typename TDFInternal::TFunctionTraits< F >::Ret_t Ret_t
bool CheckFilters(unsigned int slot, Long64_t entry) final
typename TDFInternal::TGenStaticSeq< BranchTypes_t::fgSize >::Type_t TypeInd_t
bool CheckFilters(int, unsigned int)
std::shared_ptr< TLoopManager > GetSharedPtr()
void SetTmpColumn(unsigned int slot, TCustomColumnBase *tmpColumn)
const ColumnNames_t fTmpBranches
typename TGenStaticSeq< BranchTypes_t::fgSize >::Type_t TypeInd_t
Extracts data from a TTree.
const ColumnNames_t fBranches
ActionBaseVec_t fBookedActions
PrevDataFrame & fPrevData
std::vector< FilterBasePtr_t > FilterBaseVec_t
void UpdateHelper(unsigned int slot, Long64_t entry, TDFInternal::TStaticSeq< S...>, TDFInternal::TTypeList< BranchTypes...>)
TCustomColumn(std::string_view name, F &&expression, const ColumnNames_t &bl, PrevData &pd)
RooArgSet S(const RooAbsArg &v1)
TRange(unsigned int start, unsigned int stop, unsigned int stride, PrevData &pd)
void RunAndCheckFilters(unsigned int slot, Long64_t entry)
void Report() const final
std::vector< RangeBasePtr_t > RangeBaseVec_t
std::tuple< TColumnValue< BranchTypes >...> type
std::vector< ActionBasePtr_t > ActionBaseVec_t
const Long64_t fNEmptyEntries
unsigned int fNStopsReceived
Number of times that a children node signaled to stop processing entries.
void CreateSlots(unsigned int nSlots)
Initialize all nodes of the functional graph before running the event loop.
std::shared_ptr< TCustomColumnBase > TmpBranchBasePtr_t
TLoopManager * fImplPtr
A raw pointer to the TLoopManager at the root of this functional graph.
const unsigned int fNSlots
void SetTree(std::shared_ptr< TTree > tree)
void CreateSlots(unsigned int nSlots) final
std::vector< TDFInternal::TDFValueTuple_t< BranchTypes_t > > fValues
typename TDFInternal::TFunctionTraits< F >::Args_t BranchTypes_t
const ColumnNames_t & GetDefaultBranches() const
void Reset(Detail::TBranchProxy *x)
FilterBaseVec_t fBookedNamedFilters
TFilter(FilterF &&f, const ColumnNames_t &bl, PrevDataFrame &pd, std::string_view name="")
ColumnNames_t fTmpBranches
virtual const std::type_info & GetTypeId() const =0
Describe directory structure in memory.
unsigned long long ULong64_t
void Run(unsigned int slot, Long64_t entry) final
ColumnNames_t fTmpBranches
TLoopManager * fImplPtr
A raw pointer to the TLoopManager at the root of this functional graph.
const ColumnNames_t fDefaultBranches
void * GetValuePtr(unsigned int slot) final
void Exec(unsigned int slot, Long64_t entry, TStaticSeq< S...>)
std::shared_ptr< TDFInternal::TActionBase > ActionBasePtr_t
TLoopManager * fImplPtr
A raw pointer to the TLoopManager at the root of this functional graph.
TCustomColumnBase * GetBookedBranch(const std::string &name) const
TLoopManager * GetImplPtr()
typedef void((*Func_t)())
Long64_t GetNEmptyEntries() const
std::shared_ptr< TTree > fTree
typename TDFInternal::TGenStaticSeq< BranchTypes_t::fgSize >::Type_t TypeInd_t
void Report() const final
const ColumnNames_t fBranches
A TTree object has a header with a name and a title.
void CreateSlots(unsigned int nSlots) final
std::vector< std::shared_ptr< bool > > fResProxyReadiness
void Init(TTreeReader *r, unsigned int slot) final
TLoopManager * fImplPtr
A raw pointer to the TLoopManager at the root of this functional graph.
virtual void * GetValuePtr(unsigned int slot)=0
std::shared_ptr< TRangeBase > RangeBasePtr_t
bool CheckFilters(unsigned int slot, Long64_t entry) final
Ranges act as filters when it comes to selecting entries that downstream nodes should process...