Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RResultMap.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, CERN 11/2021
2
3/*************************************************************************
4 * Copyright (C) 1995-2022, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#ifndef ROOT_RDF_RRESULTMAP
12#define ROOT_RDF_RRESULTMAP
13
17#include "ROOT/RDF/Utils.hxx" // Union
18
19#include <memory>
20#include <stdexcept>
21#include <string>
22#include <unordered_map>
23#include <vector>
24
25namespace ROOT {
26
27namespace RDF {
28
29namespace Experimental {
30// fwd decl for MakeResultMap
31template <typename T>
32class RResultMap;
33} // namespace Experimental
34} // namespace RDF
35
36namespace Detail {
37namespace RDF {
38template <typename T>
39std::unique_ptr<RMergeableVariations<T>> GetMergeableValue(ROOT::RDF::Experimental::RResultMap<T> &rmap);
40} // namespace RDF
41} // namespace Detail
42
43namespace Internal {
44namespace RDF {
45template <typename T>
47MakeResultMap(std::shared_ptr<T> nominalResult, std::vector<std::shared_ptr<T>> &&variedResults,
48 std::vector<std::string> &&keys, RLoopManager &lm,
49 std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
50 std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction)
51{
52 return ROOT::RDF::Experimental::RResultMap<T>(std::move(nominalResult), std::move(variedResults), std::move(keys),
53 lm, std::move(nominalAction), std::move(variedAction));
54}
55
56/**
57 * \brief Clones an RResultMap and its corresponding RVariedAction
58 *
59 * \tparam T The type of the results held by the map.
60 * \param inmap The map.
61 * \return ROOT::RDF::Experimental::RResultMap<T> A new map with the cloned variations.
62 */
63template <typename T>
65{
66 std::shared_ptr<T> nominalResult{inmap.fMap.at("nominal")};
67 auto nominalAction{inmap.fNominalAction->CloneAction(reinterpret_cast<void *>(&nominalResult))};
68
69 std::size_t nVariations{inmap.fMap.size() - 1};
70 std::vector<std::shared_ptr<T>> variedResults;
71 variedResults.reserve(nVariations);
72 for (auto i = 0u; i < nVariations; ++i)
73 variedResults.emplace_back(new T{*nominalResult});
74
75 std::vector<void *> typeErasedResults;
76 typeErasedResults.reserve(nVariations);
77 for (auto &res : variedResults)
78 typeErasedResults.push_back(&res);
79 auto variedAction{inmap.fVariedAction->CloneAction(reinterpret_cast<void *>(&typeErasedResults))};
80
81 std::vector<std::string> variationNames{inmap.fKeys};
82 Erase<std::string>("nominal", variationNames);
83
84 return ROOT::RDF::Experimental::RResultMap<T>(std::move(nominalResult), std::move(variedResults),
85 std::move(variationNames), *(inmap.fLoopManager),
86 std::move(nominalAction), std::move(variedAction));
87}
88} // namespace RDF
89} // namespace Internal
90
91namespace RDF {
92
93class RResultHandle;
94
95namespace Experimental {
96
97template <typename T>
99
100 std::vector<std::string> fKeys; // values are the keys available in fMap
101 std::unordered_map<std::string, std::shared_ptr<T>> fMap; // shared_ptrs are never null
103 std::shared_ptr<ROOT::Internal::RDF::RActionBase> fNominalAction; // never null
104 std::shared_ptr<ROOT::Internal::RDF::RActionBase> fVariedAction; // might be null if there are no variations
105
107 ROOT::Internal::RDF::MakeResultMap<T>(std::shared_ptr<T> nominalResult,
108 std::vector<std::shared_ptr<T>> &&variedResults,
109 std::vector<std::string> &&keys, ROOT::Detail::RDF::RLoopManager &lm,
110 std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
111 std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction);
112
113 friend RResultMap ROOT::Internal::RDF::CloneResultAndAction<T>(const RResultMap<T> &inmap);
114 friend std::unique_ptr<ROOT::Detail::RDF::RMergeableVariations<T>>
115 ROOT::Detail::RDF::GetMergeableValue<T>(RResultMap<T> &rmap);
116 friend class ::ROOT::RDF::RResultHandle;
117
118 // The preconditions are that results and keys have the same size, are ordered the same way, and keys are unique.
119 RResultMap(std::shared_ptr<T> &&nominalResult, std::vector<std::shared_ptr<T>> &&variedResults,
120 std::vector<std::string> &&keys, ROOT::Detail::RDF::RLoopManager &lm,
121 std::shared_ptr<ROOT::Internal::RDF::RActionBase> nominalAction,
122 std::shared_ptr<ROOT::Internal::RDF::RActionBase> variedAction)
123 : fKeys{ROOT::Internal::RDF::Union({std::string("nominal")}, keys)}, fLoopManager(&lm),
124 fNominalAction(std::move(nominalAction)), fVariedAction(std::move(variedAction))
125 {
126 R__ASSERT(variedResults.size() == keys.size() && "Keys and values have different sizes!");
127 std::size_t i = 0u;
128 fMap.insert({"nominal", std::move(nominalResult)});
129 for (const auto &k : keys) {
130 auto it = fMap.insert({k, variedResults[i++]});
131 R__ASSERT(it.second &&
132 "Failed to insert an element in RResultMap, maybe a duplicated key? This should never happen.");
133 }
134 }
135
137 {
138 if ((fVariedAction != nullptr && !fVariedAction->HasRun()) || !fNominalAction->HasRun())
139 fLoopManager->Run();
140 }
141
142public:
143 using iterator = typename decltype(fMap)::iterator;
144 using const_iterator = typename decltype(fMap)::const_iterator;
145
146 // TODO: can we use a std::string_view here without having to create a temporary std::string anyway?
147 T &operator[](const std::string &key)
148 {
149 auto it = fMap.find(key);
150 if (it == fMap.end())
151 throw std::runtime_error("RResultMap: no result with key \"" + key + "\".");
152
153 RunEventLoopIfNeeded();
154 return *it->second;
155 }
156
157 /// Iterator to walk through key-value pairs of all variations for a given object.
158 /// Runs the event loop before returning if necessary.
160 {
161 RunEventLoopIfNeeded();
162 return fMap.begin();
163 }
164
166 {
167 RunEventLoopIfNeeded();
168 return fMap.cbegin();
169 }
170
172 {
173 RunEventLoopIfNeeded();
174 return fMap.end();
175 }
176
178 {
179 RunEventLoopIfNeeded();
180 return fMap.cend();
181 }
182
183 const std::vector<std::string> &GetKeys() const { return fKeys; }
184};
185
186} // namespace Experimental
187} // namespace RDF
188
189namespace Detail {
190namespace RDF {
191////////////////////////////////////////////////////////////////////////////////
192/// \brief Retrieve mergeable values after calling ROOT::RDF::VariationsFor .
193/// \param[in] rmap lvalue reference of an RResultMap object.
194/// \returns A container with the variation names and then variation values.
195///
196/// This function triggers the execution of the RDataFrame computation graph.
197/// Then retrieves an RMergeableVariations object created with the results held
198/// by the RResultMap input. The user obtains ownership of the mergeable, which
199/// in turn holds a copy variation names and variation results. The RResultMap
200/// is not destroyed in the process and will still retain (shared) ownership of
201/// the original results.
202///
203/// Example usage:
204/// ~~~{.cpp}
205/// auto df = ROOT::RDataFrame(10).Define("x", [] { return 1; });
206/// auto h = df.Vary("x", [](){return ROOT::RVecI{-1, 2};}, {}, 2).Histo1D<int>("x");
207/// auto hs = ROOT::RDF::Experimental::VariationsFor(h);
208/// std::unique_ptr<RMergeableVariations<T>> m = ROOT::Detail::RDF::GetMergeableValue(hs);
209/// ~~~
210template <typename T>
211std::unique_ptr<RMergeableVariations<T>> GetMergeableValue(ROOT::RDF::Experimental::RResultMap<T> &rmap)
212{
214
215 std::unique_ptr<RMergeableVariationsBase> mVariationsBase;
216 if (rmap.fVariedAction != nullptr) {
217 auto mValueBase = rmap.fVariedAction->GetMergeableValue();
218 mVariationsBase.reset(static_cast<RMergeableVariationsBase *>(mValueBase.release())); // downcast unique_ptr
219 } else {
220 mVariationsBase = std::unique_ptr<RMergeableVariationsBase>({}, {});
221 }
222 mVariationsBase->AddNominal(rmap.fNominalAction->GetMergeableValue());
223
224 return std::make_unique<RMergeableVariations<T>>(std::move(*mVariationsBase));
225}
226} // namespace RDF
227} // namespace Detail
228} // namespace ROOT
229
230#endif
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
The head node of a RDF computation graph.
A container for variation names and variation results.
typename decltype(fMap)::const_iterator const_iterator
T & operator[](const std::string &key)
ROOT::Detail::RDF::RLoopManager * fLoopManager
RResultMap(std::shared_ptr< T > &&nominalResult, std::vector< std::shared_ptr< T > > &&variedResults, std::vector< std::string > &&keys, ROOT::Detail::RDF::RLoopManager &lm, std::shared_ptr< ROOT::Internal::RDF::RActionBase > nominalAction, std::shared_ptr< ROOT::Internal::RDF::RActionBase > variedAction)
const std::vector< std::string > & GetKeys() const
typename decltype(fMap)::iterator iterator
std::shared_ptr< ROOT::Internal::RDF::RActionBase > fNominalAction
std::unordered_map< std::string, std::shared_ptr< T > > fMap
iterator begin()
Iterator to walk through key-value pairs of all variations for a given object.
std::vector< std::string > fKeys
std::shared_ptr< ROOT::Internal::RDF::RActionBase > fVariedAction
std::unique_ptr< RMergeableVariations< T > > GetMergeableValue(ROOT::RDF::Experimental::RResultMap< T > &rmap)
Retrieve mergeable values after calling ROOT::RDF::VariationsFor .
ROOT::RDF::Experimental::RResultMap< T > MakeResultMap(std::shared_ptr< T > nominalResult, std::vector< std::shared_ptr< T > > &&variedResults, std::vector< std::string > &&keys, RLoopManager &lm, std::shared_ptr< ROOT::Internal::RDF::RActionBase > nominalAction, std::shared_ptr< ROOT::Internal::RDF::RActionBase > variedAction)
ROOT::RDF::Experimental::RResultMap< T > CloneResultAndAction(const ROOT::RDF::Experimental::RResultMap< T > &inmap)
Clones an RResultMap and its corresponding RVariedAction.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...