ATLAS Offline Software
WeightPFOTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 #include "xAODPFlow/FEHelpers.h"
7 
8 namespace CP {
9 
10  WeightPFOTool::WeightPFOTool(const std::string& name) : asg::AsgTool( name )
11  {
12  declareProperty("DoEoverPWeight", m_doEoverPweight=true);
13  declareProperty("NeutralPFOScale",m_theNeutralPFOScaleString="EM");
14  }
15 
16  // Further details of the motivation for this procedure and explanations
17  // of how it works can be found in section 4 of:
18  // Eur. Phys. J. C 81 (2021) 689: https://arxiv.org/abs/2007.02645
19  //
20  //The intended result is briefly described below.
21  //CP::EM Case
22  // Subtraction applied (inDenseEnvironment==false)
23  // pt < 30 GeV: Ptrk [weight = 1]
24  // 30 <= pt < 60 GeV: Ptrk ( E/P + (1-E/P)(1 - (pt - 30)/30 ) ) [weight = E/P + (1-E/P)(1 - (pt - 30)/30 )]
25  // pt >= 60 GeV: Ptrk * E/P [weight = E/P]
26  //
27  // Subtraction not applied (inDenseEnvironment==true)
28  // pt < 30 GeV: Ptrk (1 - E/P) + Ecal [weight = (1-E/P]
29  // 30 <= pt < 60 GeV: Ptrk ( (1-E/P)(1 - (pt - 30)/30 ) ) + Ecal [weight = (1-E/P)(1 - (pt - 30)/30 )]
30  // pt >= 60 GeV: Ecal [weight = 0]
31  //
32  //CP::LC Case - this follows when you assuem E/p = 1 for the LC scale in the above formulae
33  //Subtraction applied (inDenseEnvironment==false)
34  // pt < 30 GeV: Ptrk weight = 1
35  // 30 <= pt < 60 GeV: weight = 0
36  // pt >= 60 GeV: weight = 1;
37  //
38  // Subtraction not applied (inDenseEnvironment==true)
39  // All Pt ranges: weight = 0
40 
41  StatusCode WeightPFOTool::fillWeight( const xAOD::PFO& cpfo, float& weight ) const {
42 
43  //we need to convert the string scale back to the enum
44  PFO_JetMETConfig_inputScale theNeutralPFOScale = CP::EM;
46  bool answer = inputScaleMapper.getValue(m_theNeutralPFOScaleString,theNeutralPFOScale);
47  if (false == answer) ATH_MSG_FATAL("Invalid neutral PFO Scale has been specified in PFlowUtils::PFOWeightTool");
48 
49  // Compute the weights internally
50  weight = 0.;
51  if(cpfo.pt()>100e3) {
52  ATH_MSG_WARNING("PFO with invalid pt " << cpfo.pt() << ", quitting.");
53  return StatusCode::FAILURE;
54  }
55 
56  int isInDenseEnvironment = false;
57  float expectedEnergy = 0.0;
58  bool gotVariable = cpfo.attribute(xAOD::PFODetails::PFOAttributes::eflowRec_isInDenseEnvironment,isInDenseEnvironment);
60  if (!gotVariable) {
61  ATH_MSG_WARNING("This charged PFO did not have eflowRec_isInDenseEnvironment or eflowRec_tracksExpectedEnergyDeposit set");
62  return StatusCode::FAILURE;
63  } else {
64  //EM case first
65  if (CP::EM == theNeutralPFOScale){
66  // Start by computing the correction as though we subtracted the calo energy
67  // This interpolates between the full track P and the expected calo E
68  float EoverP = expectedEnergy/cpfo.e(); // divide once only
69  if(m_doEoverPweight) {
70  if(cpfo.pt()<30e3) { // take full track
71  weight = 1.;
72  } else if(cpfo.pt()<60e3) { // linearly interpolate between 1 and E/P
73  float interpolf = (1.0 - (cpfo.pt()-30000)/30000);
74  weight = EoverP + interpolf * (1-EoverP);
75  } else { // take the expected energy
76  weight = EoverP;
77  }
78  }
79 
80  ATH_MSG_VERBOSE("cpfo in dense environment? " << isInDenseEnvironment);
81  ATH_MSG_VERBOSE("cpfo pt: " << cpfo.pt() << ", E/P: " << EoverP << ", weight: " << weight);
82 
83  if(isInDenseEnvironment) {
84  // In this case we further remove the expected deposited energy from the track
85  weight -= EoverP;
86  }
87  }//EM Scale
88  else if (CP::LC == theNeutralPFOScale){
89  if(!isInDenseEnvironment){
90  if(cpfo.pt()<30e3 || cpfo.pt() >= 60e03) weight = 1;
91  }
92  }
93  }
94 
95  ATH_MSG_VERBOSE("Weight before zero check: " << weight);
96  // If the weight went to 0, set it to the ghost scale, so that the cPFOs
97  // are always added to the track.
98  if (weight<1e-9) {weight = 1e-20;}
99  ATH_MSG_VERBOSE("Final weight: " << weight);
100  return StatusCode::SUCCESS;
101  }
102 
104 
105  if(!(cpfo.signalType() & xAOD::FlowElement::PFlow)){
106  ATH_MSG_WARNING("FlowElement was not a PFO. Signal type was: " << cpfo.signalType());
107  return StatusCode::FAILURE;
108  }
109 
110  //we need to convert the string scale back to the enum
111  PFO_JetMETConfig_inputScale theNeutralPFOScale = CP::EM;
113  bool answer = inputScaleMapper.getValue(m_theNeutralPFOScaleString,theNeutralPFOScale);
114  if (false == answer) ATH_MSG_FATAL("Invalid neutral PFO Scale has been specified in PFlowUtils::PFOWeightTool");
115 
116  // Compute the weights internally
117  weight = 0.;
118  if(cpfo.pt()>100e3) {
119  ATH_MSG_WARNING("PFO with invalid pt " << cpfo.pt() << ", quitting.");
120  return StatusCode::FAILURE;
121  }
122 
123  const static SG::AuxElement::ConstAccessor<int> accDenseEnv("IsInDenseEnvironment");
124  const static SG::AuxElement::ConstAccessor<float> accExpE("TracksExpectedEnergyDeposit");
125 
126  int isInDenseEnvironment = accDenseEnv(cpfo);
127  float expectedEnergy = accExpE(cpfo);
128 
129  //EM case first
130  if (CP::EM == theNeutralPFOScale){
131  // Start by computing the correction as though we subtracted the calo energy
132  // This interpolates between the full track P and the expected calo E
133  float EoverP = expectedEnergy/cpfo.e(); // divide once only
134  if(m_doEoverPweight) {
135  if(cpfo.pt()<30e3) { // take full track
136  weight = 1.;
137  } else if(cpfo.pt()<60e3) { // linearly interpolate between 1 and E/P
138  float interpolf = (1.0 - (cpfo.pt()-30000)/30000);
139  weight = EoverP + interpolf * (1-EoverP);
140  } else { // take the expected energy
141  weight = EoverP;
142  }
143  }
144 
145  ATH_MSG_VERBOSE("cpfo in dense environment? " << isInDenseEnvironment);
146  ATH_MSG_VERBOSE("cpfo pt: " << cpfo.pt() << ", E/P: " << EoverP << ", weight: " << weight);
147 
148  if(isInDenseEnvironment) {
149  // In this case we further remove the expected deposited energy from the track
150  weight -= EoverP;
151  }
152  }//EM Scale
153  else if (CP::LC == theNeutralPFOScale){
154  if(!isInDenseEnvironment){
155  if(cpfo.pt()<30e3 || cpfo.pt() >= 60e03) weight = 1;
156  }
157  }
158 
159  ATH_MSG_VERBOSE("Weight before zero check: " << weight);
160  // If the weight went to 0, set it to the ghost scale, so that the cPFOs
161  // are always added to the track.
162  if (weight<1e-9) {weight = 1e-20;}
163  ATH_MSG_VERBOSE("Final weight: " << weight);
164  return StatusCode::SUCCESS;
165  }
166 
167 }
CP::PFO_JetMETConfig_inputScale
PFO_JetMETConfig_inputScale
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/PFODefs.h:10
CP::inputScaleMapper
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/PFODefs.h:13
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
xAOD::PFO_v1::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition: PFO_v1.cxx:52
CP::inputScaleMapper::getValue
bool getValue(const std::string &nameToMapFrom, PFO_JetMETConfig_inputScale &inputScaleToMapTo)
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/PFODefs.h:14
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
xAOD::PFO_v1::attribute
bool attribute(PFODetails::PFOAttributes AttributeType, T &anAttribute) const
get a PFO Variable via enum
asg
Definition: DataHandleTestTool.h:28
xAOD::PFODetails::eflowRec_isInDenseEnvironment
@ eflowRec_isInDenseEnvironment
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:60
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
xAOD::FlowElement_v1::pt
virtual double pt() const override
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:200
xAOD::FlowElement_v1::PFlow
@ PFlow
Definition: FlowElement_v1.h:45
xAOD::PFO_v1::e
virtual double e() const
The total energy of the particle.
Definition: PFO_v1.cxx:81
CP::WeightPFOTool::WeightPFOTool
WeightPFOTool(const std::string &name)
Athena constructor.
Definition: WeightPFOTool.cxx:10
CheckAppliedSFs.e3
e3
Definition: CheckAppliedSFs.py:264
CP::WeightPFOTool::m_theNeutralPFOScaleString
std::string m_theNeutralPFOScaleString
Definition: WeightPFOTool.h:34
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
PyAlgorithmExample.EoverP
int EoverP
Definition: PyAlgorithmExample.py:122
xAOD::FlowElement_v1::signalType
signal_t signalType() const
WeightPFOTool.h
xAOD::PFO_v1
Class describing a particle flow object.
Definition: PFO_v1.h:35
FEHelpers.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
xAOD::FlowElement_v1::e
virtual double e() const override
The total energy of the particle.
Definition: FlowElement_v1.cxx:25
CP::WeightPFOTool::fillWeight
StatusCode fillWeight(const xAOD::PFO &cpfo, float &weight) const
Declare the interface that the class provides.
Definition: WeightPFOTool.cxx:41
xAOD::PFODetails::eflowRec_tracksExpectedEnergyDeposit
@ eflowRec_tracksExpectedEnergyDeposit
Definition: Event/xAOD/xAODPFlow/xAODPFlow/PFODefs.h:59
CP::WeightPFOTool::m_doEoverPweight
bool m_doEoverPweight
Definition: WeightPFOTool.h:33
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
CP::LC
@ LC
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/PFODefs.h:10
CP::EM
@ EM
Definition: Reconstruction/PFlow/PFlowUtils/PFlowUtils/PFODefs.h:10
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25