ATLAS Offline Software
MakeSystematicsVector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 
8 //
9 // includes
10 //
11 
13 
14 #include <RootCoreUtils/Assert.h>
16 #include <RootCoreUtils/ThrowMsg.h>
17 #include <TRandom3.h>
18 #include <TRegexp.h>
19 #include <cstdint>
20 #include <map>
21 #include <memory>
22 
23 //
24 // method implementations
25 //
26 
27 namespace 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 
63  testInvariant () const
64  {
65  //RCU_INVARIANT (this != nullptr);
66  RCU_INVARIANT (!m_config.empty());
67  }
68 
69 
70 
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 
94  calc (const SystematicSet& sysList)
95  {
96  RCU_CHANGE_INVARIANT (this);
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 (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 = myresult;
178  }
179 
180 
181 
183  addGroup (const std::string& val_label)
184  {
185  RCU_CHANGE_INVARIANT (this);
187  config.label = val_label;
188  m_config.push_back (config);
189  }
190 
191 
192 
194  setPattern (const std::string& val_pattern)
195  {
196  RCU_CHANGE_INVARIANT (this);
197  m_config.back().pattern = val_pattern;
198  }
199 
200 
201 
203  setSigma (float val_sigma)
204  {
205  RCU_CHANGE_INVARIANT (this);
206  RCU_REQUIRE (val_sigma > 0);
207  m_config.back().sigma = val_sigma;
208  }
209 
210 
211 
213  setToys (unsigned val_toys)
214  {
215  RCU_CHANGE_INVARIANT (this);
216  RCU_REQUIRE (val_toys > 0);
217  m_config.back().toys = val_toys;
218  }
219 
220 
221 
224  {
225  RCU_CHANGE_INVARIANT (this);
226  m_useForNominal = m_config.back().label;
227  }
228 
229 
230 
231  std::vector<std::map<std::string,std::vector<SystematicVariation>>>
233  calcBaseSys (const SystematicSet& sysList)
234  {
235  std::map<std::string,std::vector<SystematicVariation> > basesys;
236  for (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 (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 (boost::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 (ensemble);
288  } else
289  {
290  basesysList[group][sys.first] = std::move (sys.second);
291  }
292  }
293  return basesysList;
294  }
295 }
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
sendEI_SPB.ch
ch
Definition: sendEI_SPB.py:35
CP::SystematicVariation::makeToyVariation
static SystematicVariation makeToyVariation(const std::string &basename, unsigned toyIndex, float toyScale)
constructor for toy systematics
Definition: SystematicVariation.cxx:238
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
PlotCalibFromCool.label
label
Definition: PlotCalibFromCool.py:78
RCU_REQUIRE
#define RCU_REQUIRE(x)
Definition: Assert.h:208
CP::SystematicVariation::name
const std::string & name() const
description: the full systematics name, for use in strings, etc.
Definition: SystematicVariation.cxx:303
CP::MakeSystematicsVector::GroupConfig
the configuration for the given group
Definition: MakeSystematicsVector.h:208
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
Assert.h
CP::SystematicVariation
Definition: SystematicVariation.h:47
CP::MakeSystematicsVector::m_result
std::map< std::string, std::vector< SystematicSet > > m_result
the value of result
Definition: MakeSystematicsVector.h:202
CP::MakeSystematicsVector::setPattern
void setPattern(const std::string &val_pattern)
set the pattern for the current group
Definition: MakeSystematicsVector.cxx:194
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
StringUtil.h
CP::MakeSystematicsVector::m_useForNominal
std::string m_useForNominal
the group for which useForNominal was set
Definition: MakeSystematicsVector.h:234
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
CP::MakeSystematicsVector::result
const std::vector< SystematicSet > & result(const std::string &label) const
the list of nuisance parameter points generated with the given label
Definition: MakeSystematicsVector.cxx:81
CP::MakeSystematicsVector::addGroup
void addGroup(const std::string &val_label)
finish configuration for this group and add a new one
Definition: MakeSystematicsVector.cxx:183
CP::MakeSystematicsVector::useForNominal
void useForNominal()
set this group as the default, i.e.
Definition: MakeSystematicsVector.cxx:223
RCU_REQUIRE2
#define RCU_REQUIRE2(x, y)
Definition: Assert.h:210
RCU::match_expr
bool match_expr(const boost::regex &expr, const std::string &str)
returns: whether we can match the entire string with the regular expression guarantee: strong failure...
Definition: StringUtil.cxx:40
CP::MakeSystematicsVector::setSigma
void setSigma(float val_sigma)
set the number of sigmas to vary this group by
Definition: MakeSystematicsVector.cxx:203
RCU_INVARIANT
#define RCU_INVARIANT(x)
Definition: Assert.h:201
CP::MakeSystematicsVector::MakeSystematicsVector
MakeSystematicsVector()
standard default constructor
Definition: MakeSystematicsVector.cxx:72
MakeSystematicsVector.h
CP::MakeSystematicsVector::m_config
std::vector< GroupConfig > m_config
the configuration on a per-group basis
Definition: MakeSystematicsVector.h:229
ThrowMsg.h
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
CP::SystematicVariation::empty
bool empty() const
returns: whether this is an empty systematic, i.e.
Definition: SystematicVariation.cxx:294
CP::MakeSystematicsVector::setToys
void setToys(unsigned val_toys)
set the number of toys to run for this group
Definition: MakeSystematicsVector.cxx:213
config
std::vector< std::string > config
Definition: fbtTestBasics.cxx:72
CP::MakeSystematicsVector::calc
void calc(const SystematicSet &sysList)
fill in result
Definition: MakeSystematicsVector.cxx:94
RCU_CHANGE_INVARIANT
#define RCU_CHANGE_INVARIANT(x)
Definition: Assert.h:231
str
Definition: BTagTrackIpAccessor.cxx:11
RCU_THROW_MSG
#define RCU_THROW_MSG(message)
Definition: PrintMsg.h:58
RCU_ASSERT
#define RCU_ASSERT(x)
Definition: Assert.h:222
RCU_READ_INVARIANT
#define RCU_READ_INVARIANT(x)
Definition: Assert.h:229
CP::MakeSystematicsVector::testInvariant
void testInvariant() const
test the invariant of this object
Definition: MakeSystematicsVector.cxx:63
CP::SystematicVariation::isToyEnsemble
bool isToyEnsemble() const
whether this represents a toy ensemble
Definition: SystematicVariation.cxx:396
CP::MakeSystematicsVector::calcBaseSys
std::vector< std::map< std::string, std::vector< SystematicVariation > > > calcBaseSys(const SystematicSet &sysList)
make the list of base systematics for calc
Definition: MakeSystematicsVector.cxx:233
RCU_NEW_INVARIANT
#define RCU_NEW_INVARIANT(x)
Definition: Assert.h:233