Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:29:48

0001 // Author: Vincenzo Eduardo Padulano, CERN 09/2024
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2024, 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_RDF_RDefaultValueFor
0012 #define ROOT_RDF_RDefaultValueFor
0013 
0014 #include "ROOT/RDF/ColumnReaderUtils.hxx"
0015 #include "ROOT/RDF/RColumnReaderBase.hxx"
0016 #include "ROOT/RDF/RDefineBase.hxx"
0017 #include "ROOT/RDF/RLoopManager.hxx"
0018 #include "ROOT/RDF/Utils.hxx"
0019 #include <string_view>
0020 #include "ROOT/TypeTraits.hxx"
0021 #include "RtypesCore.h"
0022 
0023 #include <deque>
0024 #include <type_traits>
0025 #include <utility> // std::index_sequence
0026 #include <vector>
0027 
0028 class TTreeReader;
0029 
0030 namespace ROOT {
0031 namespace Detail {
0032 namespace RDF {
0033 
0034 using namespace ROOT::TypeTraits;
0035 
0036 /**
0037  * \brief The implementation of the DefaultValueFor transformation.
0038  *
0039  * The class takes in the default value provided by the user to fill-in missing
0040  * values of the input column. During the Update step, the class checks for the
0041  * presence of the value of the column at the current event. If that value is
0042  * missing, it will return the default value to requesting nodes of the graph.
0043  */
0044 template <typename T>
0045 class R__CLING_PTRCHECK(off) RDefaultValueFor final : public RDefineBase {
0046    using ColumnTypes_t = ROOT::TypeTraits::TypeList<T>;
0047    using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
0048    // Avoid instantiating vector<bool> as `operator[]` returns temporaries in that case. Use std::deque instead.
0049    using ValuesPerSlot_t = std::conditional_t<std::is_same<T, bool>::value, std::deque<T>, std::vector<T>>;
0050 
0051    T fDefaultValue;
0052    ValuesPerSlot_t fLastResults;
0053    // One column reader per slot
0054    std::vector<RColumnReaderBase *> fValues;
0055 
0056    /// Define objects corresponding to systematic variations other than nominal for this defined column.
0057    /// The map key is the full variation name, e.g. "pt:up".
0058    std::unordered_map<std::string, std::unique_ptr<RDefineBase>> fVariedDefines;
0059 
0060    T &GetValueOrDefault(unsigned int slot, Long64_t entry)
0061    {
0062       if (auto *value = fValues[slot]->template TryGet<T>(entry))
0063          return *value;
0064       else
0065          return fDefaultValue;
0066    };
0067 
0068 public:
0069    RDefaultValueFor(std::string_view name, std::string_view type, const T &defaultValue,
0070                     const ROOT::RDF::ColumnNames_t &columns, const RDFInternal::RColumnRegister &colRegister,
0071                     RLoopManager &lm, const std::string &variationName = "nominal")
0072       : RDefineBase(name, type, colRegister, lm, columns, variationName),
0073         fDefaultValue(defaultValue),
0074         fLastResults(lm.GetNSlots() * RDFInternal::CacheLineStep<T>()),
0075         fValues(lm.GetNSlots())
0076    {
0077       fLoopManager->Register(this);
0078       // We suppress errors that TTreeReader prints regarding the missing branch
0079       fLoopManager->InsertSuppressErrorsForMissingBranch(fColumnNames[0]);
0080    }
0081 
0082    RDefaultValueFor(const RDefaultValueFor &) = delete;
0083    RDefaultValueFor &operator=(const RDefaultValueFor &) = delete;
0084    RDefaultValueFor(RDefaultValueFor &&) = delete;
0085    RDefaultValueFor &operator=(RDefaultValueFor &&) = delete;
0086    ~RDefaultValueFor()
0087    {
0088       fLoopManager->Deregister(this);
0089       fLoopManager->EraseSuppressErrorsForMissingBranch(fColumnNames[0]);
0090    }
0091 
0092    void InitSlot(TTreeReader *r, unsigned int slot) final
0093    {
0094       fValues[slot] =
0095          RDFInternal::GetColumnReader(slot, fColRegister.GetReader(slot, fColumnNames[0], fVariation, typeid(T)),
0096                                       *fLoopManager, r, fColumnNames[0], typeid(T));
0097       fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = -1;
0098    }
0099 
0100    /// Return the (type-erased) address of the Define'd value for the given processing slot.
0101    void *GetValuePtr(unsigned int slot) final
0102    {
0103       return static_cast<void *>(&fLastResults[slot * RDFInternal::CacheLineStep<T>()]);
0104    }
0105 
0106    /// Update the value at the address returned by GetValuePtr with the content corresponding to the given entry
0107    void Update(unsigned int slot, Long64_t entry) final
0108    {
0109       if (entry != fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()]) {
0110          // evaluate this define expression, cache the result
0111          fLastResults[slot * RDFInternal::CacheLineStep<T>()] = GetValueOrDefault(slot, entry);
0112          fLastCheckedEntry[slot * RDFInternal::CacheLineStep<Long64_t>()] = entry;
0113       }
0114    }
0115 
0116    void Update(unsigned int /*slot*/, const ROOT::RDF::RSampleInfo & /*id*/) final {}
0117 
0118    const std::type_info &GetTypeId() const final { return typeid(T); }
0119 
0120    /// Clean-up operations to be performed at the end of a task.
0121    void FinalizeSlot(unsigned int slot) final
0122    {
0123       fValues[slot] = nullptr;
0124 
0125       for (auto &e : fVariedDefines)
0126          e.second->FinalizeSlot(slot);
0127    }
0128 
0129    /// Create clones of this Define that work with values in varied "universes".
0130    void MakeVariations(const std::vector<std::string> &variations) final
0131    {
0132       for (const auto &variation : variations) {
0133          if (std::find(fVariationDeps.begin(), fVariationDeps.end(), variation) == fVariationDeps.end()) {
0134             // this Defined quantity does not depend on this variation, so no need to create a varied RDefine
0135             continue;
0136          }
0137          if (fVariedDefines.find(variation) != fVariedDefines.end())
0138             continue; // we already have this variation stored
0139 
0140          // the varied defines get a copy of the callable object.
0141          // TODO document this
0142          auto variedDefine = std::unique_ptr<RDefineBase>(
0143             new RDefaultValueFor(fName, fType, fDefaultValue, fColumnNames, fColRegister, *fLoopManager, variation));
0144          fVariedDefines.insert({variation, std::move(variedDefine)});
0145       }
0146    }
0147 
0148    /// Return a clone of this Define that works with values in the variationName "universe".
0149    RDefineBase &GetVariedDefine(const std::string &variationName) final
0150    {
0151       auto it = fVariedDefines.find(variationName);
0152       if (it == fVariedDefines.end()) {
0153          // We don't have a varied RDefine for this variation.
0154          // This means we don't depend on it and we can return ourselves, i.e. the RDefine for the nominal universe.
0155          assert(std::find(fVariationDeps.begin(), fVariationDeps.end(), variationName) == fVariationDeps.end());
0156          return *this;
0157       }
0158 
0159       return *(it->second);
0160    }
0161 };
0162 
0163 } // namespace RDF
0164 } // namespace Detail
0165 } // namespace ROOT
0166 
0167 #endif // ROOT_RDF_RDefaultValueFor