ATLAS Offline Software
Loading...
Searching...
No Matches
SystematicsCache.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef PAT_INTERFACES__SYSTEMATICS_CACHE_H
9#define PAT_INTERFACES__SYSTEMATICS_CACHE_H
10
16#include <functional>
17#include <mutex>
18#include <tbb/concurrent_unordered_map.h>
19
20namespace CP
21{
82
83 template<typename CalibData>
85 {
88
89 public:
90
92
93 template<typename T2>
94 SystematicsCache (T2 *val_parent);
95
98 void initialize (CP::SystematicSet val_affectingSystematics,
99 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> val_calc) noexcept;
100
103
104
110
111
115
116
118 StatusCode add (const CP::SystematicSet& sys, CalibData value);
119 StatusCode add (const SystematicVariation& variation, CalibData value);
120
121
124
125 private:
126
129
132 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> m_calc;
133
135 mutable tbb::concurrent_unordered_map<CP::SystematicSet,std::shared_ptr<const CalibData>,SystematicSetHash> m_cache ATLAS_THREAD_SAFE;
136
142 };
143
144
145
148
149 template<typename CalibData> template<typename T2>
151 SystematicsCache (T2 *val_parent)
152 : AsgMessagingForward (val_parent)
153 {}
154
155
156
157 template<typename CalibData> void SystematicsCache<CalibData> ::
158 initialize (CP::SystematicSet val_affectingSystematics,
159 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> val_calc) noexcept
160 {
161 m_calc = std::move (val_calc);
162 m_affectingSystematics = std::move (val_affectingSystematics);
163 m_cache.clear ();
164 }
165
166
167
168 template<typename CalibData>
174
175
176
177 template<typename CalibData>
180 {
181 // this is not technically correct, but what a lot of people do
182 return m_affectingSystematics.find (sys) != m_affectingSystematics.end();
183 }
184
185
186
187 template<typename CalibData>
189 get (const CP::SystematicSet& sys, const CalibData*& result) const
190 {
191 // fast-path, check if we already calculated this
192 auto iter = m_cache.find (sys);
193 if (ATH_LIKELY (iter != m_cache.end())) //[[likely]], removed until C++20 support
194 {
195 result = iter->second.get();
196 return StatusCode::SUCCESS;
197 }
198
199 // create a lock to prevent the concurrent (or duplicate)
200 // execution of the \ref m_calc function. if that function is
201 // thread-safe this lock is not strictly necessary. however,
202 // given that it is hard to enforce that the function is indeed
203 // thread-safe and there are essentially no performance gains to
204 // be had, this seems safer (unless \ref m_calc acquires mutexes
205 // in a way that causes a dead-lock).
206 std::lock_guard<std::mutex> lock (m_calcMutex);
207
208 // check if another thread already calculated this value while we
209 // acquired the lock
210 iter = m_cache.find (sys);
211 if (iter != m_cache.end())
212 {
213 result = iter->second.get();
214 return StatusCode::SUCCESS;
215 }
216
217 // we will only ever calculate the systematics for our set of
218 // affecting systematics, any systematics that are not affecting
219 // us will be ignored
220 CP::SystematicSet mysys;
222
223 std::shared_ptr<const CalibData> mycalib;
224 {
225 // check if our affecting systematics are known already
226 auto iter = m_cache.find (mysys);
227 if (iter != m_cache.end())
228 mycalib = iter->second;
229 else
230 {
231 // this will now actually calculate the systematics. note
232 // that if this fails, nothing gets cached, but we should also
233 // be aborting
234 auto value = std::make_shared<CalibData> ();
235 ANA_CHECK (m_calc (mysys, *value));
236
237 // store for the affecting systematic
238 auto emplace_result = m_cache.emplace (mysys, value);
239 mycalib = emplace_result.first->second;
240 }
241 }
242
243 // store for user requested systematics as well, which may or may
244 // not be the same as the affecting systematics, but if it is
245 // already there, this will do nothing.
246 m_cache.emplace (sys, mycalib);
247 result = mycalib.get();
248 return StatusCode::SUCCESS;
249 }
250
251
252
253 template<typename CalibData>
255 add (const CP::SystematicSet& sys, CalibData value)
256 {
257 auto emplace_result = m_cache.emplace (sys, std::make_shared<CalibData> (std::move (value)));
258 if (emplace_result.second == false)
259 {
260 ANA_MSG_ERROR ("failed to add systematic, already present: " << sys.name());
261 return StatusCode::FAILURE;
262 }
263
264 for (const auto& var : sys)
265 m_affectingSystematics.insert (var);
266
267 return StatusCode::SUCCESS;
268 }
269
270
271
272 template<typename CalibData>
274 add (const SystematicVariation& variation, CalibData value)
275 {
276 SystematicSet sys;
277 sys.insert (variation);
278 return add (sys, std::move (value));
279 }
280}
281
282#endif
#define ATH_LIKELY(x)
macros for messaging and checking status codes
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
Define macros for attributes used to control the static checker.
Class to wrap a set of SystematicVariations.
static StatusCode filterForAffectingSystematics(const SystematicSet &systConfig, const SystematicSet &affectingSystematics, SystematicSet &filteredSystematics)
description: filter the systematics for the affected systematics returns: success guarantee: strong f...
bool isAffectedBySystematic(const SystematicVariation &systematic) const
StatusCode get(const CP::SystematicSet &sys, const BTaggingEfficiencyJsonTool::sysData *&result) const
CP::SystematicSet m_affectingSystematics
the list of affecting systematics
StatusCode add(const CP::SystematicSet &sys, BTaggingEfficiencyJsonTool::sysData value)
void initialize(CP::SystematicSet val_affectingSystematics, std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> val_calc) noexcept
initialize with the list of affecting systematics and a function to calculate the calibration data fo...
std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> m_calc
the function to calculate the calibration data for a given systematics
const CP::SystematicSet & affectingSystematics() const noexcept
the list of affecting systematics
tbb::concurrent_unordered_map< CP::SystematicSet, std::shared_ptr< const CalibData >, SystematicSetHash > m_cache ATLAS_THREAD_SAFE
the cache of previously calculated calibration data
SystematicsCache(T2 *val_parent)
std::mutex m_calcMutex
a mutex to protext against concurrent execution of m_calc
base class to forward messages to another class
MsgStream & msg() const
The standard message stream.
AsgMessagingForward(T *owner)
forwarding constructor
STL class.
Select isolated Photons, Electrons and Muons.
STL namespace.
SystematicSet hash function for general use.
#define private