ATLAS Offline Software
Loading...
Searching...
No Matches
SystematicsCache.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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
15#include <functional>
16#include <mutex>
17#include <tbb/concurrent_unordered_map.h>
18
19namespace CP
20{
81
82 template<typename CalibData>
84 {
87
88 public:
89
91
92 template<typename T2>
93 SystematicsCache (T2 *val_parent);
94
97 void initialize (CP::SystematicSet val_affectingSystematics,
98 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> val_calc) noexcept;
99
102
103
109
110
113 StatusCode get (const CP::SystematicSet& sys, const CalibData*& result) const;
114
115
117 StatusCode add (const CP::SystematicSet& sys, CalibData value);
118 StatusCode add (const SystematicVariation& variation, CalibData value);
119
120
123
124 private:
125
128
131 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> m_calc;
132
134 mutable tbb::concurrent_unordered_map<CP::SystematicSet,std::shared_ptr<const CalibData>,SystematicSetHash> m_cache ATLAS_THREAD_SAFE;
135
141 };
142
143
144
147
148 template<typename CalibData> template<typename T2>
150 SystematicsCache (T2 *val_parent)
151 : AsgMessagingForward (val_parent)
152 {}
153
154
155
156 template<typename CalibData> void SystematicsCache<CalibData> ::
157 initialize (CP::SystematicSet val_affectingSystematics,
158 std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> val_calc) noexcept
159 {
160 m_calc = std::move (val_calc);
161 m_affectingSystematics = std::move (val_affectingSystematics);
162 m_cache.clear ();
163 }
164
165
166
167 template<typename CalibData>
173
174
175
176 template<typename CalibData>
179 {
180 // this is not technically correct, but what a lot of people do
181 return m_affectingSystematics.find (sys) != m_affectingSystematics.end();
182 }
183
184
185
186 template<typename CalibData>
188 get (const CP::SystematicSet& sys, const CalibData*& result) const
189 {
190 // fast-path, check if we already calculated this
191 auto iter = m_cache.find (sys);
192 if (iter != m_cache.end()) [[likely]]
193 {
194 result = iter->second.get();
195 return StatusCode::SUCCESS;
196 }
197
198 // create a lock to prevent the concurrent (or duplicate)
199 // execution of the \ref m_calc function. if that function is
200 // thread-safe this lock is not strictly necessary. however,
201 // given that it is hard to enforce that the function is indeed
202 // thread-safe and there are essentially no performance gains to
203 // be had, this seems safer (unless \ref m_calc acquires mutexes
204 // in a way that causes a dead-lock).
205 std::lock_guard<std::mutex> lock (m_calcMutex);
206
207 // check if another thread already calculated this value while we
208 // acquired the lock
209 iter = m_cache.find (sys);
210 if (iter != m_cache.end())
211 {
212 result = iter->second.get();
213 return StatusCode::SUCCESS;
214 }
215
216 // we will only ever calculate the systematics for our set of
217 // affecting systematics, any systematics that are not affecting
218 // us will be ignored
219 CP::SystematicSet mysys;
221
222 std::shared_ptr<const CalibData> mycalib;
223 {
224 // check if our affecting systematics are known already
225 auto iter = m_cache.find (mysys);
226 if (iter != m_cache.end())
227 mycalib = iter->second;
228 else
229 {
230 // this will now actually calculate the systematics. note
231 // that if this fails, nothing gets cached, but we should also
232 // be aborting
233 auto value = std::make_shared<CalibData> ();
234 ANA_CHECK (m_calc (mysys, *value));
235
236 // store for the affecting systematic
237 auto emplace_result = m_cache.emplace (mysys, value);
238 mycalib = emplace_result.first->second;
239 }
240 }
241
242 // store for user requested systematics as well, which may or may
243 // not be the same as the affecting systematics, but if it is
244 // already there, this will do nothing.
245 m_cache.emplace (sys, mycalib);
246 result = mycalib.get();
247 return StatusCode::SUCCESS;
248 }
249
250
251
252 template<typename CalibData>
254 add (const CP::SystematicSet& sys, CalibData value)
255 {
256 auto emplace_result = m_cache.emplace (sys, std::make_shared<CalibData> (std::move (value)));
257 if (emplace_result.second == false)
258 {
259 ANA_MSG_ERROR ("failed to add systematic, already present: " << sys.name());
260 return StatusCode::FAILURE;
261 }
262
263 for (const auto& var : sys)
264 m_affectingSystematics.insert (var);
265
266 return StatusCode::SUCCESS;
267 }
268
269
270
271 template<typename CalibData>
273 add (const SystematicVariation& variation, CalibData value)
274 {
275 SystematicSet sys;
276 sys.insert (variation);
277 return add (sys, std::move (value));
278 }
279}
280
281#endif
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
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
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.
#define likely(x)
SystematicSet hash function for general use.
#define private
Definition testRead.cxx:27