ATLAS Offline Software
Loading...
Searching...
No Matches
JetCalibrationTool.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5*/
6
7// JetCalibrationTool.cxx
8// Implementation file for class JetCalibrationTool
9// Author: Joe Taenzer <joseph.taenzer@cern.ch>
11
27
30
32 : asg::AsgMetadataTool( name )
33{
34 declareProperty( "JetCollection", m_jetAlgo = "AntiKt4LCTopo" );
35 declareProperty( "ConfigFile", m_config = "" );
36 declareProperty( "CalibSequence", m_calibSeq = "JetArea_Offset_AbsoluteEtaJES_Insitu" );
37 declareProperty( "IsData", m_isData = true );
38 declareProperty( "ForceCampaign", m_forceCampaign = "");
39 declareProperty( "ConfigDir", m_dir = "JetCalibTools/CalibrationConfigs/" );
40 declareProperty( "EventInfoName", m_eInfoName = "EventInfo");
41 declareProperty( "DEVmode", m_devMode = false);
42 declareProperty( "OriginScale", m_originScale = "JetOriginConstitScaleMomentum");
43 declareProperty( "CalibArea", m_calibAreaTag = "00-04-82");
44 declareProperty( "GSCDepth", m_gscDepth);
45 declareProperty( "useOriginVertex", m_useOriginVertex = false);
46 // Options to force files for metadata-dependent calibration in case metadata is not available
47 declareProperty( "ForceCalibFilePtResidual", m_forceCalibFile_PtResidual = "");
48 declareProperty( "ForceCalibFileFastSim", m_forceCalibFile_FastSim = "");
49 declareProperty( "ForceCalibFileMC2MC", m_forceCalibFile_MC2MC = "");
50}
51
54 for(TEnv* config : m_globalTimeDependentConfigs) delete config;
55 for(TEnv* config : m_globalInsituCombMassConfig) delete config;
56}
57
58
60// Public methods:
62
64 ATH_MSG_INFO ("Initializing " << name() << " to calibrate " << m_jetAlgo << "Jets");
65
66 TString jetAlgo = m_jetAlgo;
67 TString calibSeq = m_calibSeq;
68 std::string dir = m_dir;
69
70 //Make sure the necessary properties were set via the constructor or python configuration
71 if ( jetAlgo.EqualTo("") || calibSeq.EqualTo("") ) {
72 ATH_MSG_FATAL("JetCalibrationTool::initialize : At least one of your constructor arguments is not set. Did you use the copy constructor?");
73 return StatusCode::FAILURE;
74 }
75
76 if ( m_config.empty() ) { ATH_MSG_FATAL("No configuration file specified."); return StatusCode::FAILURE; }
77 // The calibration area tag is a property of the tool
78 const std::string calibPath = "CalibArea-" + m_calibAreaTag + "/";
79 if(m_devMode){
80 ATH_MSG_WARNING("Dev Mode is ON!!!");
81 ATH_MSG_WARNING("Dev Mode is NOT RECOMMENDED!!!");
82 dir = "JetCalibTools/";
83 }
84 else{dir.insert(14,calibPath);} // Obtaining the path of the configuration file
85 std::string configPath=dir+m_config; // Full path
86 TString fn = PathResolverFindCalibFile(configPath);
87 if(fn=="") {
88 ATH_MSG_FATAL( "Couldn't find ConfigFile " << configPath ); return StatusCode::FAILURE;
89 } else {
90 ATH_MSG_INFO("Reading global JES settings from: " << configPath);
91 ATH_MSG_DEBUG("resolved in: " << fn);
92 ATH_MSG_INFO(" Calibration sequence: " << calibSeq);
93 }
94
95 m_globalConfig = new TEnv();
96 int status=m_globalConfig->ReadFile(fn ,EEnvLevel(0));
97 if (status!=0) { ATH_MSG_FATAL("Cannot read config file " << fn ); return StatusCode::FAILURE; }
98
99 //Make sure that one of the standard jet collections is being used
100 if ( calibSeq.Contains("JetArea") ) {
101 if ( jetAlgo.Contains("PFlow") ) m_jetScale = PFLOW;
102 else if ( jetAlgo.Contains("EM") ) m_jetScale = EM;
103 else if ( jetAlgo.Contains("LC") ) m_jetScale = LC;
104 else { ATH_MSG_FATAL("jetAlgo " << jetAlgo << " not recognized."); return StatusCode::FAILURE; }
105 }
106
107 // Settings for R21/2.5.X
108 m_originCorrectedClusters = m_globalConfig->GetValue("OriginCorrectedClusters",false);
109 m_doSetDetectorEta = m_globalConfig->GetValue("SetDetectorEta",true);
110
111 // Rho key specified in the config file?
112 std::string rhoKey_config = m_globalConfig->GetValue("RhoKey", "None");
113
114 bool requireRhoInput = false;
115
116 //Make sure the residual correction is turned on if requested
117 if ( !calibSeq.Contains("JetArea") && !calibSeq.Contains("Residual") ) {
118 m_doJetArea = false;
119 m_doResidual = false;
120 } else if ( calibSeq.Contains("JetArea") ) {
121 if ( m_rhoKey.key().compare("auto") == 0 && rhoKey_config.compare("None") == 0) {
123 if ( m_jetScale == EM ) m_rhoKey = "Kt4EMTopoEventShape";
124 else if ( m_jetScale == LC ) m_rhoKey = "Kt4LCTopoEventShape";
125 else if ( m_jetScale == PFLOW ) m_rhoKey = "Kt4EMPFlowEventShape";
126 } else{
127 if ( m_jetScale == EM ) m_rhoKey = "Kt4EMTopoOriginEventShape";
128 else if ( m_jetScale == LC ) m_rhoKey = "Kt4LCTopoOriginEventShape";
129 else if ( m_jetScale == PFLOW ) m_rhoKey = "Kt4EMPFlowEventShape";
130 }
131 }
132 else if(rhoKey_config.compare("None") != 0 && m_rhoKey.key().compare("auto") == 0){
133 m_rhoKey = rhoKey_config;
134 }
135 requireRhoInput = true;
136 if ( !calibSeq.Contains("Residual") ) m_doResidual = false;
137 } else if ( !calibSeq.Contains("JetArea") && calibSeq.Contains("Residual") ) {
138 m_doJetArea = false;
139 ATH_MSG_INFO("ApplyOnlyResidual should be true if only Residual pile up correction wants to be applied. Need to specify pile up starting scale in the configuration file.");
140 }
141 // get nJet threshold and name
142 m_useNjetInResidual = m_globalConfig->GetValue("OffsetCorrection.UseNjet", false);
143 m_nJetThreshold = m_globalConfig->GetValue("OffsetCorrection.nJetThreshold", 20);
144 m_nJetContainerName = m_globalConfig->GetValue("OffsetCorrection.nJetContainerName",
145 "HLT_xAOD__JetContainer_a4tcemsubjesISFS");
146
147 if ( !calibSeq.Contains("Origin") ) m_doOrigin = false;
148 if ( !calibSeq.Contains("GSC") && !calibSeq.Contains("GNNC")) m_doGSC = false;
149 if ( !calibSeq.Contains("Bcid") ) m_doBcid = false;
150 if ( calibSeq.Contains("DNN") ) m_doDNNCal = true;
151
152 //Protect against the in-situ calibration being requested when isData is false
153 if ( calibSeq.Contains("Insitu") && !m_isData ) {
154 ATH_MSG_FATAL("JetCalibrationTool::initialize : calibSeq string contains Insitu with isData set to false. Can't apply in-situ correction to MC!!");
155 return StatusCode::FAILURE;
156 }
157
158 // Time-Dependent Insitu Calibration
159 m_timeDependentCalib = m_globalConfig->GetValue("TimeDependentInsituCalibration",false);
160 if(m_timeDependentCalib && calibSeq.Contains("Insitu")){ // Read Insitu Configs
161 m_timeDependentInsituConfigs = JetCalibUtils::Vectorize( m_globalConfig->GetValue("InsituTimeDependentConfigs","") );
162 if(m_timeDependentInsituConfigs.empty()) ATH_MSG_ERROR("Please check there are at least two insitu configs");
163 m_runBins = JetCalibUtils::VectorizeD( m_globalConfig->GetValue("InsituRunBins","") );
164 if(m_runBins.size()!=m_timeDependentInsituConfigs.size()+1) ATH_MSG_ERROR("Please check the insitu run bins");
165 for(unsigned int i=0;i<m_timeDependentInsituConfigs.size();++i){
166
167 std::string configPath_insitu = dir+m_timeDependentInsituConfigs.at(i).Data(); // Full path
168 TString fn_insitu = PathResolverFindCalibFile(configPath_insitu);
169
170 ATH_MSG_INFO("Reading time-dependent insitu settings from: " << m_timeDependentInsituConfigs.at(i));
171 ATH_MSG_INFO("resolved in: " << fn_insitu);
172
173 TEnv *globalConfig_insitu = new TEnv();
174 int status = globalConfig_insitu->ReadFile(fn_insitu ,EEnvLevel(0));
175 if (status!=0) { ATH_MSG_FATAL("Cannot read config file " << fn_insitu ); return StatusCode::FAILURE; }
176 m_globalTimeDependentConfigs.push_back(globalConfig_insitu);
177 }
178 }
179
180 //Combined Mass Calibration:
181 m_insituCombMassCalib = m_globalConfig->GetValue("InsituCombinedMassCorrection",false);
182 if(m_insituCombMassCalib && calibSeq.Contains("InsituCombinedMass")){ // Read Combination Config
183 m_insituCombMassConfig = JetCalibUtils::Vectorize( m_globalConfig->GetValue("InsituCombinedMassCorrectionFile","") );
184 if(m_insituCombMassConfig.empty()) ATH_MSG_ERROR("Please check there is a combination config");
185 for(unsigned int i=0;i<m_insituCombMassConfig.size();++i){
186
187 std::string configPath_comb = dir+m_insituCombMassConfig.at(i).Data(); // Full path
188 TString fn_comb = PathResolverFindCalibFile(configPath_comb);
189
190 ATH_MSG_INFO("Reading combination settings from: " << m_insituCombMassConfig.at(i));
191 ATH_MSG_INFO("resolved in: " << fn_comb);
192
193 TEnv *globalInsituCombMass = new TEnv();
194 int status = globalInsituCombMass->ReadFile(fn_comb ,EEnvLevel(0));
195 if (status!=0) { ATH_MSG_FATAL("Cannot read config file " << fn_comb ); return StatusCode::FAILURE; }
196 m_globalInsituCombMassConfig.push_back(globalInsituCombMass);
197 }
198 }
199
200 //Loop over the request calib sequence
201 //Initialize derived classes for applying the requested calibrations and add them to a vector
202 std::vector<TString> vecCalibSeq = JetCalibUtils::Vectorize(calibSeq,"_");
203 for ( unsigned int i=0; i<vecCalibSeq.size(); ++i) {
204 if ( vecCalibSeq[i].EqualTo("Origin") || vecCalibSeq[i].EqualTo("DEV") ) continue;
205 if ( vecCalibSeq[i].EqualTo("Residual") && m_doJetArea ) continue;
206 ATH_CHECK( getCalibClass(vecCalibSeq[i] ));
207 }
208
209 // Initialise ReadHandle(s)
210 ATH_CHECK( m_evtInfoKey.initialize() );
211 ATH_CHECK( m_muKey.initialize() );
212 ATH_CHECK( m_actualMuKey.initialize() );
213 ATH_CHECK( m_rhoKey.initialize(requireRhoInput) );
214 if(m_pvKey.empty()) {
215 // No PV key: -- check if it is required
216 if(m_doResidual) {
217 // May require modification in case of residual that does not require NPV
218 ATH_MSG_ERROR("Residual calibration requested but no primary vertex container specified!");
219 return StatusCode::FAILURE;
220 }
221 else if(m_doGSC) {
222 if(m_jetAlgo.find("PFlow")!=std::string::npos) {
223 ATH_MSG_ERROR("GSC calibration for PFlow requested but no primary vertex container specified!");
224 return StatusCode::FAILURE;
225 }
226 else if((m_gscDepth!="Tile0" && m_gscDepth!="EM3")) {
227 ATH_MSG_ERROR("GSC calibration with tracks requested but no primary vertex container specified!");
228 return StatusCode::FAILURE;
229 }
230 }
231 } else {
232 // Received a PV key, declare the data dependency
233 ATH_CHECK( m_pvKey.initialize() );
234 }
235 return StatusCode::SUCCESS;
236}
237
238//Method for initializing the requested calibration derived classes
239StatusCode JetCalibrationTool::getCalibClass(const TString& calibration) {
240 TString jetAlgo = m_jetAlgo;
241 const TString calibPath = "CalibArea-" + m_calibAreaTag + "/";
242 bool ok{true};
243 // Metadata needed to configure some corrections
244 TString generatorsInfo{};
245 TString simFlavour{};
246 float mcDSID{-1.0};
247 TString mcCampaign{};
248 if ( inputMetaStore()->contains<xAOD::FileMetaData>("FileMetaData") ) {
249 const xAOD::FileMetaData *fmd = nullptr;
250 ATH_CHECK(inputMetaStore()->retrieve(fmd,"FileMetaData") );
251
252 if(m_isData){
253 UInt_t dataYear = 0;
254 ok &= fmd->value(xAOD::FileMetaData::dataYear, dataYear);
255 if (dataYear >= 2015 && dataYear <= 2018) {
256 mcCampaign = "MC20";
257 } else if (dataYear >= 2022 && dataYear <= 2024) {
258 mcCampaign = "MC23";
259 } else {
260 ATH_MSG_VERBOSE("Data year " << dataYear << " not recognized from file metadata. The corresponding mcCampaign will not be known.");
261 }
262
263 } else { // is MC
264 std::string str_generatorsInfo;
265 ok &= fmd->value(xAOD::FileMetaData::generatorsInfo, str_generatorsInfo);
266 generatorsInfo = str_generatorsInfo;
267
268 std::string str_simFlavour;
269 ok &= fmd->value(xAOD::FileMetaData::simFlavour, str_simFlavour);
270 simFlavour = str_simFlavour;
271
272 ok &= fmd->value(xAOD::FileMetaData::mcProcID, mcDSID);
273
274 std::string str_mcCampaign;
275 ok &= fmd->value(xAOD::FileMetaData::mcCampaign, str_mcCampaign);
276 str_mcCampaign.resize(4); //Only keep top-level of campaign (e.g. mc20 or mc23)
277 mcCampaign = str_mcCampaign;
278 mcCampaign.ToUpper();
279 if(mcDSID){
280 ATH_MSG_INFO("Have loaded metadata mcDSID:" << mcDSID << ", generatorsInfo: " << generatorsInfo << ", mcCampaign: " << mcCampaign << ", simFlavour: " << simFlavour);
281 }
282 }
283 }
284 if (not ok){
285 ATH_MSG_DEBUG("Some values in FileMetaData returned false for 'value()'.");
286 }
287 // Force the MCCampaign (or data equivalent) for missing Metadata or tests
288 if( m_forceCampaign != "" ){
289 mcCampaign = m_forceCampaign;
290 }
291
292 if ( calibration.EqualTo("Bcid") ){
293 m_globalConfig->SetValue("PileupStartingScale","JetBcidScaleMomentum");
294 std::unique_ptr<JetCalibrationStep> bcidCorr = std::make_unique<BcidOffsetCorrection>(this->name()+"_Bcid", m_globalConfig, jetAlgo, calibPath, m_isData);
295 ATH_CHECK(bcidCorr->initialize());
296 m_calibSteps.push_back(std::move(bcidCorr));
297 return StatusCode::SUCCESS;
298 }
299 else if ( calibration.EqualTo("JetArea") || calibration.EqualTo("Residual") ) {
300 std::unique_ptr<JetCalibrationStep> puCorr = std::make_unique<JetPileupCorrection>(this->name()+"_Pileup", m_globalConfig, jetAlgo, calibPath,
302 puCorr->msg().setLevel( this->msg().level() );
303 ATH_CHECK(puCorr->initialize());
304 m_calibSteps.push_back(std::move(puCorr));
305 return StatusCode::SUCCESS;
306 }
307 else if ( calibration.EqualTo("EtaJES") || calibration.EqualTo("AbsoluteEtaJES") ) {
308 std::unique_ptr<JetCalibrationStep> etaJESCorr = std::make_unique<EtaJESCorrection>(this->name()+"_EtaJES", m_globalConfig, jetAlgo, calibPath, false, m_devMode);
309 etaJESCorr->msg().setLevel( this->msg().level() );
310 ATH_CHECK(etaJESCorr->initialize());
311 m_calibSteps.push_back(std::move(etaJESCorr));
312 return StatusCode::SUCCESS;
313 }
314 else if ( calibration.EqualTo("EtaMassJES") ) {
315 std::unique_ptr<JetCalibrationStep> etaJESCorr = std::make_unique<EtaJESCorrection>(this->name()+"_EtaMassJES", m_globalConfig, jetAlgo, calibPath, true, m_devMode);
316 etaJESCorr->msg().setLevel( this->msg().level() );
317 ATH_CHECK(etaJESCorr->initialize());
318 m_calibSteps.push_back(std::move(etaJESCorr));
319 return StatusCode::SUCCESS;
320 }
321 else if ( calibration.EqualTo("GSC") ) {
322 std::unique_ptr<JetCalibrationStep> gsc = std::make_unique<GlobalSequentialCorrection>(this->name()+"_GSC", m_globalConfig, jetAlgo, m_gscDepth, calibPath, m_useOriginVertex, m_devMode);
323 gsc->msg().setLevel( this->msg().level() );
324 ATH_CHECK(gsc->initialize());
325 m_calibSteps.push_back(std::move(gsc));
326
327 // Set devMode paths for the following corrections
328 TString actualCalibPath;
329 if(m_devMode){
330 actualCalibPath = "JetCalibTools/";
331 } else {
332 actualCalibPath = "JetCalibTool/CalibArea-" + m_calibAreaTag + "/";
333 }
334 // Additional FastSim and PtResidual patches happen after GSC
335 bool do_FastSim = m_globalConfig->GetValue("JPS_FastSim.doCalibration", false) || (m_forceCalibFile_FastSim != "");
336 if(m_isData and do_FastSim){
337 ATH_MSG_WARNING("JPS_FastSim.doCalibration is set in JetCalibrationTool config but isData is set to true. Will turn off FastSim calibration.");
338 do_FastSim = false;
339 }
340 if(do_FastSim){
341 if ( (m_forceCalibFile_FastSim == "") && !inputMetaStore()->contains<xAOD::FileMetaData>("FileMetaData") ) {
342 ATH_MSG_FATAL("JPS_FastSim.doCalibration is set in JetCalibrationTool config but file has no FileMetaData. Please fix the sample or configuration.");
343 return StatusCode::FAILURE;
344 }
345 std::unique_ptr<JetCalibrationStep> JPS_FastSim = std::make_unique<Generic4VecCorrection>(this->name()+"_FastSim", m_globalConfig, jetAlgo, actualCalibPath, m_forceCalibFile_FastSim, Generic4VecCorrection::JET_CORRTYPE::FASTSIM, mcCampaign, simFlavour);
346 JPS_FastSim->msg().setLevel( this->msg().level() );
347 ATH_CHECK(JPS_FastSim->initialize());
348 m_calibSteps.push_back(std::move(JPS_FastSim));
349 }
350 bool do_PtResidual = m_globalConfig->GetValue("JPS_PtResidual.doCalibration", false) || (m_forceCalibFile_PtResidual != "");
351 if(do_PtResidual){
352 std::unique_ptr<JetCalibrationStep> JPS_PtResidual = std::make_unique<Generic4VecCorrection>(this->name()+"_PtResidual", m_globalConfig, jetAlgo, actualCalibPath, m_forceCalibFile_PtResidual, Generic4VecCorrection::JET_CORRTYPE::PTRESIDUAL, mcCampaign);
353 JPS_PtResidual->msg().setLevel( this->msg().level() );
354 ATH_CHECK(JPS_PtResidual->initialize());
355 m_calibSteps.push_back(std::move(JPS_PtResidual));
356 }
357 return StatusCode::SUCCESS;
358 }
359 else if ( calibration.EqualTo("GNNC") ) {
360 std::unique_ptr<JetCalibrationStep> gnnc = std::make_unique<GlobalNNCalibration>(this->name()+"_GNNC",m_globalConfig,jetAlgo,calibPath,m_devMode);
361 gnnc->msg().setLevel( this->msg().level() );
362 ATH_CHECK(gnnc->initialize());
363 m_calibSteps.push_back(std::move(gnnc));
364 return StatusCode::SUCCESS;
365 }
366 else if ( calibration.EqualTo("MC2MC") ) {
367 // Set devMode paths for this correction
368 TString actualCalibPath;
369 if(m_devMode){
370 actualCalibPath = "JetCalibTools/";
371 } else {
372 actualCalibPath = "JetCalibTool/CalibArea-" + m_calibAreaTag + "/";
373 }
374 if ( !inputMetaStore()->contains<xAOD::FileMetaData>("FileMetaData") && (m_forceCalibFile_MC2MC == "") ) {
375 ATH_MSG_FATAL("MC2MC step of jet calibration is requested but file has no FileMetaData. Please fix the sample or configuration.");
376 return StatusCode::FAILURE;
377 }
378 std::unique_ptr<JetCalibrationStep> JPS_MC2MC = std::make_unique<Generic4VecCorrection>(this->name()+"_MC2MC", m_globalConfig, jetAlgo, actualCalibPath, m_forceCalibFile_MC2MC, Generic4VecCorrection::JET_CORRTYPE::MC2MC, mcCampaign, simFlavour, (int) mcDSID, generatorsInfo);
379 JPS_MC2MC->msg().setLevel( this->msg().level() );
380 ATH_CHECK(JPS_MC2MC->initialize());
381 m_calibSteps.push_back(std::move(JPS_MC2MC));
382 return StatusCode::SUCCESS;
383 }
384 else if ( calibration.EqualTo("JMS") ) {
385 std::unique_ptr<JetCalibrationStep> jetMassCorr = std::make_unique<JMSCorrection>(this->name()+"_JMS", m_globalConfig, jetAlgo, calibPath, m_devMode);
386 jetMassCorr->msg().setLevel( this->msg().level() );
387 ATH_CHECK(jetMassCorr->initialize());
388 m_calibSteps.push_back(std::move(jetMassCorr));
389 return StatusCode::SUCCESS;
390 }
391 else if ( calibration.EqualTo("InsituCombinedMass") ){
392 for(unsigned int i=0;i<m_insituCombMassConfig.size();++i){
393 std::unique_ptr<JetCalibrationStep> jetMassCorr = std::make_unique<JMSCorrection>(this->name()+"_InsituCombinedMass", m_globalInsituCombMassConfig.at(i), jetAlgo, calibPath, m_devMode);
394 jetMassCorr->msg().setLevel( this->msg().level() );
395 ATH_CHECK(jetMassCorr->initialize());
396 m_calibSteps.push_back(std::move(jetMassCorr));
397 }
398 return StatusCode::SUCCESS;
399 }
400 else if ( calibration.EqualTo("Insitu") ) {
402 std::unique_ptr<JetCalibrationStep> insituDataCorr = std::make_unique<InsituDataCorrection>(this->name()+"_Insitu", m_globalConfig, jetAlgo, calibPath, m_devMode);
403 insituDataCorr->msg().setLevel( this->msg().level() );
404 ATH_CHECK(insituDataCorr->initialize());
405 m_calibSteps.push_back(std::move(insituDataCorr));
406 return StatusCode::SUCCESS;
407 }
408 else{
409 ATH_MSG_INFO("Initializing Time-Dependent Insitu Corrections");
410 for(unsigned int i=0;i<m_timeDependentInsituConfigs.size();++i){
411 // Add 0.5 before casting to avoid floating-point precision issues
412 unsigned int firstRun = static_cast<unsigned int>(m_runBins.at(i)+1.5);
413 unsigned int lastRun = static_cast<unsigned int>(m_runBins.at(i+1)+0.5);
414 std::unique_ptr<JetCalibrationStep> insituDataCorr = std::make_unique<InsituDataCorrection>(this->name()+"_Insitu_"+std::to_string(i), m_globalTimeDependentConfigs.at(i), jetAlgo,
415 calibPath, m_devMode, firstRun, lastRun);
416 insituDataCorr->msg().setLevel( this->msg().level() );
417 ATH_CHECK(insituDataCorr->initialize());
418 m_calibSteps.push_back(std::move(insituDataCorr));
419 }
420 return StatusCode::SUCCESS;
421 }
422 }
423 else if ( calibration.EqualTo("Smear") ) {
424 if(m_isData){
425 ATH_MSG_FATAL("Asked for smearing of data, which is not supported. Aborting.");
426 return StatusCode::FAILURE;
427 }
428 std::unique_ptr<JetCalibrationStep> jetSmearCorr = std::make_unique<JetSmearingCorrection>(this->name()+"_Smear", m_globalConfig,jetAlgo,calibPath,m_devMode);
429 jetSmearCorr->msg().setLevel(this->msg().level());
430 ATH_CHECK(jetSmearCorr->initialize());
431 m_calibSteps.push_back(std::move(jetSmearCorr));
432 m_smearIndex = m_calibSteps.size() - 1;
433 return StatusCode::SUCCESS;
434 }
435 else if ( calibration.EqualTo("LargeRDNN") ) {
436 std::unique_ptr<JetCalibrationStep> largeR_dnn = std::make_unique<GlobalLargeRDNNCalibration>(this->name()+"_R10DNN", m_globalConfig,calibPath,m_devMode);
437 largeR_dnn->msg().setLevel(this->msg().level());
438 ATH_CHECK(largeR_dnn->initialize());
439 m_calibSteps.push_back(std::move(largeR_dnn));
440 return StatusCode::SUCCESS;
441 }
442 ATH_MSG_FATAL("Calibration string not recognized: " << calibration << ", aborting.");
443 return StatusCode::FAILURE;
444}
445
447 //Grab necessary event info for pile up correction and store it in a JetEventInfo class object
448 ATH_MSG_VERBOSE("Modifying jet collection.");
449 JetEventInfo jetEventInfo;
450 ATH_CHECK( initializeEvent(jetEventInfo) );
451 for (xAOD::Jet* jet : jets) ATH_CHECK( calibrate(*jet, jetEventInfo) );
452 return StatusCode::SUCCESS;
453}
454
455// Private/Protected Methods
457
458StatusCode JetCalibrationTool::initializeEvent(JetEventInfo& jetEventInfo) const {
459
460 // Check if the tool was initialized
461 if( m_calibSteps.empty() ){
462 ATH_MSG_FATAL(" JetCalibrationTool::initializeEvent : The tool was not initialized.");
463 return StatusCode::FAILURE;
464 }
465
466 // static accessor for PV index access
467 static const SG::ConstAccessor<int> PVIndexAccessor("PVIndex");
468
469 ATH_MSG_VERBOSE("Initializing event.");
470
471 if( m_doJetArea ) {
472 //Determine the rho value to use for the jet area subtraction
473 //Should be determined using EventShape object, use hard coded values if EventShape doesn't exist
474 double rho=0;
475 const xAOD::EventShape * eventShape = nullptr;
476
478
479 if ( rhRhoKey.isValid() ) {
480 ATH_MSG_VERBOSE(" Found event density container " << m_rhoKey.key());
481 eventShape = rhRhoKey.cptr();
482 if ( !rhRhoKey.isValid() ) {
483 ATH_MSG_VERBOSE(" Event shape container not found.");
484 ATH_MSG_FATAL("Could not retrieve the xAOD::EventShape container " << m_rhoKey.key() << " from the input file");
485 return StatusCode::FAILURE;
486 } else if ( !eventShape->getDensity( xAOD::EventShape::Density, rho ) ) {
487 ATH_MSG_VERBOSE(" Event density not found in container.");
488 ATH_MSG_FATAL("Could not retrieve the xAOD::EventShape::Density variable from " << m_rhoKey.key());
489 return StatusCode::FAILURE;
490 } else {
491 ATH_MSG_VERBOSE(" Event density retrieved.");
492 }
493 } else if ( m_doJetArea && !rhRhoKey.isValid() ) {
494 ATH_MSG_VERBOSE(" Rho container not found: " << m_rhoKey.key());
495 ATH_MSG_FATAL("Could not retrieve xAOD::EventShape container " << m_rhoKey.key() << " from the input file");
496 return StatusCode::FAILURE;
497 }
498 jetEventInfo.setRho(rho);
499 ATH_MSG_VERBOSE(" Rho = " << 0.001*rho << " GeV");
500
501 // Necessary retrieval and calculation for use of nJetX instead of NPV
503 // retrieve the container
504 const xAOD::JetContainer * jets = nullptr;
506 ATH_MSG_VERBOSE(" Found jet container " << m_nJetContainerName);
507 if ( evtStore()->retrieve(jets, m_nJetContainerName).isFailure() || !jets ) {
508 ATH_MSG_FATAL("Could not retrieve xAOD::JetContainer " << m_nJetContainerName << " from evtStore");
509 return StatusCode::FAILURE;
510 }
511 } else {
512 ATH_MSG_FATAL("Could not find jet container " << m_nJetContainerName << " in the evtStore");
513 return StatusCode::FAILURE;
514 }
515
516 // count jets above threshold
517 int nJets = 0;
518 for (const auto *jet : *jets) {
519 if(jet->pt()/1000. > m_nJetThreshold)
520 nJets += 1;
521 }
522 jetEventInfo.setNjet(nJets);
523 }
524 }
525
526 // Retrieve EventInfo object, which now has multiple uses
528 const xAOD::EventInfo * eventObj = nullptr;
529 static std::atomic<unsigned int> eventInfoWarnings = 0;
531 if ( rhEvtInfo.isValid() ) {
532 eventObj = rhEvtInfo.cptr();
533 } else {
534 ++eventInfoWarnings;
535 if ( eventInfoWarnings < 20 )
536 ATH_MSG_ERROR(" JetCalibrationTool::initializeEvent : Failed to retrieve event information.");
537 jetEventInfo.setMu(0); //Hard coded value mu = 0 in case of failure (to prevent seg faults later).
538 jetEventInfo.setPVIndex(0);
539 return StatusCode::SUCCESS; //error is recoverable, so return SUCCESS
540 }
541 jetEventInfo.setRunNumber( eventObj->runNumber() );
542
543 // If we are applying the reisdual, then store mu
544 if (m_doResidual || m_doBcid) {
546 if(!eventInfoDecor.isPresent()) {
547 ATH_MSG_ERROR("EventInfo decoration not available!");
548 return StatusCode::FAILURE;
549 }
550 jetEventInfo.setMu( eventInfoDecor(0) );
551 }
552
553 // If this is GSC, we need EventInfo to determine the PV to use
554 // This is support for groups where PV0 is not the vertex of interest (H->gamgam, etc)
555 if (m_doGSC)
556 {
557 // First retrieve the PVIndex if specified
558 // Default is to not specify this, so no warning if it doesn't exist
559 // However, if specified, it should be a sane value - fail if not
560 if ( m_doGSC && PVIndexAccessor.isAvailable(*eventObj) )
561 jetEventInfo.setPVIndex( PVIndexAccessor(*eventObj) );
562 else{
563 if(!m_pvKey.empty()){
564 const xAOD::VertexContainer * vertices = nullptr;
566 if (rhPV.isValid()) {
567 vertices = rhPV.cptr();
568 xAOD::VertexContainer::const_iterator vtx_itr = vertices->begin();
569 xAOD::VertexContainer::const_iterator vtx_end = vertices->end();
570 for ( ; vtx_itr != vtx_end; ++vtx_itr ){
571 if ( (*vtx_itr)->vertexType() == xAOD::VxType::PriVtx ){
572 jetEventInfo.setPVIndex((*vtx_itr)->index());
573 break;
574 }
575 }
576 }
577 else{
578 jetEventInfo.setPVIndex(0);
579 }
580 }
581 else{
582 jetEventInfo.setPVIndex(0);
583 }
584 }
585 }
586
587 // Extract the BCID information for the BCID correction
588 if (m_doBcid)
589 {
590 static const SG::ConstAccessor<int> BCIDDistanceFromFrontAcc ("DFCommonJets_BCIDDistanceFromFront");
591 static const SG::ConstAccessor<int> BCIDGapBeforeTrainAcc ("DFCommonJets_BCIDGapBeforeTrain");
592 static const SG::ConstAccessor<int> BCIDGapBeforeTrainMinus12Acc ("DFCommonJets_BCIDGapBeforeTrainMinus12");
593
594 jetEventInfo.setBcidDistanceFromFront( BCIDDistanceFromFrontAcc (*eventObj) );
595 jetEventInfo.setBcidGapBeforeTrain( BCIDGapBeforeTrainAcc (*eventObj) );
596 jetEventInfo.setBcidGapBeforeTrainMinus12( BCIDGapBeforeTrainMinus12Acc (*eventObj) );
597 }
598
599 // If PV index is not zero, we need to confirm it's a reasonable value
600 // To do this, we need the primary vertices
601 // However, other users of the GSC may not have the PV collection (in particular: trigger GSC in 2016)
602 // So only retrieve vertices if needed for NPV (residual) or a non-zero PV index was specified (GSC)
603 if ((m_doResidual && !m_useNjetInResidual) || (m_doGSC && jetEventInfo.PVIndex()))
604 {
605 //Retrieve VertexContainer object, use it to obtain NPV for the residual correction or check validity of GSC non-PV0 usage
606 const xAOD::VertexContainer * vertices = nullptr;
607
609 if (rhPV.isValid()) {
610 vertices = rhPV.cptr();
611 } else {
612 ATH_MSG_WARNING(" JetCalibrationTool::initializeEvent : Failed to retrieve primary vertices.");
613 jetEventInfo.setNPV(0); //Hard coded value NPV = 0 in case of failure (to prevent seg faults later).
614 return StatusCode::SUCCESS; //error is recoverable, so return SUCCESS
615 }
616
617 // Calculate and set NPV if this is residual
618 if (m_doResidual)
619 {
620 int eventNPV = 0;
621 eventNPV = std::count_if(vertices->begin(), vertices->end(), [](const xAOD::Vertex* vtx){ return vtx->vertexType() == xAOD::VxType::PileUp || vtx->vertexType() == xAOD::VxType::PriVtx;});
622 jetEventInfo.setNPV(eventNPV);
623 }
624
625 // Validate value of non-standard PV index usage
626 if (m_doGSC && jetEventInfo.PVIndex())
627 {
628 static std::atomic<unsigned int> vertexIndexWarnings = 0;
629 if (jetEventInfo.PVIndex() < 0 || static_cast<size_t>(jetEventInfo.PVIndex()) >= vertices->size())
630 {
631 ++vertexIndexWarnings;
632 if (vertexIndexWarnings < 20)
633 ATH_MSG_WARNING(" JetCalibrationTool::initializeEvent : PV index is out of bounds.");
634 jetEventInfo.setPVIndex(0); // Hard coded value PVIndex = 0 in case of failure (to prevent seg faults later).
635 return StatusCode::SUCCESS; // error is recoverable, so return SUCCESS
636 }
637 }
638 }
639 } else if (m_doDNNCal) {
640 // retrieve mu and NPV only from eventInfo
641 static std::atomic<unsigned int> eventInfoWarningsMu = 0;
643 if ( rhEvtInfo.isValid() ) {
645 jetEventInfo.setMu(eventInfoDecor(0));
646 } else {
647 ++eventInfoWarningsMu;
648 if ( eventInfoWarningsMu < 20 ) ATH_MSG_WARNING(" JetCalibrationTool::initializeEvent : Failed to retrieve event information.");
649 jetEventInfo.setMu(0); //Hard coded value mu = 0 in case of failure (to prevent seg faults later).
650 }
651
652 static std::atomic<unsigned int> eventInfoWarningsPV = 0;
653 const xAOD::VertexContainer * vertices = nullptr;
655 if (rhPV.isValid()) {
656 vertices = rhPV.cptr();
657 int eventNPV = 0;
658 eventNPV = std::count_if(vertices->begin(), vertices->end(), [](const xAOD::Vertex* vtx){ return vtx->vertexType() == xAOD::VxType::PileUp || vtx->vertexType() == xAOD::VxType::PriVtx;});
659 jetEventInfo.setNPV(eventNPV);
660 } else {
661 ++eventInfoWarningsPV;
662 if ( eventInfoWarningsPV < 20 ) ATH_MSG_WARNING(" JetCalibrationTool::initializeEvent : Failed to retrieve primary vertices.");
663 jetEventInfo.setNPV(0); //Hard coded value NPV = 0 in case of failure (to prevent seg faults later).
664 }
665 }
666 return StatusCode::SUCCESS;
667}
668
669StatusCode JetCalibrationTool::calibrate(xAOD::Jet& jet, JetEventInfo& jetEventInfo) const {
670
671 //Check for OriginCorrected and PileupCorrected attributes, assume they are false if not found
672 int tmp = 0; //temporary int for checking getAttribute
673 if ( !jet.getAttribute<int>("OriginCorrected",tmp) )
674 jet.setAttribute<int>("OriginCorrected",false);
675 if ( !jet.getAttribute<int>("PileupCorrected",tmp) )
676 jet.setAttribute<int>("PileupCorrected",false);
677
678 ATH_MSG_VERBOSE("Calibrating jet " << jet.index());
680 xAOD::JetFourMom_t jetconstitP4 = jet.getAttribute<xAOD::JetFourMom_t>("JetConstitScaleMomentum");
681 jet.setAttribute<float>("DetectorEta",jetconstitP4.eta()); //saving constituent scale eta for later use
682 }
683
684 for (unsigned int i=0; i<m_calibSteps.size(); ++i) ATH_CHECK(m_calibSteps[i]->calibrate(jet, jetEventInfo));
685
686 return StatusCode::SUCCESS;
687}
688
689
690StatusCode JetCalibrationTool::getNominalResolutionData(const xAOD::Jet& jet, double& resolution) const{
691
692 if(m_smearIndex < 0){
693 ATH_MSG_ERROR("Requested jet resolution without a smearing step in the CalibSequence!");
694 return StatusCode::FAILURE;
695 }
696 return m_calibSteps.at(m_smearIndex)->getNominalResolutionData(jet, resolution);
697}
698
699StatusCode JetCalibrationTool::getNominalResolutionMC(const xAOD::Jet& jet, double& resolution) const{
700
701 if(m_smearIndex < 0){
702 ATH_MSG_ERROR("Requested jet resolution without a smearing step in the CalibSequence!");
703 return StatusCode::FAILURE;
704 }
705 return m_calibSteps.at(m_smearIndex)->getNominalResolutionMC(jet, resolution);
706}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Handle class for reading a decoration on an object.
Helper class to provide constant type-safe access to aux data.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:861
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
JetCalibrationTool(const std::string &name="JetCalibrationTool")
Constructor with parameters:
std::vector< double > m_runBins
std::vector< TString > m_timeDependentInsituConfigs
SG::ReadHandleKey< xAOD::EventInfo > m_evtInfoKey
StatusCode calibrate(xAOD::Jet &jet, JetEventInfo &jetEventInfo) const
SG::ReadDecorHandleKey< xAOD::EventInfo > m_muKey
std::vector< TString > m_insituCombMassConfig
SG::ReadHandleKey< xAOD::EventShape > m_rhoKey
SG::ReadHandleKey< xAOD::VertexContainer > m_pvKey
std::vector< TEnv * > m_globalTimeDependentConfigs
std::vector< std::unique_ptr< JetCalibrationStep > > m_calibSteps
StatusCode initialize() override
Dummy implementation of the initialisation function.
std::string m_forceCalibFile_FastSim
StatusCode getNominalResolutionData(const xAOD::Jet &jet, double &resolution) const override
std::string m_forceCalibFile_PtResidual
StatusCode initializeEvent(JetEventInfo &jetEventInfo) const
StatusCode applyCalibration(xAOD::JetContainer &) const override
Apply calibration to a jet container.
std::string m_forceCalibFile_MC2MC
StatusCode getNominalResolutionMC(const xAOD::Jet &jet, double &resolution) const override
StatusCode getCalibClass(const TString &calibration)
~JetCalibrationTool()
Destructor:
std::string m_nJetContainerName
SG::ReadDecorHandleKey< xAOD::EventInfo > m_actualMuKey
std::vector< TEnv * > m_globalInsituCombMassConfig
void setBcidDistanceFromFront(Int_t BcidDistanceFromFront)
void setRho(double rho)
void setBcidGapBeforeTrainMinus12(Int_t BcidGapBeforeTrainMinus12)
void setMu(double mu)
void setPVIndex(int PVindex)
void setRunNumber(UInt_t RunNumber)
void setBcidGapBeforeTrain(Int_t BcidGapBeforeTrain)
void setNjet(double nJet)
void setNPV(double NPV)
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
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?
const_pointer_type cptr()
Dereference the pointer.
AsgMetadataTool(const std::string &name)
Normal ASG tool constructor with a name.
MetaStorePtr_t inputMetaStore() const
Accessor for the input metadata store.
uint32_t runNumber() const
The current event's run number.
bool getDensity(EventDensityID id, double &v) const
Get a density variable from the object.
@ mcProcID
Same as mc_channel_number [float].
@ generatorsInfo
Generators information [string].
@ mcCampaign
MC campaign [string].
@ dataYear
Data year [uint32_t].
@ simFlavour
Fast or Full sim [string].
bool value(MetaDataType type, std::string &val) const
Get a pre-defined string value out of the object.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:116
StrV Vectorize(const TString &str, const TString &sep=" ")
VecD VectorizeD(const TString &str, const TString &sep=" ")
@ PriVtx
Primary vertex.
Jet_v1 Jet
Definition of the current "jet version".
EventInfo_v1 EventInfo
Definition of the latest event info version.
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
EventShape_v1 EventShape
Definition of the current event format version.
Definition EventShape.h:16
FileMetaData_v1 FileMetaData
Declare the latest version of the class.
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
MsgStream & msg
Definition testRead.cxx:32