ATLAS Offline Software
Loading...
Searching...
No Matches
JetPileupCorrection.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <TEnv.h>
7
10
13
14#include <memory>
15#include <utility>
16
19 m_config(nullptr), m_jetAlgo(""), m_calibAreaTag(""), m_dev(false), m_doResidual(false),
20 m_doJetArea(false), m_doOrigin(false), m_isData(false),
21 m_useFull4vectorArea(false), m_residualOffsetCorr(nullptr), m_originScale("JetOriginConstitScaleMomentum")
22{}
23
24JetPileupCorrection::JetPileupCorrection(const std::string& name, TEnv* config, TString jetAlgo, TString calibAreaTag,
25 bool doResidual, bool doJetArea, bool doOrigin, const std::string& originScale,
26 bool isData, bool dev)
28 m_config(config), m_jetAlgo(std::move(jetAlgo)), m_calibAreaTag(std::move(calibAreaTag)), m_dev(dev),
29 m_doResidual(doResidual), m_doJetArea(doJetArea), m_doOrigin(doOrigin), m_isData(isData),
30 m_useFull4vectorArea(false), m_residualOffsetCorr(nullptr), m_originScale(originScale)
31{}
32
38
39
41
42 ATH_MSG_INFO("Initializing pileup correction.");
43
44 if (m_doOrigin) ATH_MSG_INFO("OriginScale: " << m_originScale);
45
46 if(!m_config){
47 ATH_MSG_ERROR("Jet pileup correction tool received a null config pointer.");
48 return StatusCode::FAILURE;
49 }
50
51 m_doOnlyResidual = m_config->GetValue("ApplyOnlyResidual",false);
53 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.");
54 return StatusCode::FAILURE;
55 }
56
57 m_doMuOnly = m_config->GetValue("ApplyOnlyMuResidual",false);
58 m_doNPVOnly = m_config->GetValue("ApplyOnlyNPVResidual",false);
59 m_doNJetOnly = m_config->GetValue("ApplyOnlyNJetResidual",false);
60 m_doSequentialResidual = m_config->GetValue("DoSequentialResidual",false); // first mu and then NPV/NJet corrections
61 bool useNjet = m_config->GetValue("OffsetCorrection.UseNjet", false);
62
63 m_do3Dcorrection = m_config->GetValue("Do3DCorrection", false);
64
65 if(m_doSequentialResidual) ATH_MSG_DEBUG("The pileup residual calibrations will be applied sequentially.");
66 else ATH_MSG_DEBUG("The pileup residual calibrations will be applied simultaneously (default).");
67 if(m_doMuOnly) ATH_MSG_INFO("Only the pileup mu-based calibration will be applied.");
68 if(m_doNPVOnly) ATH_MSG_INFO("Only the pileup NPV-based calibration will be applied.");
69 if(m_doNJetOnly) ATH_MSG_INFO("Only the pileup NJet-based calibration will be applied.");
70 else if (useNjet) ATH_MSG_DEBUG("NJet will be used instead of NPV in the pileup corrections.");
71
72 // Protections
74 ATH_MSG_FATAL("Sequential residual calibration can not be applied in doMuOnly or doNPVOnly or doNJetOnly cases.");
75 return StatusCode::FAILURE;
76 }
77 if(useNjet && (m_doMuOnly || m_doNPVOnly)){
78 ATH_MSG_FATAL("Conflicting configuation, UseNjet true but doMuOnly or doNPVOnly also true.");
79 return StatusCode::FAILURE;
80 }
82 ATH_MSG_FATAL("It was requested to apply only the mu-based AND the NPV-based calibrations.");
83 return StatusCode::FAILURE;
84 }
86 ATH_MSG_FATAL("It was requested to apply only the mu-based AND the NJet-based calibrations.");
87 return StatusCode::FAILURE;
88 }
89 if(!useNjet && m_doNJetOnly){
90 ATH_MSG_FATAL("It was requested to apply only the NJet-based calibration but not to use Njet instead of NPV.");
91 return StatusCode::FAILURE;
92 }
94 ATH_MSG_FATAL("It was requested to apply NJet-based and NPV calibrations.");
95 return StatusCode::FAILURE;
96 }
97
99 ATH_MSG_FATAL("3D correction incompatible with any other PU correction. Please turn off any PU residual options.");
100 return StatusCode::FAILURE;
101
102 }
103
104 m_jetStartScale = m_config->GetValue("PileupStartingScale","JetConstitScaleMomentum");
105 ATH_MSG_INFO("JetPileupCorrection: Starting scale: " << m_jetStartScale);
106 if ( m_jetStartScale.compare("DO_NOT_USE") == 0 ) {
107 ATH_MSG_WARNING("Configuration file does not specify the jet starting scale!");
108 }
109
110 m_useFull4vectorArea = m_config->GetValue("ApplyFullJetArea4MomentumCorrection", false);
111 if(m_doJetArea) ATH_MSG_INFO("Jet area pile up correction will be applied.");
112 if ( m_useFull4vectorArea ) ATH_MSG_INFO(" Full 4-vector jet area correction is activated.");
113 //ATH_MSG_INFO(" \n");
114
116 m_residual3DCorr = std::make_unique<PUCorrection::PU3DCorrectionHelper>( ) ;
117
118 TString PUCalibFile3D = m_config->GetValue("PU3DCorrection.constants", "pu3DResidualsConstants.root");
119
120 if(m_dev){
121 //Currently hard coded that we remove "JetCalibTools/CalibrationFactors/" from the string in dev mode
122 //Same implementation as in other JetCalibTools classes for now, will be changed everywhere during major overhaul of package for r22
123 PUCalibFile3D.Remove(0,33);
124 PUCalibFile3D.Insert(0,"JetCalibTools/");
125 }
126 else{
127 PUCalibFile3D.Insert(14,m_calibAreaTag);
128 }
129
130 const std::string calibFilePU = PathResolverFindCalibFile(PUCalibFile3D.Data());
131
132 m_residual3DCorr->loadParameters(calibFilePU);
133 m_residual3DCorr->m_rhoEnergyScale = m_config->GetValue("PU3DCorrection.rhoEnergyScale", 0.001);
134 m_residual3DCorr->m_pTEnergyScale = m_config->GetValue("PU3DCorrection.pTEnergyScale", 0.001);
135 m_residual3DCorr->m_applyDeltaPtTerm = m_config->GetValue("PU3DCorrection.applyDeltaPtTerm", true);
136 ATH_MSG_INFO("Pile-up 3D correction. Configured with :");
137 ATH_MSG_INFO(" calib constants file="<< m_config->GetValue("PU3DCorrection.constants", "pu3DResidualsConstants.root") );
138 ATH_MSG_INFO(" rho scale ="<<m_residual3DCorr->m_rhoEnergyScale );
139 ATH_MSG_INFO(" pT scale ="<<m_residual3DCorr->m_pTEnergyScale);
140 ATH_MSG_INFO(" apply deltaPt term = " << m_residual3DCorr->m_applyDeltaPtTerm);
141 } else if ( m_doResidual ) {
142 std::string suffix = "_Residual";
144 m_residualOffsetCorr->msg().setLevel( this->msg().level() );
145 ATH_CHECK( m_residualOffsetCorr->initialize() );
146 }
147
149 ATH_MSG_WARNING("JetPileupCorrection::initializeTool : WARNING!! You have requested the 4 vector jet area correction and the residual offset correction. This configuration is not currently supported, the residual offset correction will be deactivated.");
150 return StatusCode::SUCCESS;
151 } else if ( !m_doResidual && !m_useFull4vectorArea ) {
152 ATH_MSG_VERBOSE("JetPileupCorrection::initializeTool : You have requested the transverse jet area correction without the residual offset correction. This configuration is not recommended.");
153 return StatusCode::SUCCESS;
154 } else {
155 return StatusCode::SUCCESS;
156 }
157 return StatusCode::FAILURE;
158}
159
160StatusCode JetPileupCorrection::calibrate(xAOD::Jet& jet, JetEventInfo& jetEventInfo) const {
161 ATH_MSG_VERBOSE(" Applying pileup calibration to jet " << jet.index());
162 ATH_MSG_VERBOSE(" Initial jet pT = " << 0.001*jet.pt() << " GeV");
163
164 xAOD::JetFourMom_t jetStartP4;
166 jetStartP4 = jet.jetP4();
167
168 const double E_det = jetStartP4.e();
169 const double pT_det = jetStartP4.pt();
170 const double eta_det = jetStartP4.eta();
171 const double mass_det = jetStartP4.mass();
172
173 if ( E_det < mass_det ) {
174 ATH_MSG_WARNING( "JetPileupCorrection::calibrateImpl : Current jet has mass=" << mass_det/m_GeV << " GeV, which is greater than it's energy=" << E_det/m_GeV << " GeV?? Aborting." );
175 return StatusCode::FAILURE;
176 }
177
178 xAOD::JetFourMom_t jetareaP4 = jet.getAttribute<xAOD::JetFourMom_t>("ActiveArea4vec");
179 ATH_MSG_VERBOSE(" Area = " << jetareaP4);
180 const double rho = jetEventInfo.rho();
181 ATH_MSG_VERBOSE(" Rho = " << rho);
182
184 int NPV = jetEventInfo.NPV();
185 float mu = jetEventInfo.mu();
186
187 double pt_calib= m_residual3DCorr->correctedPt(pT_det, eta_det, jetareaP4.Pt(), rho, mu, NPV ) ;
188 double scaleF = pt_calib < 0 ? 0.01*m_GeV/pT_det : pt_calib/pT_det;
189 xAOD::JetFourMom_t calibP4 = jetStartP4 * scaleF;
190 jet.setAttribute<int>("PileupCorrected",true);
191 jet.setAttribute<xAOD::JetFourMom_t>("JetPileupScaleMomentum",calibP4);
192 jet.setJetP4( calibP4 );
193
194 } else if (m_useFull4vectorArea) {
195 ATH_MSG_VERBOSE(" Applying area-subtraction calibration to jet " << jet.index() << " with pT = " << 0.001*jet.pt() << " GeV");
196 //subtract rho * the jet area from the jet
197 xAOD::JetFourMom_t calibP4 = jetStartP4 - rho*jetareaP4;
198 //Attribute to track if a jet has received the pileup subtraction (always true if this code was run)
199 jet.setAttribute<int>("PileupCorrected",true);
200 //Transfer calibrated jet properties to the Jet object
201 jet.setAttribute<xAOD::JetFourMom_t>("JetPileupScaleMomentum",calibP4);
202 jet.setJetP4( calibP4 );
203
205 ATH_MSG_VERBOSE(" Applying residual pileup calibration to jet " << jet.index() << " with pT = " << 0.001*jet.pt() << " GeV");
206
207 const double NPV = jetEventInfo.NPV();
208 const double mu = jetEventInfo.mu();
209 const int nJet = jetEventInfo.nJet();
210
211 // Retrieve the offset correction from the residual correction class
212 double offsetET = 0; // pT residual subtraction
213 double pT_offset = pT_det; // pT difference before/after pileup corrections
214 double pileup_SF = 1; // final calibration factor applied to the four vector
215
216 xAOD::JetFourMom_t calibP4;
217 if(!m_doSequentialResidual){ // Default, both corrections are applied simultaneously
218 offsetET = m_residualOffsetCorr->GetResidualOffset(fabs(eta_det), mu, NPV, nJet, m_doMuOnly, m_doNPVOnly||m_doNJetOnly);
219
220 // Calculate the pT after jet areas and residual offset
221 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
222
223 // Set the jet pT to 10 MeV if the pT is negative after the jet area and residual offset corrections
224 pileup_SF = pT_offset >= 0 ? pT_offset / pT_det : 0.01*m_GeV/pT_det;
225
226 if ( m_doOrigin ) {
227 xAOD::JetFourMom_t jetOriginP4;
228 static std::atomic<unsigned int> originWarnings = 0;
229 if ( jet.getAttribute<xAOD::JetFourMom_t>(m_originScale.c_str(),jetOriginP4) )
230 calibP4 = jetOriginP4*pileup_SF;
231 else {
232 if ( originWarnings < 20 ) {
233 ATH_MSG_WARNING("Could not retrieve " << m_originScale << " jet attribute, origin correction will not be applied.");
234 ++originWarnings;
235 }
236 calibP4 = jetStartP4*pileup_SF;
237 }
238 } else {
239 calibP4 = jetStartP4*pileup_SF;
240 }
241 } else {
242
243 // Calculate mu-based correction factor
244 offsetET = m_residualOffsetCorr->GetResidualOffset(fabs(eta_det), mu, NPV, nJet, true, false);
245 pT_offset = m_doJetArea ? pT_det - rho*jetareaP4.pt() - offsetET : pT_det - offsetET;
246 double muSF = pT_offset >= 0 ? pT_offset / pT_det : 0.01*m_GeV/pT_det;
247
248 // Apply mu-based calibration
249 if ( m_doOrigin ) {
250 xAOD::JetFourMom_t jetOriginP4;
251 static std::atomic<unsigned int> originWarnings = 0;
252 if ( jet.getAttribute<xAOD::JetFourMom_t>(m_originScale.c_str(),jetOriginP4) )
253 calibP4 = jetOriginP4*muSF;
254 else {
255 if ( originWarnings < 20 ) {
256 ATH_MSG_WARNING("Could not retrieve " << m_originScale << " jet attribute, origin correction will not be applied.");
257 ++originWarnings;
258 }
259 calibP4 = jetStartP4*muSF;
260 }
261 } else {
262 calibP4 = jetStartP4*muSF;
263 }
264
265 // Calculate and apply NPV/Njet-based calibration
266 offsetET = m_residualOffsetCorr->GetResidualOffset(fabs(eta_det), mu, NPV, nJet, false, true);
267 double pT_afterMuCalib = calibP4.pt();
268 pT_offset = pT_afterMuCalib - offsetET;
269 double SF = pT_offset >= 0 ? pT_offset / pT_afterMuCalib : 0.01*m_GeV/pT_afterMuCalib;
270 calibP4 = calibP4*SF;
271
272 }
273
274 //Attribute to track if a jet has received the origin correction
275 jet.setAttribute<int>("OriginCorrected",m_doOrigin);
276 //Attribute to track if a jet has received the pileup subtraction (always true if this code was run)
277 jet.setAttribute<int>("PileupCorrected",true);
278
279 //Transfer calibrated jet properties to the Jet object
280 jet.setAttribute<xAOD::JetFourMom_t>("JetPileupScaleMomentum",calibP4);
281 jet.setJetP4( calibP4 );
282
283 } else {
284 ATH_MSG_VERBOSE(" Applying postive-only area-subtraction calibration to jet " << jet.index() << " with pT = " << 0.001*jet.pt() << " GeV");
285 //Set the jet pT to 10 MeV if the pT or energy is negative after the jet area correction
286 const double area_SF = (pT_det-rho*jetareaP4.pt()<=0 || E_det-rho*jetareaP4.e()<=0) ? 10/pT_det : (pT_det-rho*jetareaP4.pt())/pT_det;
287 xAOD::JetFourMom_t calibP4;
288 if ( m_doOrigin ) {
289 xAOD::JetFourMom_t jetOriginP4;
290 static std::atomic<unsigned int> originWarnings = 0;
291 if ( jet.getAttribute<xAOD::JetFourMom_t>(m_originScale.c_str(),jetOriginP4) )
292 calibP4 = jetOriginP4*area_SF;
293 else {
294 if ( originWarnings < 20 ) {
295 ATH_MSG_WARNING("Could not retrieve " << m_originScale << " jet attribute, origin correction will not be applied.");
296 ++originWarnings;
297 }
298 calibP4 = jetStartP4*area_SF;
299 }
300 } else calibP4 = jetStartP4*area_SF;
301
302 //Attribute to track if a jet has received the origin correction
303 jet.setAttribute<int>("OriginCorrected",m_doOrigin);
304 //Attribute to track if a jet has received the pileup subtraction (always true if this code was run)
305 jet.setAttribute<int>("PileupCorrected",true);
306
307 //Transfer calibrated jet properties to the Jet object
308 jet.setAttribute<xAOD::JetFourMom_t>("JetPileupScaleMomentum",calibP4);
309 jet.setJetP4( calibP4 );
310 }
311
312 ATH_MSG_VERBOSE(" Calibrated jet pT = " << 0.001*jet.pt() << " GeV");
313 return StatusCode::SUCCESS;
314}
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
virtual StatusCode setStartP4(xAOD::Jet &jet) const
JetCalibrationStep(const char *name="JetCalibrationStep")
double rho()
double mu()
double NPV()
std::unique_ptr< PUCorrection::PU3DCorrectionHelper > m_residual3DCorr
virtual StatusCode calibrate(xAOD::Jet &jet, JetEventInfo &jetEventInfo) const override
ResidualOffsetCorrection * m_residualOffsetCorr
virtual StatusCode initialize() override
MsgStream & msg() const
The standard message stream.
STL namespace.
Jet_v1 Jet
Definition of the current "jet version".
ROOT::Math::LorentzVector< ROOT::Math::PtEtaPhiM4D< double > > JetFourMom_t
Base 4 Momentum type for Jet.
Definition JetTypes.h:17