diff --git a/tree/treeplayer/inc/ROOT/TDFNodes.hxx b/tree/treeplayer/inc/ROOT/TDFNodes.hxx index dfedd528b6bd0..ba2f1d08b72fa 100644 --- a/tree/treeplayer/inc/ROOT/TDFNodes.hxx +++ b/tree/treeplayer/inc/ROOT/TDFNodes.hxx @@ -65,15 +65,15 @@ class TDataFrameImpl : public std::enable_shared_from_this { ROOT::Detail::FilterBaseVec_t fBookedFilters; ROOT::Detail::FilterBaseVec_t fBookedNamedFilters; std::map fBookedBranches; - ROOT::Detail::RangeBaseVec_t fBookedRanges; + ROOT::Detail::RangeBaseVec_t fBookedRanges; std::vector> fResProxyReadiness; ::TDirectory * fDirPtr{nullptr}; TTree * fTree{nullptr}; const BranchNames_t fDefaultBranches; const unsigned int fNSlots{0}; bool fHasRunAtLeastOnce{false}; - unsigned int fNChildren = 0; ///< Number of nodes of the functional graph hanging from this object - unsigned int fNStopsReceived = 0; ///< Number of times that a children node signaled to stop processing entries. + unsigned int fNChildren{0}; ///< Number of nodes of the functional graph hanging from this object + unsigned int fNStopsReceived{0}; ///< Number of times that a children node signaled to stop processing entries. public: TDataFrameImpl(TTree *tree, const BranchNames_t &defaultBranches); @@ -144,8 +144,8 @@ class TDataFrameValue { /// T == std::array_view. T * fValuePtr{nullptr}; //< Non-owning ptr to the value of a temporary column. ROOT::Detail::TDataFrameBranchBase *fTmpColumn{ - nullptr}; //< Non-owning ptr to the node responsible for the temporary column. - unsigned int fSlot = 0; //< The slot this value belongs to. Only used for temporary columns, not for real branches. + nullptr}; //< Non-owning ptr to the node responsible for the temporary column. + unsigned int fSlot{0}; //< The slot this value belongs to. Only used for temporary columns, not for real branches. public: TDataFrameValue() = default; @@ -260,8 +260,8 @@ protected: /// guaranteed to contain a valid address during an event loop. BranchNames_t fTmpBranches; const std::string fName; - unsigned int fNChildren = 0; ///< Number of nodes of the functional graph hanging from this object - unsigned int fNStopsReceived = 0; ///< Number of times that a children node signaled to stop processing entries. + unsigned int fNChildren{0}; ///< Number of nodes of the functional graph hanging from this object + unsigned int fNStopsReceived{0}; ///< Number of times that a children node signaled to stop processing entries. public: TDataFrameBranchBase(TDataFrameImpl *df, const BranchNames_t &tmpBranches, const std::string &name); @@ -277,7 +277,7 @@ public: std::string GetName() const; BranchNames_t GetTmpBranches() const; virtual void Update(unsigned int slot, Long64_t entry) = 0; - void IncrChildrenCount() { ++fNChildren; } + void IncrChildrenCount() { ++fNChildren; } virtual void StopProcessing() = 0; }; @@ -351,10 +351,10 @@ public: void PartialReport() const final { fPrevData.PartialReport(); } - void StopProcessing() { + void StopProcessing() + { ++fNStopsReceived; - if (fNStopsReceived == fNChildren) - fPrevData.StopProcessing(); + if (fNStopsReceived == fNChildren) fPrevData.StopProcessing(); } }; @@ -368,8 +368,8 @@ protected: std::vector fAccepted = {0}; std::vector fRejected = {0}; const std::string fName; - unsigned int fNChildren = 0; ///< Number of nodes of the functional graph hanging from this object - unsigned int fNStopsReceived = 0; ///< Number of times that a children node signaled to stop processing entries. + unsigned int fNChildren{0}; ///< Number of nodes of the functional graph hanging from this object + unsigned int fNStopsReceived{0}; ///< Number of times that a children node signaled to stop processing entries. public: TDataFrameFilterBase(TDataFrameImpl *df, const BranchNames_t &tmpBranches, const std::string &name); @@ -382,8 +382,8 @@ public: BranchNames_t GetTmpBranches() const; bool HasName() const; virtual void CreateSlots(unsigned int nSlots) = 0; - void PrintReport() const; - void IncrChildrenCount() { ++fNChildren; } + void PrintReport() const; + void IncrChildrenCount() { ++fNChildren; } virtual void StopProcessing() = 0; }; @@ -457,10 +457,10 @@ public: PrintReport(); } - void StopProcessing() { + void StopProcessing() + { ++fNStopsReceived; - if (fNStopsReceived == fNChildren) - fPrevData.StopProcessing(); + if (fNStopsReceived == fNChildren) fPrevData.StopProcessing(); } }; @@ -472,11 +472,11 @@ protected: unsigned int fStart; unsigned int fStop; unsigned int fStride; - Long64_t fLastCheckedEntry = -1; - bool fLastResult = true; - ULong64_t fNProcessedEntries = 0; - unsigned int fNChildren = 0; ///< Number of nodes of the functional graph hanging from this object - unsigned int fNStopsReceived = 0; ///< Number of times that a children node signaled to stop processing entries. + Long64_t fLastCheckedEntry{-1}; + bool fLastResult{true}; + ULong64_t fNProcessedEntries{0}; + unsigned int fNChildren{0}; ///< Number of nodes of the functional graph hanging from this object + unsigned int fNStopsReceived{0}; ///< Number of times that a children node signaled to stop processing entries. public: TDataFrameRangeBase(TDataFrameImpl *implPtr, const BranchNames_t &tmpBranches, unsigned int start, unsigned int stop, diff --git a/tree/treeplayer/src/TDataFrame.cxx b/tree/treeplayer/src/TDataFrame.cxx index 8e379078ece3b..3ae147ad97b1c 100644 --- a/tree/treeplayer/src/TDataFrame.cxx +++ b/tree/treeplayer/src/TDataFrame.cxx @@ -360,6 +360,26 @@ Stats are printed in the same order as named filters have been added to the grap that has been run using the relevant `TDataFrame`. If `Report` is called before the event-loop has been run at least once, a run is triggered. +### Ranges +When `TDataFrame` is not being used in a multi-thread environment (i.e. no call to `EnableImplicitMT` was made), +`Range` transformations are available. These act very much like filters but instead of basing their decision on +a filter expression, they rely on `start`,`stop` and `stride` parameters. + +- `start`: number of entries that will be skipped before starting processing again +- `stop`: maximum number of entries that will be processed +- `stride`: only process one entry every `stride` entries + +The actual number of entries processed downstream of a `Range` node will be `(stop - start)/stride` (or less if less +entries than that are available). + +Note that ranges act "locally", not based on the global entry count: `Range(10,50)` means "skip the first 10 entries +*that reach this node*, let the next 40 entries pass, then stop processing". If a range node hangs from a filter node, +and the range has a `start` parameter of 10, that means the range will skip the first 10 entries *that pass the +preceding filter*. + +Ranges allow "early quitting": if all branches of execution of a functional graph reached their `stop` value of +processed entries, the event-loop is immediately interrupted. This is useful for debugging and initial explorations. + ### Temporary columns Temporary columns are created by invoking `AddColumn(name, f, branchList)`. As usual, `f` can be any callable object (function, lambda expression, functor class...); it takes the values of the branches listed in `branchList` (a list of