ATLAS Offline Software
Loading...
Searching...
No Matches
MakeSystematicsVector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8//
9// includes
10//
11
13
17#include <TRandom3.h>
18#include <TRegexp.h>
19#include <cstdint>
20#include <map>
21#include <memory>
22
23//
24// method implementations
25//
26
27namespace CP
28{
29 namespace
30 {
41 uint32_t hash_string (const std::string& str)
42 {
43 uint32_t hash = 0;
44
45 for (char ch : str)
46 {
47 hash += ch;
48 hash += (hash << 10);
49 hash ^= (hash >> 6);
50 }
51
52 hash += (hash << 3);
53 hash ^= (hash >> 11);
54 hash += (hash << 15);
55
56 return hash;
57 }
58 }
59
60
61
62 void MakeSystematicsVector ::
63 testInvariant () const
64 {
65 //RCU_INVARIANT (this != nullptr);
66 RCU_INVARIANT (!m_config.empty());
67 }
68
69
70
71 MakeSystematicsVector ::
72 MakeSystematicsVector ()
73 : m_config (1)
74 {
75 RCU_NEW_INVARIANT (this);
76 }
77
78
79
80 const std::vector<SystematicSet>& MakeSystematicsVector ::
81 result (const std::string& label) const
82 {
83 RCU_READ_INVARIANT (this);
84 RCU_REQUIRE2 (!m_result.empty(), "calculate() has been called");
85 auto iter = m_result.find (label);
86 if (iter == m_result.end())
87 RCU_THROW_MSG ("unknown systematics group: " + label);
88 return iter->second;
89 }
90
91
92
93 void MakeSystematicsVector ::
94 calc (const SystematicSet& sysList)
95 {
97
98 auto baseSys = calcBaseSys (sysList);
99
100 std::map<std::string,std::vector<SystematicSet>> myresult;
101 myresult[m_useForNominal].push_back (SystematicSet ());
102 for (std::size_t group = 0; group != m_config.size(); ++ group)
103 {
104 const auto& config = m_config[group];
105
106 // note: this is not just a short-cut, but also makes sure that
107 // we have an entry for each label, even if there are no
108 // systematics for the label
109 auto& subresult = myresult[config.label];
110
111 // this skips groups that don't match any requested systematics,
112 // which is mainly important for toy systematics as you wouldn't
113 // want to generate a bunch of empty systematics
114 if (baseSys[group].empty())
115 continue;
116
117 if (config.toys == 0)
118 {
119 for (auto sys : baseSys[group])
120 {
121 RCU_ASSERT (!sys.second.empty());
122 RCU_ASSERT (!sys.second.front().isToyEnsemble());
123 if (sys.second.front().isContinuousEnsemble())
124 {
125 // for continuous systematics
126 subresult.push_back(CP::SystematicSet());
127 subresult.back().insert (CP::SystematicVariation (sys.first, config.sigma));
128 subresult.push_back(CP::SystematicSet());
129 subresult.back().insert (CP::SystematicVariation (sys.first, -config.sigma));
130 } else if (sys.second.front().isEnsemble())
131 {
132 // we must have added a new kind of ensemble after I wrote
133 // this code
134 RCU_THROW_MSG ("unsupported ensemble systematic: " + sys.first);
135 } else
136 {
137 // otherwise just add all of them flat
138 for (const auto & mysys : sys.second)
139 {
140 subresult.push_back(CP::SystematicSet());
141 subresult.back().insert(mysys);
142 }
143 }
144 }
145 } else
146 {
147 std::vector<CP::SystematicSet> toys (config.toys);
148
149 for (auto sys : baseSys[group])
150 {
151 RCU_ASSERT (!sys.second.empty());
152 RCU_ASSERT (sys.second.front().isEnsemble());
153
154 if (sys.second.front().isContinuousEnsemble())
155 {
156 std::unique_ptr<TRandom3> random (new TRandom3);
157 random->SetSeed (hash_string (sys.first));
158
159 for (auto& toy : toys)
160 toy.insert (CP::SystematicVariation (sys.first, random->Gaus (0, config.sigma)));
161 } else if (sys.second.front().isToyEnsemble())
162 {
163 for (unsigned toy = 0; toy != config.toys; ++ toy)
164 toys[toy].insert (CP::SystematicVariation::makeToyVariation (sys.first, toy + 1, config.sigma));
165 } else
166 {
167 // we must have added a new kind of ensemble after I
168 // wrote this code
169 RCU_THROW_MSG ("unsupported ensemble systematic for toys: " + sys.first);
170 }
171 }
172 for (auto& toy : toys)
173 subresult.push_back (std::move (toy));
174 }
175 }
176
177 m_result = std::move(myresult);
178 }
179
180
181
182 void MakeSystematicsVector ::
183 addGroup (const std::string& val_label)
184 {
187 config.label = val_label;
188 m_config.push_back (std::move(config));
189 }
190
191
192
193 void MakeSystematicsVector ::
194 setPattern (const std::string& val_pattern)
195 {
197 m_config.back().pattern = val_pattern;
198 }
199
200
201
202 void MakeSystematicsVector ::
203 setSigma (float val_sigma)
204 {
206 RCU_REQUIRE (val_sigma > 0);
207 m_config.back().sigma = val_sigma;
208 }
209
210
211
212 void MakeSystematicsVector ::
213 setToys (unsigned val_toys)
214 {
216 RCU_REQUIRE (val_toys > 0);
217 m_config.back().toys = val_toys;
218 }
219
220
221
222 void MakeSystematicsVector ::
223 useForNominal ()
224 {
226 m_useForNominal = m_config.back().label;
227 }
228
229
230
231 std::vector<std::map<std::string,std::vector<SystematicVariation>>>
232 MakeSystematicsVector ::
233 calcBaseSys (const SystematicSet& sysList)
234 {
235 std::map<std::string,std::vector<SystematicVariation> > basesys;
236 for (const auto & sys : sysList)
237 {
238 basesys[sys.basename()].push_back (sys);
239 }
240 std::vector<std::map<std::string,std::vector<SystematicVariation> >>
241 basesysList (m_config.size());
242 for (auto sys : basesys)
243 {
244 // extract the ensemble if we have one
245 SystematicVariation ensemble;
246 for (const auto & mysys : sys.second)
247 {
248 if (mysys.isEnsemble())
249 {
250 if (!ensemble.empty())
251 RCU_THROW_MSG ("inconsistent ensembles requested: " + ensemble.name() + " " + mysys.name());
252 ensemble = mysys;
253 }
254 }
255
256 // setting this beyond the valid groups in case none matches
257 std::size_t group = m_config.size();
258 for (std::size_t iter = 0; iter != m_config.size(); ++ iter)
259 {
260 if (m_config[iter].pattern.empty())
261 {
262 // only use empty patterns if no previous pattern already took this
263 if (group == m_config.size())
264 {
265 if (m_config[iter].toys > 0)
266 {
267 if (ensemble.isToyEnsemble())
268 group = iter;
269 } else
270 {
271 if (!ensemble.isToyEnsemble())
272 group = iter;
273 }
274 }
275 } else if (RCU::match_expr (std::regex (m_config[iter].pattern.c_str()), sys.first))
276 {
277 if (m_config[iter].toys > 0 && ensemble.empty())
278 RCU_THROW_MSG ("toys only supported for ensemble systematics");
279 group = iter;
280 }
281 }
282 if (group == m_config.size())
283 RCU_THROW_MSG ("no systematics group for systematic: " + sys.first);
284
285 if (!ensemble.empty())
286 {
287 basesysList[group][sys.first].push_back (std::move(ensemble));
288 } else
289 {
290 basesysList[group][sys.first] = std::move (sys.second);
291 }
292 }
293 return basesysList;
294 }
295}
#define RCU_REQUIRE2(x, y)
Definition Assert.h:210
#define RCU_INVARIANT(x)
Definition Assert.h:201
#define RCU_ASSERT(x)
Definition Assert.h:222
#define RCU_CHANGE_INVARIANT(x)
Definition Assert.h:231
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:233
#define RCU_REQUIRE(x)
Definition Assert.h:208
#define RCU_READ_INVARIANT(x)
Definition Assert.h:229
#define RCU_THROW_MSG(message)
Definition PrintMsg.h:58
static const Attributes_t empty
std::string m_useForNominal
the group for which useForNominal was set
std::vector< std::map< std::string, std::vector< SystematicVariation > > > calcBaseSys(const SystematicSet &sysList)
make the list of base systematics for calc
std::vector< GroupConfig > m_config
the configuration on a per-group basis
std::map< std::string, std::vector< SystematicSet > > m_result
the value of result
Class to wrap a set of SystematicVariations.
static SystematicVariation makeToyVariation(const std::string &basename, unsigned toyIndex, float toyScale)
constructor for toy systematics
bool isToyEnsemble() const
whether this represents a toy ensemble
bool empty() const
returns: whether this is an empty systematic, i.e.
const std::string & name() const
description: the full systematics name, for use in strings, etc.
std::string label(const std::string &format, int i)
Definition label.h:19
Select isolated Photons, Electrons and Muons.
bool match_expr(const std::regex &expr, const std::string &str)
returns: whether we can match the entire string with the regular expression guarantee: strong failure...
std::string str(const TrigT2MbtsBits_v1 &trigT2MbtsBits)
setEventNumber uint32_t
the configuration for the given group