ATLAS Offline Software
SoftKillerWeightTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "fastjet/ClusterSequenceArea.hh"
8 #include "fastjet/Selector.hh"
9 #include "fastjet/RectangularGrid.hh"
10 #include "fastjet/contrib/SoftKiller.hh"
11 
12 #include "xAODPFlow/PFO.h"
13 #include "xAODPFlow/FlowElement.h"
15 
16 
17 using namespace std;
18 
19 namespace {
20  const static SG::AuxElement::ConstAccessor<float> acc_clambda("CENTER_LAMBDA");
21 }
22 
24  , m_lambdaCalDivide(317)
25  , m_isCaloSplit(false)
26  , m_gridSpacing(0.6)
27  , m_eCalGrid(0.5)
28  , m_hCalGrid(0.5)
29  , m_rapmin(0.0)
30  , m_rapmax(2.5)
31  , m_rapminApplied(0)
32  , m_rapmaxApplied(10)
33  , m_ignoreChargedPFOs(true)
34 
35 {
36 
37  declareProperty("SKGridSize", m_gridSpacing);
38  declareProperty("SKRapMin", m_rapmin);
39  declareProperty("SKRapMax", m_rapmax);
40  declareProperty("SKRapMinApplied", m_rapminApplied);
41  declareProperty("SKRapMaxApplied", m_rapmaxApplied);
42  declareProperty("isCaloSplit", m_isCaloSplit);
43  declareProperty("ECalGridSize", m_eCalGrid);
44  declareProperty("HCalGridSize", m_hCalGrid);
45 
46  // Option to disregard cPFOs in the weight calculation
47  declareProperty("IgnoreChargedPFO", m_ignoreChargedPFOs);
48 }
49 
50 
53  ATH_MSG_ERROR("SoftKillerWeightTool requires CaloCluster or PFO inputs when isCaloSplit is true."
54  << " It cannot apply split calorimeters on objects of type "
55  << m_inputType);
56  return StatusCode::FAILURE;
57  }
58 
61  ATH_MSG_ERROR("Incompatible configuration: setting both IgnoreChargedPFO and ApplyToChargedPFO to true"
62  << "will set all cPFOs to zero");
63  return StatusCode::FAILURE;
64  }
65  if(!m_applyToNeutralPFO) {
66  ATH_MSG_ERROR("Incompatible configuration: ApplyToNeutralPFO=False -- what kind of pileup do you wish to suppress?");
67  return StatusCode::FAILURE;
68  }
69  }
70  return StatusCode::SUCCESS;
71 }
72 
74  const static SG::AuxElement::Accessor<float> weightAcc("SoftKillerWeight"); // Handle for PU weighting here
75  double minPt(0.), minPtECal(0.), minPtHCal(0.);
76  if(!m_isCaloSplit) {
77  minPt = getSoftKillerMinPt(*cont);
78  ATH_MSG_VERBOSE("For current event, minpt = " << minPt);
79  }
80  else {
81  std::pair<double,double> minPt_split = getSoftKillerMinPtSplit(*cont);
82  minPtECal = minPt_split.first;
83  minPtHCal = minPt_split.second;
84  ATH_MSG_VERBOSE("For current event, minpt = " << minPtECal << " (ECAL), "
85  << minPtHCal << " (HCAL)");
86  }
87 
88  for(xAOD::IParticle* part : *cont) {
89  float w = 1;
90  if(!m_isCaloSplit) w = calculateWeight(*part, minPt);
91  else w = calculateSplitWeight(*part, minPtECal, minPtHCal);
92  // use parent class's type-sensitive setter
93  ATH_CHECK( setEnergyPt(part, part->e()*w, part->pt()*w,&weightAcc) );
94  }
95  return StatusCode::SUCCESS;
96 }
97 
98 
99 // Finds the pT cut for this event based on the SK results
100 // The partSK collection contains all particles that aren't cut, so particles below
101 // its min pT are cut
102 double SoftKillerWeightTool::findMinPt(const vector<fastjet::PseudoJet> &partSK) const {
103  if (partSK.empty()) {return 0.;}
104  double minPt = 999999999999;
105 
106  for(unsigned int i=0; i < partSK.size(); i++){
107  if( partSK[i].pt() < minPt) minPt = partSK[i].pt();
108  }
109 
110  // There is a small rounding error which I account for this way
111  return (minPt - 1e-12);
112 }
113 
114 
115 
116 // Reweights particles (when calo isn't split)
118  vector<fastjet::PseudoJet> partPJ;
119  partPJ.reserve(cont.size());
120 
121  for(xAOD::IParticle* part : cont){
122  // Only use positive E
123  bool accept = part->e() > 1e-9;
124  // For PFlow we would only want to apply the correction to neutral PFOs,
125  // because charged hadron subtraction handles the charged PFOs.
126  // However, we might still want to use the cPFOs for the min pt calculation
128  xAOD::PFO* pfo = static_cast<xAOD::PFO*>(part);
129  accept = !pfo->isCharged();
130  }
132  xAOD::TrackCaloCluster* tcc = static_cast<xAOD::TrackCaloCluster*>(part);
133  accept = (tcc->taste()!= 0);
134  }
136  xAOD::FlowElement* fe = static_cast<xAOD::FlowElement*>(part);
138  if(m_ignoreChargedPFOs) accept = !fe->isCharged();
139  }
140  else
141  accept = !fe->isCharged();
142  }
143  if(accept) {
144  partPJ.emplace_back( part->p4() );
145  }
146  }
147 
148  fastjet::Selector selector = fastjet::SelectorAbsRapRange(m_rapmin, m_rapmax);
149  fastjet::RectangularGrid SKgrid(-m_rapmax, m_rapmax, m_gridSpacing, m_gridSpacing, selector);
150  fastjet::contrib::SoftKiller softkiller(SKgrid);
151  std::vector<fastjet::PseudoJet> partSK = softkiller(selector(partPJ));
152 
153  return findMinPt(partSK);
154 }
155 
157  vector<fastjet::PseudoJet> partPJ_ECal;
158  partPJ_ECal.reserve(cont.size());
159  vector<fastjet::PseudoJet> partPJ_HCal;
160  partPJ_HCal.reserve(cont.size());
161 
162  for(xAOD::IParticle* part : cont){
163  // Only use positive E
164  bool accept = part->e() > 1e-9;
165  // For PFlow we would only want to apply the correction to neutral PFOs,
166  // because charged hadron subtraction handles the charged PFOs.
167  // However, we might still want to use the cPFOs for the min pt calculation
169  xAOD::PFO* pfo = static_cast<xAOD::PFO*>(part);
170  accept = !pfo->isCharged();
171  }
173  xAOD::TrackCaloCluster* tcc = static_cast<xAOD::TrackCaloCluster*>(part);
174  accept = (tcc->taste()!= 0);
175  }
177  xAOD::FlowElement* fe = static_cast<xAOD::FlowElement*>(part);
179  if(m_ignoreChargedPFOs) accept = !fe->isCharged();
180  }
181  else
182  accept = !fe->isCharged();
183  }
184  if(accept) {
185  double center_lambda = acc_clambda.isAvailable(*part) ? acc_clambda(*part) : 0.;
186  if( center_lambda < m_lambdaCalDivide) partPJ_ECal.emplace_back( part->p4() );
187  if( center_lambda >= m_lambdaCalDivide) partPJ_HCal.emplace_back( part->p4() );
188  }
189  }
190 
191  fastjet::Selector selector = fastjet::SelectorAbsRapRange(m_rapmin, m_rapmax);
192  fastjet::RectangularGrid SKgridECal(-m_rapmax, m_rapmax, m_eCalGrid, m_eCalGrid, selector);
193  fastjet::contrib::SoftKiller softkillerECal(SKgridECal);
194  std::vector<fastjet::PseudoJet> partSK_ECal = softkillerECal(selector(partPJ_ECal));
195  double minPtECal = findMinPt(partSK_ECal);
196 
197  fastjet::RectangularGrid SKgridHCal(-m_rapmax, m_rapmax, m_hCalGrid, m_hCalGrid, selector);
198  fastjet::contrib::SoftKiller softkillerHCal(SKgridHCal);
199  std::vector<fastjet::PseudoJet> partSK_HCal = softkillerHCal(selector(partPJ_HCal));
200  double minPtHCal = findMinPt(partSK_HCal);
201  return std::make_pair(minPtECal,minPtHCal);
202 }
203 
205  // If the particle pT is below the SoftKiller pT cut, rescale 4-momentum to 0
206  if( abs(part.eta()) < m_rapminApplied || abs(part.eta()) > m_rapmaxApplied) return 1;
207  if( part.pt() < minPt) return 0;
208  return 1;
209 }
210 
211 
212 float SoftKillerWeightTool::calculateSplitWeight(xAOD::IParticle& part, double minPtECal, double minPtHCal) const{
213  if( abs(part.eta()) < m_rapminApplied || abs(part.eta()) > m_rapmaxApplied) return 1;
214  double center_lambda = acc_clambda.isAvailable(part) ? acc_clambda(part) : 0.;
215 
216  //Make a separate pT cut for the ECal and HCal
217  if( center_lambda < m_lambdaCalDivide && part.pt() < minPtECal) return 0;
218  if( part.pt() < minPtHCal) return 0;
219  return 1;
220 }
221 
222 
223 
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
JetConstituentModifierBase::m_applyToNeutralPFO
bool m_applyToNeutralPFO
Definition: JetConstituentModifierBase.h:63
SoftKillerWeightTool::calculateSplitWeight
float calculateSplitWeight(xAOD::IParticle &part, double minPtECal, double minPtHCal) const
Definition: SoftKillerWeightTool.cxx:212
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
xAOD::TrackCaloCluster_v1
Class describing a TrackCaloCluster.
Definition: TrackCaloCluster_v1.h:25
CutsMETMaker::accept
StatusCode accept(const xAOD::Muon *mu)
Definition: CutsMETMaker.cxx:18
TrackCaloCluster.h
test_pyathena.pt
pt
Definition: test_pyathena.py:11
SoftKillerWeightTool::SoftKillerWeightTool
SoftKillerWeightTool(const std::string &name)
Definition: SoftKillerWeightTool.cxx:23
SoftKillerWeightTool::m_eCalGrid
float m_eCalGrid
Definition: SoftKillerWeightTool.h:90
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SoftKillerWeightTool::findMinPt
double findMinPt(const std::vector< fastjet::PseudoJet > &partSK) const
Definition: SoftKillerWeightTool.cxx:102
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
JetConstituentModifierBase::m_applyToChargedPFO
bool m_applyToChargedPFO
Definition: JetConstituentModifierBase.h:62
xAOD::CaloCluster
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Definition: Event/xAOD/xAODCaloEvent/xAODCaloEvent/CaloCluster.h:19
SoftKillerWeightTool::m_lambdaCalDivide
float m_lambdaCalDivide
Definition: SoftKillerWeightTool.h:85
xAOD::TrackCaloCluster
TrackCaloCluster_v1 TrackCaloCluster
Reference the current persistent version:
Definition: TrackCaloCluster.h:12
xAOD::FlowElement_v1::PFlow
@ PFlow
Definition: FlowElement_v1.h:45
xAOD::FlowElement_v1::isCharged
bool isCharged() const
Definition: FlowElement_v1.cxx:56
PFO.h
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
FlowElement.h
SoftKillerWeightTool::m_rapmin
float m_rapmin
Definition: SoftKillerWeightTool.h:92
lumiFormat.i
int i
Definition: lumiFormat.py:85
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::FlowElement
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition: FlowElement.h:16
xAOD::FlowElement_v1::signalType
signal_t signalType() const
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAODType::ParticleFlow
@ ParticleFlow
The object is a particle-flow object.
Definition: ObjectType.h:41
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
xAOD::PFO_v1::isCharged
bool isCharged() const
is a charged PFO
Definition: PFO_v1.cxx:251
SoftKillerWeightTool::getSoftKillerMinPtSplit
std::pair< double, double > getSoftKillerMinPtSplit(xAOD::IParticleContainer &cont) const
Definition: SoftKillerWeightTool.cxx:156
SoftKillerWeightTool::m_rapminApplied
float m_rapminApplied
Definition: SoftKillerWeightTool.h:94
xAOD::PFO_v1
Class describing a particle flow object.
Definition: PFO_v1.h:35
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
JetConstituentModifierBase
Definition: JetConstituentModifierBase.h:22
SoftKillerWeightTool::m_ignoreChargedPFOs
bool m_ignoreChargedPFOs
Definition: SoftKillerWeightTool.h:96
JetConstituentModifierBase::setEnergyPt
StatusCode setEnergyPt(xAOD::IParticle *obj, float e, float pt, const SG::AuxElement::Accessor< float > *weightAcc=nullptr) const
Definition: JetConstituentModifierBase.cxx:61
SoftKillerWeightTool::calculateWeight
float calculateWeight(xAOD::IParticle &part, double minPt) const
Definition: SoftKillerWeightTool.cxx:204
SoftKillerWeightTool::m_gridSpacing
float m_gridSpacing
Definition: SoftKillerWeightTool.h:89
SoftKillerWeightTool::initialize
StatusCode initialize()
Dummy implementation of the initialisation function.
Definition: SoftKillerWeightTool.cxx:51
xAOD::TrackCaloCluster_v1::taste
virtual int taste() const
The taste of the particle.
SoftKillerWeightTool::m_rapmaxApplied
float m_rapmaxApplied
Definition: SoftKillerWeightTool.h:95
JetConstituentModifierBase::m_inputType
unsigned int m_inputType
Definition: JetConstituentModifierBase.h:60
SoftKillerWeightTool::getSoftKillerMinPt
double getSoftKillerMinPt(xAOD::IParticleContainer &cont) const
Definition: SoftKillerWeightTool.cxx:117
python.selector.AtlRunQuerySelectorLhcOlc.selector
selector
Definition: AtlRunQuerySelectorLhcOlc.py:611
SoftKillerWeightTool::process_impl
StatusCode process_impl(xAOD::IParticleContainer *cont) const
Definition: SoftKillerWeightTool.cxx:73
SoftKillerWeightTool.h
SoftKillerWeightTool::m_hCalGrid
float m_hCalGrid
Definition: SoftKillerWeightTool.h:91
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
SoftKillerWeightTool::m_rapmax
float m_rapmax
Definition: SoftKillerWeightTool.h:93
SoftKillerWeightTool::m_isCaloSplit
bool m_isCaloSplit
Definition: SoftKillerWeightTool.h:88
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25