ATLAS Offline Software
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 
10 namespace jet
11 {
12 
13 bool operator < (const UncertaintyGroup& groupA, const UncertaintyGroup& groupB)
14 {
15  return groupA.getName() < groupB.getName();
16 }
17 
18 bool operator == (const UncertaintyGroup& groupA, const UncertaintyGroup& groupB)
19 {
20  return groupA.getName() == groupB.getName();
21 }
22 
24 // //
25 // Constructor/destructor/initialization //
26 // //
28 
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()
41  , m_compScaleMap()
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()
58  , m_compScaleMap()
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)
74  , m_subgroupNum(toCopy.m_subgroupNum)
75  , m_category(toCopy.m_category)
76  , m_corrType(toCopy.m_corrType)
77  , m_isReducible(toCopy.m_isReducible)
78  , m_components()
79  , m_subgroups()
80  , m_compScaleMap()
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 
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 
247 std::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  }
297  if (result == JetTopology::MIXED)
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  }
315  if (result == JetTopology::MIXED)
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 
359 bool UncertaintyGroup::getValidity(const xAOD::Jet& jet, const xAOD::EventInfo& eInfo, const CompScaleVar::TypeEnum scaleVar) const
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 
386 double UncertaintyGroup::getUncertainty(const xAOD::Jet& jet, const xAOD::EventInfo& eInfo, const CompScaleVar::TypeEnum scaleVar) const
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 
439 bool 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 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
jet::GroupHelper
Definition: ConfigHelper.h:84
jet::JetTopology::UNKNOWN
@ UNKNOWN
Definition: UncertaintyEnum.h:209
UncertaintyGroup.h
get_generator_info.result
result
Definition: get_generator_info.py:21
jet::UncertaintyGroup::addComponent
virtual StatusCode addComponent(UncertaintyComponent *component)
Definition: UncertaintyGroup.cxx:105
Data
@ Data
Definition: BaseObject.h:11
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
asg
Definition: DataHandleTestTool.h:28
jet::operator==
bool operator==(const UncertaintyComponent &componentA, const UncertaintyComponent &componentB)
Definition: UncertaintyComponent.cxx:18
jet::UncertaintyGroup::UncertaintyGroup
UncertaintyGroup(const GroupHelper &group)
Definition: UncertaintyGroup.cxx:46
jet::UncertaintyGroup::getNumComponents
virtual size_t getNumComponents() const
Definition: UncertaintyGroup.cxx:238
jet::CompCorrelation::UNKNOWN
@ UNKNOWN
Definition: UncertaintyEnum.h:33
jet::UncertaintyGroup::m_name
const TString m_name
Definition: UncertaintyGroup.h:72
jet::UncertaintyGroup::~UncertaintyGroup
virtual ~UncertaintyGroup()
Definition: UncertaintyGroup.cxx:87
jet::UncertaintyGroup::getName
virtual TString getName() const
Definition: UncertaintyGroup.h:40
Helpers.h
jet::UncertaintyComponent
Definition: UncertaintyComponent.h:25
jet::CompCorrelation::Correlated
@ Correlated
Definition: UncertaintyEnum.h:35
JESUNC_ERROR_CODE
#define JESUNC_ERROR_CODE
Definition: Reconstruction/Jet/JetUncertainties/JetUncertainties/Helpers.h:23
jet::UncertaintyGroup::getUncertainty
virtual double getUncertainty(const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
Definition: UncertaintyGroup.cxx:386
jet::UncertaintyGroup::getScaleVars
virtual std::set< CompScaleVar::TypeEnum > getScaleVars() const
Definition: UncertaintyGroup.cxx:247
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
CaloCondBlobAlgs_fillNoiseFromASCII.desc
desc
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:54
JESUNC_SAFE_DELETE
#define JESUNC_SAFE_DELETE(T)
Definition: Reconstruction/Jet/JetUncertainties/JetUncertainties/Helpers.h:25
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
jet::operator<
bool operator<(const UncertaintyComponent &componentA, const UncertaintyComponent &componentB)
Definition: UncertaintyComponent.cxx:13
jet::UncertaintyGroup::m_corrType
const CompCorrelation::TypeEnum m_corrType
Definition: UncertaintyGroup.h:77
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
ReweightUtils.category
category
Definition: ReweightUtils.py:15
jet::UncertaintyGroup::addSubgroup
virtual StatusCode addSubgroup(UncertaintyGroup *subgroup)
Definition: UncertaintyGroup.cxx:137
jet::CompScaleVar::UNKNOWN
@ UNKNOWN
Definition: UncertaintyEnum.h:93
jet::JetTopology::MIXED
@ MIXED
Definition: UncertaintyEnum.h:214
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
jet::UncertaintyGroup
Definition: UncertaintyGroup.h:28
jet::UncertaintyGroup::getValidUncertainty
virtual bool getValidUncertainty(double &unc, const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
Definition: UncertaintyGroup.cxx:439
jet::CompCorrelation::Uncorrelated
@ Uncorrelated
Definition: UncertaintyEnum.h:34
jet::UncertaintyGroup::isAlwaysZero
virtual bool isAlwaysZero() const
Definition: UncertaintyGroup.cxx:329
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
JESUNC_NO_DEFAULT_CONSTRUCTOR
#define JESUNC_NO_DEFAULT_CONSTRUCTOR
Definition: Reconstruction/Jet/JetUncertainties/JetUncertainties/Helpers.h:24
jet::CompScaleVar::TypeEnum
TypeEnum
Definition: UncertaintyEnum.h:91
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
jet::UncertaintyGroup::m_subgroups
std::vector< UncertaintyGroup * > m_subgroups
Definition: UncertaintyGroup.h:80
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
jet::UncertaintyGroup::getValidity
virtual bool getValidity(const xAOD::Jet &jet, const xAOD::EventInfo &eInfo, const CompScaleVar::TypeEnum scaleVar) const
Definition: UncertaintyGroup.cxx:359
jet::UncertaintyGroup::m_components
std::vector< UncertaintyComponent * > m_components
Definition: UncertaintyGroup.h:79
jet::JetTopology::TypeEnum
TypeEnum
Definition: UncertaintyEnum.h:208
jet::UncertaintyGroup::getTopology
virtual JetTopology::TypeEnum getTopology(const CompScaleVar::TypeEnum scaleVar=CompScaleVar::UNKNOWN) const
Definition: UncertaintyGroup.cxx:275
jet::UncertaintyGroup::initialize
virtual StatusCode initialize(TFile *histFile)
Definition: UncertaintyGroup.cxx:158
jet::UncertaintyComponent::getScaleVar
virtual CompScaleVar::TypeEnum getScaleVar() const
Definition: UncertaintyComponent.h:37
jet::UncertaintyGroup::m_compScaleMap
std::map< CompScaleVar::TypeEnum, std::vector< UncertaintyComponent * > * > m_compScaleMap
Definition: UncertaintyGroup.h:81
jet::UncertaintyGroup::m_isInit
bool m_isInit
Definition: UncertaintyGroup.h:71