Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:35

0001 // Author: Enrico Guiraud, Danilo Piparo CERN  09/2018
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 #ifndef ROOT_RDFRANGE
0012 #define ROOT_RDFRANGE
0013 
0014 #include "ROOT/RDF/RLoopManager.hxx"
0015 #include "ROOT/RDF/RRangeBase.hxx"
0016 #include "ROOT/RDF/Utils.hxx"
0017 #include "RtypesCore.h"
0018 
0019 #include <cassert>
0020 #include <memory>
0021 #include <string>
0022 #include <string_view>
0023 #include <vector>
0024 
0025 namespace ROOT {
0026 
0027 // fwd decl
0028 namespace Internal {
0029 namespace RDF {
0030 namespace GraphDrawing {
0031 std::shared_ptr<GraphNode> CreateRangeNode(const ROOT::Detail::RDF::RRangeBase *rangePtr,
0032                                            std::unordered_map<void *, std::shared_ptr<GraphNode>> &visitedMap);
0033 } // ns GraphDrawing
0034 } // ns RDF
0035 } // ns Internal
0036 
0037 namespace Detail {
0038 namespace RDF {
0039 namespace RDFGraphDrawing = ROOT::Internal::RDF::GraphDrawing;
0040 class RJittedFilter;
0041 
0042 template <typename PrevNodeRaw>
0043 class RRange final : public RRangeBase {
0044    // If the PrevNode is a RJittedFilter, treat it as a more generic RFilterBase: when dealing with systematic
0045    // variations we'll have a RJittedFilter node for the nominal case but other "universes" will use concrete filters,
0046    // so we normalize the "previous node type" to the base type RFilterBase.
0047    using PrevNode_t = std::conditional_t<std::is_same<PrevNodeRaw, RJittedFilter>::value, RFilterBase, PrevNodeRaw>;
0048    const std::shared_ptr<PrevNode_t> fPrevNodePtr;
0049    PrevNode_t &fPrevNode;
0050 
0051 public:
0052    RRange(unsigned int start, unsigned int stop, unsigned int stride, std::shared_ptr<PrevNode_t> pd)
0053       : RRangeBase(pd->GetLoopManagerUnchecked(), start, stop, stride, pd->GetLoopManagerUnchecked()->GetNSlots(),
0054                    pd->GetVariations()),
0055         fPrevNodePtr(std::move(pd)), fPrevNode(*fPrevNodePtr)
0056    {
0057       fLoopManager->Register(this);
0058    }
0059 
0060    RRange(const RRange &) = delete;
0061    RRange &operator=(const RRange &) = delete;
0062    // must call Deregister here, before fPrevNode is destroyed,
0063    // otherwise if fPrevNode is fLoopManager we get a use after delete
0064    ~RRange() { fLoopManager->Deregister(this); }
0065 
0066    /// Ranges act as filters when it comes to selecting entries that downstream nodes should process
0067    bool CheckFilters(unsigned int slot, Long64_t entry) final
0068    {
0069       if (entry != fLastCheckedEntry) {
0070          if (fHasStopped)
0071             return false;
0072          if (!fPrevNode.CheckFilters(slot, entry)) {
0073             // a filter upstream returned false, cache the result
0074             fLastResult = false;
0075          } else {
0076             // apply range filter logic, cache the result
0077             if (fNProcessedEntries < fStart || (fStop > 0 && fNProcessedEntries >= fStop) ||
0078                 (fStride != 1 && (fNProcessedEntries - fStart) % fStride != 0))
0079                fLastResult = false;
0080             else
0081                fLastResult = true;
0082             ++fNProcessedEntries;
0083             if (fNProcessedEntries == fStop) {
0084                fHasStopped = true;
0085                fPrevNode.StopProcessing();
0086             }
0087          }
0088          fLastCheckedEntry = entry;
0089       }
0090       return fLastResult;
0091    }
0092 
0093    // recursive chain of `Report`s
0094    // RRange simply forwards these calls to the previous node
0095    void Report(ROOT::RDF::RCutFlowReport &rep) const final { fPrevNode.PartialReport(rep); }
0096 
0097    void PartialReport(ROOT::RDF::RCutFlowReport &rep) const final { fPrevNode.PartialReport(rep); }
0098 
0099    void StopProcessing() final
0100    {
0101       ++fNStopsReceived;
0102       if (fNStopsReceived == fNChildren && !fHasStopped)
0103          fPrevNode.StopProcessing();
0104    }
0105 
0106    void IncrChildrenCount() final
0107    {
0108       ++fNChildren;
0109       // propagate "children activation" upstream
0110       if (fNChildren == 1)
0111          fPrevNode.IncrChildrenCount();
0112    }
0113 
0114    /// This function must be defined by all nodes, but only the filters will add their name
0115    void AddFilterName(std::vector<std::string> &filters) final { fPrevNode.AddFilterName(filters); }
0116    std::shared_ptr<RDFGraphDrawing::GraphNode>
0117    GetGraph(std::unordered_map<void *, std::shared_ptr<RDFGraphDrawing::GraphNode>> &visitedMap) final
0118    {
0119       // TODO: Ranges node have no information about custom columns, hence it is not possible now
0120       // if defines have been used before.
0121       auto prevNode = fPrevNode.GetGraph(visitedMap);
0122       const auto &prevColumns = prevNode->GetDefinedColumns();
0123 
0124       auto thisNode = RDFGraphDrawing::CreateRangeNode(this, visitedMap);
0125 
0126       /* If the returned node is not new, there is no need to perform any other operation.
0127        * This is a likely scenario when building the entire graph in which branches share
0128        * some nodes. */
0129       if (!thisNode->IsNew()) {
0130          return thisNode;
0131       }
0132       thisNode->SetPrevNode(prevNode);
0133 
0134       // If there have been some defines between the last Filter and this Range node we won't detect them:
0135       // Ranges don't keep track of Defines (they have no RColumnRegister data member).
0136       // Let's pretend that the Defines of this node are the same as the node above, so that in the graph
0137       // the Defines will just appear below the Range instead (no functional change).
0138       // TODO: Converting the string_views for backward compatibility.
0139       // Since they are names of defined columns, they were added to the
0140       // register of column names of the RLoopManager object by the
0141       // RColumnRegister, so we could also change GetDefinedColumns to return string_views directly
0142       std::vector<std::string_view> colsViews;
0143       colsViews.reserve(prevColumns.size());
0144       for (const auto &col : prevColumns)
0145          colsViews.push_back(col);
0146       thisNode->AddDefinedColumns(colsViews);
0147 
0148       return thisNode;
0149    }
0150 
0151    std::shared_ptr<RNodeBase> GetVariedFilter(const std::string &variationName) final
0152    {
0153       // nobody should ask for a varied filter for the nominal variation: they can just
0154       // use the nominal filter!
0155       assert(variationName != "nominal");
0156       // nobody should ask for a varied filter for a variation on which this filter does not depend:
0157       // they can just use the nominal filter.
0158       assert(RDFInternal::IsStrInVec(variationName, fVariations));
0159 
0160       auto it = fVariedRanges.find(variationName);
0161       if (it != fVariedRanges.end())
0162          return it->second;
0163 
0164       auto prevNode = fPrevNodePtr;
0165       if (static_cast<RNodeBase *>(fPrevNodePtr.get()) != static_cast<RNodeBase *>(fLoopManager) &&
0166           RDFInternal::IsStrInVec(variationName, prevNode->GetVariations()))
0167          prevNode = std::static_pointer_cast<PrevNode_t>(prevNode->GetVariedFilter(variationName));
0168 
0169       auto variedRange = std::unique_ptr<RRangeBase>(new RRange(fStart, fStop, fStride, std::move(prevNode)));
0170       auto e = fVariedRanges.insert({variationName, std::move(variedRange)});
0171       return e.first->second;
0172    }
0173 };
0174 
0175 } // namespace RDF
0176 } // namespace Detail
0177 } // namespace ROOT
0178 
0179 #endif // ROOT_RDFRANGE