Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Author: Enrico Guiraud, CERN 11/2021
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2022, 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_RRESULTMAP
0012 #define ROOT_RDF_RRESULTMAP
0013 
0014 #include "ROOT/RDF/RActionBase.hxx"
0015 #include "ROOT/RDF/RLoopManager.hxx"
0016 #include "ROOT/RDF/RMergeableValue.hxx"
0017 #include "ROOT/RDF/Utils.hxx" // Union
0018 
0019 #include <memory>
0020 #include <stdexcept>
0021 #include <string>
0022 #include <unordered_map>
0023 #include <vector>
0024 
0025 namespace ROOT {
0026 
0027 namespace RDF {
0028 
0029 namespace Experimental {
0030 // fwd decl for MakeResultMap
0031 template <typename T>
0032 class RResultMap;
0033 } // namespace Experimental
0034 } // namespace RDF
0035 
0036 namespace Detail {
0037 namespace RDF {
0038 template <typename T>
0039 std::unique_ptr<RMergeableVariations<T>> GetMergeableValue(ROOT::RDF::Experimental::RResultMap<T> &rmap);
0040 } // namespace RDF
0041 } // namespace Detail
0042 
0043 namespace Internal {
0044 namespace RDF {
0045 template <typename T>
0046 ROOT::RDF::Experimental::RResultMap<T>
0047 MakeResultMap(std::shared_ptr<T> nominalResult, std::vector<std::shared_ptr<T>> &&variedResults,
0048               std::vector<std::string> &&keys, RLoopManager &lm,
0049               std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
0050               std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction)
0051 {
0052    return ROOT::RDF::Experimental::RResultMap<T>(std::move(nominalResult), std::move(variedResults), std::move(keys),
0053                                                  lm, std::move(nominalAction), std::move(variedAction));
0054 }
0055 
0056 /**
0057  * \brief Clones an RResultMap and its corresponding RVariedAction
0058  *
0059  * \tparam T The type of the results held by the map.
0060  * \param inmap The map.
0061  * \return ROOT::RDF::Experimental::RResultMap<T> A new map with the cloned variations.
0062  */
0063 template <typename T>
0064 ROOT::RDF::Experimental::RResultMap<T> CloneResultAndAction(const ROOT::RDF::Experimental::RResultMap<T> &inmap)
0065 {
0066    std::shared_ptr<T> nominalResult{inmap.fMap.at("nominal")};
0067    auto nominalAction{inmap.fNominalAction->CloneAction(reinterpret_cast<void *>(&nominalResult))};
0068 
0069    std::size_t nVariations{inmap.fMap.size() - 1};
0070    std::vector<std::shared_ptr<T>> variedResults;
0071    variedResults.reserve(nVariations);
0072    for (auto i = 0u; i < nVariations; ++i)
0073       variedResults.emplace_back(new T{*nominalResult});
0074 
0075    std::vector<void *> typeErasedResults;
0076    typeErasedResults.reserve(nVariations);
0077    for (auto &res : variedResults)
0078       typeErasedResults.push_back(&res);
0079    auto variedAction{inmap.fVariedAction->CloneAction(reinterpret_cast<void *>(&typeErasedResults))};
0080 
0081    std::vector<std::string> variationNames{inmap.fKeys};
0082    Erase<std::string>("nominal", variationNames);
0083 
0084    return ROOT::RDF::Experimental::RResultMap<T>(std::move(nominalResult), std::move(variedResults),
0085                                                  std::move(variationNames), *(inmap.fLoopManager),
0086                                                  std::move(nominalAction), std::move(variedAction));
0087 }
0088 } // namespace RDF
0089 } // namespace Internal
0090 
0091 namespace RDF {
0092 
0093 class RResultHandle;
0094 
0095 namespace Experimental {
0096 
0097 template <typename T>
0098 class RResultMap {
0099 
0100    std::vector<std::string> fKeys;                            // values are the keys available in fMap
0101    std::unordered_map<std::string, std::shared_ptr<T>> fMap;  // shared_ptrs are never null
0102    ROOT::Detail::RDF::RLoopManager *fLoopManager;             // never null
0103    std::shared_ptr<ROOT::Internal::RDF::RActionBase> fNominalAction; // never null
0104    std::shared_ptr<ROOT::Internal::RDF::RActionBase> fVariedAction;  // might be null if there are no variations
0105 
0106    friend RResultMap
0107    ROOT::Internal::RDF::MakeResultMap<T>(std::shared_ptr<T> nominalResult,
0108                                          std::vector<std::shared_ptr<T>> &&variedResults,
0109                                          std::vector<std::string> &&keys, ROOT::Detail::RDF::RLoopManager &lm,
0110                                          std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
0111                                          std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction);
0112 
0113    friend RResultMap ROOT::Internal::RDF::CloneResultAndAction<T>(const RResultMap<T> &inmap);
0114    friend std::unique_ptr<ROOT::Detail::RDF::RMergeableVariations<T>>
0115    ROOT::Detail::RDF::GetMergeableValue<T>(RResultMap<T> &rmap);
0116    friend class ::ROOT::RDF::RResultHandle;
0117 
0118    // The preconditions are that results and keys have the same size, are ordered the same way, and keys are unique.
0119    RResultMap(std::shared_ptr<T> &&nominalResult, std::vector<std::shared_ptr<T>> &&variedResults,
0120               std::vector<std::string> &&keys, ROOT::Detail::RDF::RLoopManager &lm,
0121               std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
0122               std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction)
0123       : fKeys{ROOT::Internal::RDF::Union({std::string("nominal")}, keys)}, fLoopManager(&lm),
0124         fNominalAction(std::move(nominalAction)), fVariedAction(std::move(variedAction))
0125    {
0126       R__ASSERT(variedResults.size() == keys.size() && "Keys and values have different sizes!");
0127       std::size_t i = 0u;
0128       fMap.insert({"nominal", std::move(nominalResult)});
0129       for (const auto &k : keys) {
0130          auto it = fMap.insert({k, variedResults[i++]});
0131          R__ASSERT(it.second &&
0132                    "Failed to insert an element in RResultMap, maybe a duplicated key? This should never happen.");
0133       }
0134    }
0135 
0136    void RunEventLoopIfNeeded()
0137    {
0138       if ((fVariedAction != nullptr && !fVariedAction->HasRun()) || !fNominalAction->HasRun())
0139          fLoopManager->Run();
0140    }
0141 
0142 public:
0143    using iterator = typename decltype(fMap)::iterator;
0144    using const_iterator = typename decltype(fMap)::const_iterator;
0145 
0146    // TODO: can we use a std::string_view here without having to create a temporary std::string anyway?
0147    T &operator[](const std::string &key)
0148    {
0149       auto it = fMap.find(key);
0150       if (it == fMap.end())
0151          throw std::runtime_error("RResultMap: no result with key \"" + key + "\".");
0152 
0153       RunEventLoopIfNeeded();
0154       return *it->second;
0155    }
0156 
0157    /// Iterator to walk through key-value pairs of all variations for a given object.
0158    /// Runs the event loop before returning if necessary.
0159    iterator begin()
0160    {
0161       RunEventLoopIfNeeded();
0162       return fMap.begin();
0163    }
0164 
0165    const_iterator cbegin()
0166    {
0167       RunEventLoopIfNeeded();
0168       return fMap.cbegin();
0169    }
0170 
0171    iterator end()
0172    {
0173       RunEventLoopIfNeeded();
0174       return fMap.end();
0175    }
0176 
0177    const_iterator cend() const
0178    {
0179       RunEventLoopIfNeeded();
0180       return fMap.cend();
0181    }
0182 
0183    const std::vector<std::string> &GetKeys() const { return fKeys; }
0184 };
0185 
0186 } // namespace Experimental
0187 } // namespace RDF
0188 
0189 namespace Detail {
0190 namespace RDF {
0191 ////////////////////////////////////////////////////////////////////////////////
0192 /// \brief Retrieve mergeable values after calling ROOT::RDF::VariationsFor .
0193 /// \param[in] rmap lvalue reference of an RResultMap object.
0194 /// \returns A container with the variation names and then variation values.
0195 ///
0196 /// This function triggers the execution of the RDataFrame computation graph.
0197 /// Then retrieves an RMergeableVariations object created with the results held
0198 /// by the RResultMap input. The user obtains ownership of the mergeable, which
0199 /// in turn holds a copy variation names and variation results. The RResultMap
0200 /// is not destroyed in the process and will still retain (shared) ownership of
0201 /// the original results.
0202 ///
0203 /// Example usage:
0204 /// ~~~{.cpp}
0205 /// auto df = ROOT::RDataFrame(10).Define("x", [] { return 1; });
0206 /// auto h = df.Vary("x", [](){return ROOT::RVecI{-1, 2};}, {}, 2).Histo1D<int>("x");
0207 /// auto hs = ROOT::RDF::Experimental::VariationsFor(h);
0208 /// std::unique_ptr<RMergeableVariations<T>> m = ROOT::Detail::RDF::GetMergeableValue(hs);
0209 /// ~~~
0210 template <typename T>
0211 std::unique_ptr<RMergeableVariations<T>> GetMergeableValue(ROOT::RDF::Experimental::RResultMap<T> &rmap)
0212 {
0213    rmap.RunEventLoopIfNeeded();
0214 
0215    std::unique_ptr<RMergeableVariationsBase> mVariationsBase;
0216    if (rmap.fVariedAction != nullptr) {
0217       auto mValueBase = rmap.fVariedAction->GetMergeableValue();
0218       mVariationsBase.reset(static_cast<RMergeableVariationsBase *>(mValueBase.release())); // downcast unique_ptr
0219    } else {
0220       mVariationsBase = std::unique_ptr<RMergeableVariationsBase>({}, {});
0221    }
0222    mVariationsBase->AddNominal(rmap.fNominalAction->GetMergeableValue());
0223 
0224    return std::make_unique<RMergeableVariations<T>>(std::move(*mVariationsBase));
0225 }
0226 } // namespace RDF
0227 } // namespace Detail
0228 } // namespace ROOT
0229 
0230 #endif