ATLAS Offline Software
Loading...
Searching...
No Matches
UncertaintyGroup.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include "TFile.h"
9
10namespace jet
11{
12
13bool operator < (const UncertaintyGroup& groupA, const UncertaintyGroup& groupB)
14{
15 return groupA.getName() < groupB.getName();
16}
17
18bool operator == (const UncertaintyGroup& groupA, const UncertaintyGroup& groupB)
19{
20 return groupA.getName() == groupB.getName();
21}
22
24// //
25// Constructor/destructor/initialization //
26// //
28
29UncertaintyGroup::UncertaintyGroup(const std::string& name)
30 : asg::AsgMessaging(name)
31 , m_isInit(false)
32 , m_name(name.c_str())
33 , m_desc("")
34 , m_groupNum(0)
35 , m_subgroupNum(0)
36 , m_category(CompCategory::UNKNOWN)
37 , m_corrType(CompCorrelation::UNKNOWN)
38 , m_isReducible(false)
39 , m_components()
40 , m_subgroups()
42{
44}
45
47 : asg::AsgMessaging(group.name.Data())
48 , m_isInit(false)
49 , m_name(group.name)
50 , m_desc(group.desc)
51 , m_groupNum(group.groupNum)
52 , m_subgroupNum(group.subgroupNum)
53 , m_category(group.category)
54 , m_corrType(group.correlation)
55 , m_isReducible(group.reducible)
56 , m_components()
57 , m_subgroups()
59{
60 ATH_MSG_DEBUG(Form("Creating UncertaintyGroup named %s",m_name.Data()));
61 //if (m_category == CompCategory::UNKNOWN)
62 // ATH_MSG_FATAL("UNKNOWN category for UncertaintyGroup named " << m_name.Data());
63 // Acceptible to not exist if it's only one component, check during initialize()
64 //if (m_corrType == CompCorrelation::UNKNOWN)
65 // ATH_MSG_FATAL(Form("UNKNOWN correlation for UncertaintyGroup named %s",m_name.Data()));
66}
67
69 : asg::AsgMessaging(Form("%s_copy",toCopy.m_name.Data()))
70 , m_isInit(toCopy.m_isInit)
71 , m_name(toCopy.m_name)
72 , m_desc(toCopy.m_desc)
73 , m_groupNum(toCopy.m_groupNum)
75 , m_category(toCopy.m_category)
76 , m_corrType(toCopy.m_corrType)
78 , m_components()
79 , m_subgroups()
81{
82 for (size_t iComp = 0; iComp < toCopy.m_components.size(); ++iComp)
83 if (toCopy.m_components.at(iComp))
84 m_components.push_back(toCopy.m_components.at(iComp)->clone());
85}
86
88{
89 ATH_MSG_DEBUG(Form("Deleting UncertaintyGroup named %s",m_name.Data()));
90
91 std::map<CompScaleVar::TypeEnum,std::vector<UncertaintyComponent*>*>::iterator iter;
92 for (iter = m_compScaleMap.begin(); iter != m_compScaleMap.end(); ++iter)
93 JESUNC_SAFE_DELETE(iter->second);
94 m_compScaleMap.clear();
95
96 for (size_t iComp = 0; iComp < m_components.size(); ++iComp)
98 m_components.clear();
99
100 for (size_t iSubGroup = 0; iSubGroup < m_subgroups.size(); ++iSubGroup)
101 JESUNC_SAFE_DELETE(m_subgroups.at(iSubGroup));
102 m_subgroups.clear();
103}
104
106{
107 if (m_isInit)
108 {
109 ATH_MSG_ERROR("Cannot add components to a group after initialization: " << getName().Data());
110 return StatusCode::FAILURE;
111 }
112
113 // Ensure the component is not NULL
114 if (!component)
115 {
116 ATH_MSG_ERROR("Component specified for addition to the group is NULL: " << getName().Data());
117 return StatusCode::FAILURE;
118 }
119
120 // Add it to the vector of components
121 m_components.push_back(component);
122
123 // Now add it to the map with its scale variable
124 std::map<CompScaleVar::TypeEnum,std::vector<UncertaintyComponent*>*>::iterator iter = m_compScaleMap.find(component->getScaleVar());
125 if (iter != m_compScaleMap.end())
126 iter->second->push_back(component);
127 else
128 {
129 std::vector<UncertaintyComponent*>* newScaleVarVec = new std::vector<UncertaintyComponent*>();
130 newScaleVarVec->push_back(component);
131 m_compScaleMap.insert(std::make_pair(component->getScaleVar(),newScaleVarVec));
132 }
133
134 return StatusCode::SUCCESS;
135}
136
138{
139 if (m_isInit)
140 {
141 ATH_MSG_ERROR("Cannot add subgroups to a group after initialization: " << getName().Data());
142 return StatusCode::FAILURE;
143 }
144
145 // Ensure the subgroup is not NULL
146 if (!subgroup)
147 {
148 ATH_MSG_ERROR("Subgroup specified for addition to the group is NULL: " << getName().Data());
149 return StatusCode::FAILURE;
150 }
151
152 // Add it to the vector of subgroups
153 m_subgroups.push_back(subgroup);
154
155 return StatusCode::SUCCESS;
156}
157
158StatusCode UncertaintyGroup::initialize(TFile* histFile)
159{
160 // Prevent double-initialization
161 if (m_isInit)
162 {
163 ATH_MSG_ERROR("Group is already initialized: " << getName().Data());
164 return StatusCode::FAILURE;
165 }
166
167 // Ensure the group has component(s) and/or subgroup(s)
168 if (m_components.empty() && m_subgroups.empty())
169 {
170 ATH_MSG_ERROR("Group is empty: " << getName().Data());
171 return StatusCode::FAILURE;
172 }
173
174 // Initialize the subgroups (has to happen before we check parametrizations below)
175 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
176 if(m_subgroups.at(iSubgroup)->initialize(histFile).isFailure())
177 return StatusCode::FAILURE;
178
179 // If the group has multiple components of the same parametrization, ensure there is a correlation type specified
180 if (m_corrType == CompCorrelation::UNKNOWN && !m_components.empty() && !m_subgroups.empty())
181 {
182 // First check the raw components
183 std::set<CompScaleVar::TypeEnum> vars;
184 for (size_t iComp = 0; iComp < m_components.size(); ++iComp)
185 vars.insert(m_components.at(iComp)->getScaleVar());
186 if (vars.size() != m_components.size())
187 {
188 ATH_MSG_ERROR("Correlation type is set to UNKNOWN for multiple components scaling the same variable: " << getName().Data());
189 return StatusCode::FAILURE;
190 }
191
192 // Now check the subgroup components
193 std::set<CompScaleVar::TypeEnum> groupVars;
194 size_t numSubComps = 0;
195 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
196 {
197 const std::set<CompScaleVar::TypeEnum> subVars = m_subgroups.at(iSubgroup)->getScaleVars();
198 groupVars.insert(subVars.begin(),subVars.end());
199 numSubComps += m_subgroups.at(iSubgroup)->getNumComponents();
200 }
201 if (groupVars.size() != numSubComps)
202 {
203 ATH_MSG_ERROR("Correlation type is set to UNKNOWN for multiple subgroups scaling the same variable: " << getName().Data());
204 return StatusCode::FAILURE;
205 }
206
207 // Now check if any of the raw component scales overlap with subgroup scales
208 for (std::set<CompScaleVar::TypeEnum>::const_iterator iter = vars.begin(); iter != vars.end(); ++iter)
209 {
210 if (groupVars.count(*iter))
211 {
212 ATH_MSG_ERROR("Correlation type is set to UNKNOWN for a component and subgroup scaling the same variable: " << getName().Data());
213 return StatusCode::FAILURE;
214 }
215 }
216 }
217
218
219 // Initialize the components
220 for (size_t iComp = 0; iComp < m_components.size(); ++iComp)
221 if (m_components.at(iComp)->initialize(histFile).isFailure())
222 return StatusCode::FAILURE;
223
224 // Print a summary
225 ATH_MSG_DEBUG("Successfully initialized UncertaintyGroup named " << getName().Data());
226
227 m_isInit = true;
228 return StatusCode::SUCCESS;
229}
230
231
233// //
234// Methods to access underlying constituents //
235// //
237
239{
240 size_t numComps = m_components.size();
241 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
242 numComps += m_subgroups.at(iSubgroup)->getNumComponents();
243
244 return numComps;
245}
246
247std::set<CompScaleVar::TypeEnum> UncertaintyGroup::getScaleVars() const
248{
249 std::set<CompScaleVar::TypeEnum> vars;
250 if (!m_isInit)
251 {
252 ATH_MSG_ERROR("Cannot call method before initialization, group: " << getName().Data());
253 return vars;
254 }
255
256 for (size_t iComp = 0; iComp < m_components.size(); ++iComp)
257 vars.insert(m_components.at(iComp)->getScaleVar());
258
259 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
260 {
261 const std::set<CompScaleVar::TypeEnum> subVars = m_subgroups.at(iSubgroup)->getScaleVars();
262 vars.insert(subVars.begin(),subVars.end());
263 }
264
265 return vars;
266}
267
268
270// //
271// Specialty methods //
272// //
274
276{
277 // The topology is not normally needed
278 // Most variables are topology-independent, and thus are listed as "UNKNOWN"
279 // Mixing topology-agnostic and topology-specific variables is expected
280 // Mixing topology-specific variables of different topologies is not expected
281
282 // Furthermore, the user can specify either a specific scale variable or not
283 // If the user doesn't specify (or specifies UNKNOWN, the default), then it checks all
284
286
287 // First check subgroups
288 for (const UncertaintyGroup* subgroup : m_subgroups)
289 {
290 if (subgroup->getTopology() != JetTopology::UNKNOWN)
291 {
293 result = subgroup->getTopology();
294 else if (result != subgroup->getTopology(scaleVar))
296 }
298 return result; // If it's mixed, it won't change any further
299 }
300
301 // Now check direct components
302 for (const UncertaintyComponent* component : m_components)
303 {
304 // Skip components that don't match our desired scale var (if appropriate)
305 if (scaleVar != CompScaleVar::UNKNOWN && scaleVar != component->getScaleVar())
306 continue;
307
308 if (component->getTopology() != JetTopology::UNKNOWN)
309 {
311 result = component->getTopology();
312 else if (result != component->getTopology())
314 }
316 return result; // If it's mixed, it won't change any further
317 }
318
319 return result; // If we got here, it's not a mixed topology, so return what it is
320}
321
322
324// //
325// Methods to test for special cases //
326// //
328
330{
331 if (!m_isInit)
332 {
333 ATH_MSG_ERROR("Cannot call method before initialization, group: "<<getName().Data());
334 return false;
335 }
336
337 for (size_t iComp = 0; iComp < m_components.size(); ++iComp)
338 {
339 if (!m_components.at(iComp)->isAlwaysZero())
340 return false;
341 }
342
343 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
344 {
345 if (!m_subgroups.at(iSubgroup)->isAlwaysZero())
346 return false;
347 }
348
349 return true;
350}
351
352
354// //
355// Validity and uncertainty retrieval //
356// //
358
360{
361 // Search for the component in question
362 std::map<CompScaleVar::TypeEnum,std::vector<UncertaintyComponent*>*>::const_iterator iter = m_compScaleMap.find(scaleVar);
363 if (iter == m_compScaleMap.end())
364 return true;
365 const std::vector<UncertaintyComponent*>* relevantComponents = iter->second;
366
367 // Valid only if all component(s) are valid
368 if (!m_isInit)
369 {
370 ATH_MSG_ERROR("Group hasn't been initialized: " << getName().Data());
371 return false;
372 }
373 for (size_t iComp = 0; iComp < relevantComponents->size(); ++iComp)
374 if (!relevantComponents->at(iComp)->getValidity(jet,eInfo))
375 return false;
376
377 // Valid only if all subgroup(s) are valid
378 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
379 if (!m_subgroups.at(iSubgroup)->getValidity(jet,eInfo,scaleVar))
380 return false;
381
382 return true;
383}
384
385
387{
388 // Search for the component in question
389 std::map<CompScaleVar::TypeEnum,std::vector<UncertaintyComponent*>*>::const_iterator iter = m_compScaleMap.find(scaleVar);
390 const std::vector<UncertaintyComponent*>* relevantComponents = (iter != m_compScaleMap.end()) ? iter->second : NULL;
391
392 // Also check if any subgroup(s) are affected
393 std::vector<UncertaintyGroup*> relevantGroups;
394 for (size_t iSubgroup = 0; iSubgroup < m_subgroups.size(); ++iSubgroup)
395 if (m_subgroups.at(iSubgroup)->getScaleVars().count(scaleVar))
396 relevantGroups.push_back(m_subgroups.at(iSubgroup));
397
398 // Simple if it neither affects components nor subgroups
399 if ((!relevantComponents || relevantComponents->empty()) && relevantGroups.empty()) return 0;
400
401 // Simple if it's one component and doesn't affect subgroups
402 if ((relevantComponents && relevantComponents->size() == 1) && relevantGroups.empty())
403 return relevantComponents->at(0)->getUncertainty(jet,eInfo);
404
405 // Simple if it's one subgroup and doesn't affect components
406 if (relevantGroups.size() == 1 && (!relevantComponents || relevantComponents->empty()))
407 return relevantGroups.at(0)->getUncertainty(jet,eInfo,scaleVar);
408
409
410 // More complicated case where there are multiple component(s) and/or group(s)
411 // Quad sum or linear sum depending on correlation type specified
412 double unc = 0;
414 {
415 if (relevantComponents)
416 for (size_t iComp = 0; iComp < relevantComponents->size(); ++iComp)
417 unc += pow(relevantComponents->at(iComp)->getUncertainty(jet,eInfo),2);
418 for (size_t iGroup = 0; iGroup < relevantGroups.size(); ++iGroup)
419 unc += pow(relevantGroups.at(iGroup)->getUncertainty(jet,eInfo,scaleVar),2);
420 unc = sqrt(unc);
421 }
423 {
424 if (relevantComponents)
425 for (size_t iComp = 0; iComp < relevantComponents->size(); ++iComp)
426 unc += relevantComponents->at(iComp)->getUncertainty(jet,eInfo);
427 for (size_t iGroup = 0; iGroup < relevantGroups.size(); ++iGroup)
428 unc += relevantGroups.at(iGroup)->getUncertainty(jet,eInfo,scaleVar);
429 }
430 else
431 {
432 ATH_MSG_ERROR(Form("Unexpected correlation type for %s",m_name.Data()));
433 return JESUNC_ERROR_CODE;
434 }
435
436 return unc;
437}
438
439bool UncertaintyGroup::getValidUncertainty(double& unc, const xAOD::Jet& jet, const xAOD::EventInfo& eInfo, const CompScaleVar::TypeEnum scaleVar) const
440{
441 if (getValidity(jet,eInfo,scaleVar))
442 {
443 unc = getUncertainty(jet,eInfo,scaleVar);
444 return true;
445 }
446 return false;
447}
448
449} // end jet namespace
450
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
@ Data
Definition BaseObject.h:11
constexpr int pow(int base, int exp) noexcept
AsgMessaging(const std::string &name)
Constructor with a name.
virtual CompScaleVar::TypeEnum getScaleVar() const
virtual JetTopology::TypeEnum getTopology(const CompScaleVar::TypeEnum scaleVar=CompScaleVar::UNKNOWN) const
virtual double getUncertainty(const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
virtual size_t getNumComponents() const
std::vector< UncertaintyGroup * > m_subgroups
const CompCategory::TypeEnum m_category
const CompCorrelation::TypeEnum m_corrType
std::map< CompScaleVar::TypeEnum, std::vector< UncertaintyComponent * > * > m_compScaleMap
virtual StatusCode addComponent(UncertaintyComponent *component)
virtual bool getValidity(const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
virtual bool getValidUncertainty(double &unc, const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
virtual TString getName() const
UncertaintyGroup(const GroupHelper &group)
virtual bool isAlwaysZero() const
virtual StatusCode initialize(TFile *histFile)
virtual StatusCode addSubgroup(UncertaintyGroup *subgroup)
virtual std::set< CompScaleVar::TypeEnum > getScaleVars() const
std::vector< UncertaintyComponent * > m_components
bool operator==(const UncertaintyComponent &componentA, const UncertaintyComponent &componentB)
bool operator<(const UncertaintyComponent &componentA, const UncertaintyComponent &componentB)
Jet_v1 Jet
Definition of the current "jet version".
EventInfo_v1 EventInfo
Definition of the latest event info version.