ATLAS Offline Software
Loading...
Searching...
No Matches
Pileup1DResidualCalibStep.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
11
13
14
16
17#include <memory>
18#include <utility>
19
20
22 : asg::AsgTool( name ) { }
23
24
25
26
28
30 ATH_MSG_FATAL("If you're trying to apply only the Residual pile up correction, it needs to be specify in the Calibration Sequence. ApplyOnlyResidual should be true in the configuration file and the PileupStartScale should be specified.");
31 return StatusCode::FAILURE;
32 }
33
34 ATH_MSG_DEBUG("Reading from " << m_jetInScale << " and writing to " << m_jetOutScale);
35
36 ATH_CHECK( m_muKey.initialize() );
37 ATH_CHECK( m_pvKey.initialize() );
38 ATH_CHECK( m_rhoKey.initialize() );
40
41
42
43 if(m_doSequentialResidual) ATH_MSG_DEBUG("The pileup residual calibrations will be applied sequentially.");
44 else ATH_MSG_DEBUG("The pileup residual calibrations will be applied simultaneously (default).");
45 if(m_doMuOnly) ATH_MSG_INFO("Only the pileup mu-based calibration will be applied.");
46 if(m_doNPVOnly) ATH_MSG_INFO("Only the pileup NPV-based calibration will be applied.");
47 if(m_doNJetOnly) ATH_MSG_INFO("Only the pileup NJet-based calibration will be applied.");
48 if (m_useNjet) ATH_MSG_DEBUG("NJet will be used instead of NPV in the pileup corrections.");
49
50 // Protections
52 "Sequential residual calibration can not be applied in doMuOnly or doNPVOnly or doNJetOnly cases.");
53
55 "Conflicting configuation, UseNjet true but doMuOnly or doNPVOnly also true.");
56
58 "It was requested to apply only the mu-based AND the NPV-based calibrations.");
59
61 "It was requested to apply only the mu-based AND the NJet-based calibrations.");
62
64 "It was requested to apply only the NJet-based calibration but not to use Njet instead of NPV.");
65
67 "It was requested to apply NJet-based and NPV calibrations.");
68
69 if(m_doJetArea) ATH_MSG_DEBUG("Jet area pile up correction will be applied.");
70
71
73 "OffsetCorrection.DefaultMuRef not specified.");
74
76 "OffsetCorrection.DefaultNPVRef not specified.");
77
79 "OffsetCorrection.DefaultNjetRef not specified.");
80
81
82 m_resOffsetBins = new TAxis(m_offsetEtaBins.size()-1,&m_offsetEtaBins[0]);
83
84 if(!m_doNPVOnly && !m_doNJetOnly){
85 CHECK_THEN_ERROR( (int)m_resOffsetMu.size()!=(m_resOffsetBins->GetNbins()+1),
86 "Incorrect specification of MuTerm binning" );
87 }
88
89 if(m_useNjet) {
90 CHECK_THEN_ERROR( (int)m_resOffsetNjet.size()!= (m_resOffsetBins->GetNbins()+1),
91 "Incorrect specification of nJetTerm binning." );
92 } else if(!m_doMuOnly){
93 CHECK_THEN_ERROR( (int)m_resOffsetNPV.size()!= (m_resOffsetBins->GetNbins()+1),
94 "Incorrect specification of NPVTerm binning." );
95
98 ATH_MSG_INFO("\n NPV beamspot correction will be applied.");
99 }
100 }
101
102 return StatusCode::SUCCESS;
103}
104
105
106
108
109 ATH_MSG_DEBUG("Calibrating jet collection with 1D pile-up correction");
110
112 CHECK_THEN_ERROR( ! eventInfoDecor.isPresent() , "EventInfo decoration not available! "<< m_muKey.key() );
113 double mu = eventInfoDecor(0) ;
114
115
117 CHECK_THEN_ERROR( ! PVCont.isValid() , "No Primary Vertices "<< m_pvKey.key() );
118 double NPV = JetCalibUtils::countNPV(*PVCont);
119
121 CHECK_THEN_ERROR( ! eventShape.isValid() , "Could not retrieve xAOD::EventShape : "<< m_rhoKey.key());
122 double rho=0;
123 CHECK_THEN_ERROR( ! eventShape->getDensity(xAOD::EventShape::Density, rho ),
124 "Could not retrieve xAOD::EventShape::Density from xAOD::EventShape "<< m_rhoKey.key() );
125
126 int nJets=0;
127 if(m_useNjet){
129 CHECK_THEN_ERROR( !nJetCont.isValid() , "Jet container needed for nJet not found: "<< m_nJetContainerKey.key());
130 for(const xAOD::Jet*jet: *nJetCont){
131 if(jet->pt()/1000. > m_njetThreshold)
132 nJets += 1;
133 }
134 }
135
136
137 ATH_MSG_DEBUG(" Rho = " << 0.001*rho << " GeV");
138 static const double toGeV = 0.001;
142 SG::AuxElement::Accessor<int> puCorrectedAcc("PileupCorrected");
143
144 for( xAOD::Jet * jet : jetCont){
145
146 xAOD::JetFourMom_t jetStartP4 = startScaleMomAcc.getAttribute(*jet);
147
148 const double E_det = jetStartP4.e();
149 const double pT_det = jetStartP4.pt();
150 const double eta_det = jetStartP4.eta();
151 const double mass_det = jetStartP4.mass();
152
153 if ( E_det < mass_det ) {
154 ATH_MSG_ERROR( "JetPileupCorrection::calibrateImpl : Current jet has mass=" << mass_det*toGeV << " GeV, which is greater than it's energy=" << E_det*toGeV << " GeV?? Aborting." );
155 return StatusCode::FAILURE;
156 }
157
158 xAOD::JetFourMom_t jetareaP4 = areaAcc.getAttribute(*jet);
159 ATH_MSG_VERBOSE(" Area = " << jetareaP4);
160
161 double offsetET = 0; // pT residual subtraction
162 double pT_offset = pT_det; // pT difference before/after pileup corrections
163 double pileup_SF = 1; // final calibration factor applied to the four vector
164
165 xAOD::JetFourMom_t calibP4;
166 if(!m_doSequentialResidual){ // Default, both corrections are applied simultaneously
167
168 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, m_doMuOnly, m_doNPVOnly||m_doNJetOnly);
169
170 // Calculate the pT after jet areas and residual offset
171 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
172
173 // Set the jet pT to 10 MeV if the pT is negative after the jet area and residual offset corrections
174 pileup_SF = pT_offset >= 0 ? pT_offset / pT_det : 10./pT_det;
175
176 calibP4 = jetStartP4*pileup_SF;
177
178 }else{
179 // Calculate mu-based correction factor
180 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, true, false);
181 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
182 double muSF = pT_offset >= 0 ? pT_offset / pT_det : 10./pT_det;
183
184 calibP4 = jetStartP4*muSF;
185
186 // Calculate and apply NPV/Njet-based calibration
187 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, false, true);
188 double pT_afterMuCalib = calibP4.pt();
189 pT_offset = pT_afterMuCalib - offsetET;
190 double SF = pT_offset >= 0 ? pT_offset / pT_afterMuCalib : 10./pT_afterMuCalib;
191 calibP4 = calibP4*SF;
192
193 }
194
195 //Attribute to track if a jet has received the pileup subtraction (always true if this code was run)
196 puCorrectedAcc(*jet) = 1 ;
197 //Transfer calibrated jet properties to the Jet object
198 outScaleMomAcc.setAttribute(*jet, calibP4 );
199 jet->setJetP4( calibP4 );
200
201 }
202
203
204 return StatusCode::SUCCESS;
205}
206
207
208double Pileup1DResidualCalibStep::getResidualOffset ( double abseta, double mu, double NPV,
209 int nJet, bool MuOnly, bool NOnly ) const {
210 return getResidualOffsetET(abseta, mu, NPV, nJet, MuOnly, NOnly,
212}
213
214double Pileup1DResidualCalibStep::getResidualOffsetET( double abseta, double mu, double NPV,
215 int nJet, bool MuOnly, bool NOnly,
216 const std::vector<double>& OffsetMu,
217 const std::vector<double>& OffsetNPV,
218 const std::vector<double>& OffsetNjet,
219 const TAxis *OffsetBins ) const {
220
221 static const double toMeV= 1000.;
222 //mu rescaling
223 const double muCorr = m_isData ? mu : mu*m_muSF;
224 if(m_useNjet) {
225 // further correction to nJet if desired
226 int nJetCorr = nJet;
227
228 double alpha, beta, etaEdge;
229 if(!MuOnly){ beta = OffsetNjet[0];
230 } else { beta = 0; }
231 if(!NOnly){ alpha = OffsetMu[0];
232 } else { alpha = 0; }
233 etaEdge=0;
234 int bin=1;
235 for (;bin<=OffsetBins->GetNbins();++bin) {
236 etaEdge = OffsetBins->GetBinLowEdge(bin);
237 const double width=OffsetBins->GetBinWidth(bin);
238 if (abseta<etaEdge+width) break;
239 if(!NOnly) alpha += width*OffsetMu[bin];
240 if(!MuOnly) beta += width*OffsetNjet[bin];
241 }
242 if(!NOnly) alpha += OffsetMu[bin]*(abseta-etaEdge);
243 if(!MuOnly) beta += OffsetNjet[bin]*(abseta-etaEdge);
244 return (alpha*(muCorr-m_mu_ref) + beta*(nJetCorr-m_nJet_ref))*toMeV;
245 } else {
246 //NPV beamspot correction
247 const double NPVCorr = getNPVBeamspotCorrection(NPV);
248
249 double alpha, beta, etaEdge;
250 if(!MuOnly){ beta = OffsetNPV[0];
251 } else { beta = 0; }
252 if(!NOnly){ alpha = OffsetMu[0];
253 } else { alpha = 0; }
254 etaEdge = 0;
255 int bin=1;
256 for (;bin<=OffsetBins->GetNbins();++bin) {
257 etaEdge = OffsetBins->GetBinLowEdge(bin);
258 const double width=OffsetBins->GetBinWidth(bin);
259 if (abseta<etaEdge+width) break;
260 if(!NOnly) alpha += width*OffsetMu[bin];
261 if(!MuOnly) beta += width*OffsetNPV[bin];
262 }
263 if(!NOnly) alpha += OffsetMu[bin]*(abseta-etaEdge);
264 if(!MuOnly) beta += OffsetNPV[bin]*(abseta-etaEdge);
265 return (alpha*(muCorr-m_mu_ref) + beta*(NPVCorr-m_NPV_ref))*toMeV;
266 }
267
268}
269
271 if(!m_isData && m_applyNPVBeamspotCorrection) return std::as_const(m_npvBeamspotCorr)->GetNVertexBsCorrection(NPV);
272 return NPV;
273}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading a decoration on an object.
This header defines wrapper classes around SG::AuxElement::Accessor used internally in the Jet EDM.
#define CHECK_THEN_ERROR(checkcode, message)
const double width
Gaudi::Property< std::vector< double > > m_resOffsetNjet
Gaudi::Property< int > m_njetThreshold
Gaudi::Property< std::string > m_jetOutScale
Gaudi::Property< bool > m_doMuOnly
NPVBeamspotCorrection * m_npvBeamspotCorr
virtual StatusCode calibrate(xAOD::JetContainer &jetCont) const override
Apply calibration to a jet container.
Gaudi::Property< float > m_mu_ref
Gaudi::Property< bool > m_doJetArea
Gaudi::Property< bool > m_doSequentialResidual
Gaudi::Property< bool > m_applyNPVBeamspotCorrection
Gaudi::Property< std::string > m_jetInScale
double getNPVBeamspotCorrection(double NPV) const
Gaudi::Property< std::vector< double > > m_resOffsetNPV
SG::ReadHandleKey< xAOD::VertexContainer > m_pvKey
double getResidualOffset(double abseta, double mu, double NPV, int nJet, bool MuOnly, bool NOnly) const
Gaudi::Property< float > m_NPV_ref
Gaudi::Property< std::vector< double > > m_resOffsetMu
Gaudi::Property< std::vector< double > > m_offsetEtaBins
Pileup1DResidualCalibStep(const std::string &name="Pileup1DResidualCalibStep")
SG::ReadHandleKey< xAOD::JetContainer > m_nJetContainerKey
Gaudi::Property< float > m_muSF
double getResidualOffsetET(double abseta, double mu, double NPV, int nJet, bool MuOnly, bool NOnly, const std::vector< double > &OffsetMu, const std::vector< double > &OffsetNPV, const std::vector< double > &OffsetNjet, const TAxis *OffsetBins) const
Gaudi::Property< bool > m_doOnlyResidual
Gaudi::Property< bool > m_doNJetOnly
SG::ReadDecorHandleKey< xAOD::EventInfo > m_muKey
Gaudi::Property< float > m_nJet_ref
Gaudi::Property< bool > m_doNPVOnly
Gaudi::Property< bool > m_useNjet
SG::ReadHandleKey< xAOD::EventShape > m_rhoKey
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Handle class for reading a decoration on an object.
bool isPresent() const
Is the referenced container present in SG?
virtual bool isValid() override final
Can the handle be successfully dereferenced?
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
void getAttribute(const SG::AuxElement &p, TYPE &v) const
void setAttribute(SG::AuxElement &p, const TYPE &v) const
int countNPV(const VXCONT &vxCont)
Jet_v1 Jet
Definition of the current "jet version".
JetContainer_v1 JetContainer
Definition of the current "jet container version".
ROOT::Math::LorentzVector< ROOT::Math::PtEtaPhiM4D< double > > JetFourMom_t
Base 4 Momentum type for Jet.
Definition JetTypes.h:17