ATLAS Offline Software
Loading...
Searching...
No Matches
Pileup1DResidualCalibStep.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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_INFO("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
110 CHECK_THEN_ERROR( ! eventInfoDecor.isPresent() , "EventInfo decoration not available! "<< m_muKey.key() );
111 double mu = eventInfoDecor(0) ;
112
113
115 CHECK_THEN_ERROR( ! PVCont.isValid() , "No Primary Vertices "<< m_pvKey.key() );
116 double NPV = JetCalibUtils::countNPV(*PVCont);
117
119 CHECK_THEN_ERROR( ! eventShape.isValid() , "Could not retrieve xAOD::EventShape DataHandle : "<< m_rhoKey.key());
120 double rho=0;
121 CHECK_THEN_ERROR( ! eventShape->getDensity(xAOD::EventShape::Density, rho ),
122 "Could not retrieve xAOD::EventShape::Density from xAOD::EventShape "<< m_rhoKey.key() );
123
124 int nJets=0;
125 if(m_useNjet){
127 CHECK_THEN_ERROR( !nJetCont.isValid() , "Jet container needed for nJet not found: "<< m_nJetContainerKey.key());
128 for(const xAOD::Jet*jet: *nJetCont){
129 if(jet->pt()/1000. > m_njetThreshold)
130 nJets += 1;
131 }
132 }
133
134
135 ATH_MSG_DEBUG(" Rho = " << 0.001*rho << " GeV");
136 static const double toGeV = 0.001;
140 SG::AuxElement::Accessor<int> puCorrectedAcc("PileupCorrected");
141
142 for( xAOD::Jet * jet : jetCont){
143
144
145 xAOD::JetFourMom_t jetStartP4 = startScaleMomAcc.getAttribute(*jet);
146
147 const double E_det = jetStartP4.e();
148 const double pT_det = jetStartP4.pt();
149 const double eta_det = jetStartP4.eta();
150 const double mass_det = jetStartP4.mass();
151
152 if ( E_det < mass_det ) {
153 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." );
154 return StatusCode::FAILURE;
155 }
156
157 xAOD::JetFourMom_t jetareaP4 = areaAcc.getAttribute(*jet);
158 ATH_MSG_VERBOSE(" Area = " << jetareaP4);
159
160 double offsetET = 0; // pT residual subtraction
161 double pT_offset = pT_det; // pT difference before/after pileup corrections
162 double pileup_SF = 1; // final calibration factor applied to the four vector
163
164 xAOD::JetFourMom_t calibP4;
165 if(!m_doSequentialResidual){ // Default, both corrections are applied simultaneously
166
167 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, m_doMuOnly, m_doNPVOnly||m_doNJetOnly);
168
169 // Calculate the pT after jet areas and residual offset
170 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
171
172 // Set the jet pT to 10 MeV if the pT is negative after the jet area and residual offset corrections
173 pileup_SF = pT_offset >= 0 ? pT_offset / pT_det : 10./pT_det;
174
175 calibP4 = jetStartP4*pileup_SF;
176
177 }else{
178 // Calculate mu-based correction factor
179 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, true, false);
180 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
181 double muSF = pT_offset >= 0 ? pT_offset / pT_det : 10./pT_det;
182
183 calibP4 = jetStartP4*muSF;
184
185 // Calculate and apply NPV/Njet-based calibration
186 offsetET = getResidualOffset(fabs(eta_det), mu, NPV, nJets, false, true);
187 double pT_afterMuCalib = calibP4.pt();
188 pT_offset = pT_afterMuCalib - offsetET;
189 double SF = pT_offset >= 0 ? pT_offset / pT_afterMuCalib : 10./pT_afterMuCalib;
190 calibP4 = calibP4*SF;
191
192 }
193
194 //Attribute to track if a jet has received the pileup subtraction (always true if this code was run)
195 puCorrectedAcc(*jet) = 1 ;
196 //Transfer calibrated jet properties to the Jet object
197 outScaleMomAcc.setAttribute(*jet, calibP4 );
198 jet->setJetP4( calibP4 );
199
200 }
201
202
203 return StatusCode::SUCCESS;
204}
205
206
207double Pileup1DResidualCalibStep::getResidualOffset ( double abseta, double mu, double NPV,
208 int nJet, bool MuOnly, bool NOnly ) const {
209 return getResidualOffsetET(abseta, mu, NPV, nJet, MuOnly, NOnly,
211}
212
213double Pileup1DResidualCalibStep::getResidualOffsetET( double abseta, double mu, double NPV,
214 int nJet, bool MuOnly, bool NOnly,
215 const std::vector<double>& OffsetMu,
216 const std::vector<double>& OffsetNPV,
217 const std::vector<double>& OffsetNjet,
218 const TAxis *OffsetBins ) const {
219
220 static const double toMeV= 1000.;
221 //mu rescaling
222 const double muCorr = m_isData ? mu : mu*m_muSF;
223 if(m_useNjet) {
224 // further correction to nJet if desired
225 int nJetCorr = nJet;
226
227 double alpha, beta, etaEdge;
228 if(!MuOnly){ beta = OffsetNjet[0];
229 } else { beta = 0; }
230 if(!NOnly){ alpha = OffsetMu[0];
231 } else { alpha = 0; }
232 etaEdge=0;
233 int bin=1;
234 for (;bin<=OffsetBins->GetNbins();++bin) {
235 etaEdge = OffsetBins->GetBinLowEdge(bin);
236 const double width=OffsetBins->GetBinWidth(bin);
237 if (abseta<etaEdge+width) break;
238 if(!NOnly) alpha += width*OffsetMu[bin];
239 if(!MuOnly) beta += width*OffsetNjet[bin];
240 }
241 if(!NOnly) alpha += OffsetMu[bin]*(abseta-etaEdge);
242 if(!MuOnly) beta += OffsetNjet[bin]*(abseta-etaEdge);
243 return (alpha*(muCorr-m_mu_ref) + beta*(nJetCorr-m_nJet_ref))*toMeV;
244 } else {
245 //NPV beamspot correction
246 const double NPVCorr = getNPVBeamspotCorrection(NPV);
247
248 double alpha, beta, etaEdge;
249 if(!MuOnly){ beta = OffsetNPV[0];
250 } else { beta = 0; }
251 if(!NOnly){ alpha = OffsetMu[0];
252 } else { alpha = 0; }
253 etaEdge = 0;
254 int bin=1;
255 for (;bin<=OffsetBins->GetNbins();++bin) {
256 etaEdge = OffsetBins->GetBinLowEdge(bin);
257 const double width=OffsetBins->GetBinWidth(bin);
258 if (abseta<etaEdge+width) break;
259 if(!NOnly) alpha += width*OffsetMu[bin];
260 if(!MuOnly) beta += width*OffsetNPV[bin];
261 }
262 if(!NOnly) alpha += OffsetMu[bin]*(abseta-etaEdge);
263 if(!MuOnly) beta += OffsetNPV[bin]*(abseta-etaEdge);
264 return (alpha*(muCorr-m_mu_ref) + beta*(NPVCorr-m_NPV_ref))*toMeV;
265 }
266
267}
268
270 if(!m_isData && m_applyNPVBeamspotCorrection) return std::as_const(m_npvBeamspotCorr)->GetNVertexBsCorrection(NPV);
271 return NPV;
272}
#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.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
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