ATLAS Offline Software
Loading...
Searching...
No Matches
JMSCorrection.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5/*
6 * JMS Calibration
7 *
8 * Author: Jonathan Bossio (jbossios@cern.ch)
9 *
10 */
11
16#include <TAxis.h>
17#include <TEnv.h>
18#include <TFile.h>
19#include <TKey.h>
20#include <cmath>
21#include <utility>
22
27
28
29JMSCorrection::JMSCorrection(const std::string& name, TEnv* config, TString jetAlgo, TString calibAreaTag, bool dev)
31 m_config(config), m_jetAlgo(std::move(jetAlgo)), m_calibAreaTag(std::move(calibAreaTag)), m_dev(dev)
32{ }
33
35
36 ATH_MSG_INFO("Initializing the JMS Calibration tool");
37
38 if ( !m_config ) { ATH_MSG_FATAL("Config file not specified. Aborting."); return StatusCode::FAILURE; }
39
40 m_jetStartScale = m_config->GetValue("JMSStartingScale","JetEtaJESScaleMomentum");
41 m_jetOutScale = m_config->GetValue("JMSOutScale","JetJMSScaleMomentum");
42 // Starting pT value to calibrate
43 m_pTMinCorr = m_config->GetValue("MinpT",180);
44
45 m_pTfixed = m_config->GetValue("pTfixed",false); //small-R:true, large-R:false
46
47 if ( m_jetAlgo.EqualTo("") ) { ATH_MSG_FATAL("No jet algorithm specified. Aborting."); return StatusCode::FAILURE; }
48
49
50 // Check if we are reading 2D histograms (one per eta bin) or 3D histograms
51 // 3D histograms allow for interpolation also across the eta dimension
52 // Defaults to "false" (use 2D) for backwards compatibility
53 // *Note* that it is assumed the calo and TA masses use the same histogram dimensionality
54 m_use3Dhisto = m_config->GetValue("MassCalibrationIs3D",false);
55
56 // Should the mass combination be applied?
57 m_combination = m_config->GetValue("Combination",false); // true: turn on combination of calo mass with track-assisted mass
58 m_useCorrelatedWeights = m_config->GetValue("UseCorrelatedWeights",false); // true: turn on combination of calo mass with track-assisted mass
59 // Should we only apply the combination (e.g after in situ calibration)
60 m_onlyCombination = m_config->GetValue("OnlyCombination",false);
61
62 //find the ROOT file containing response histograms, path comes from the config file.
63 TString JMSFile;
64
66 JMSFile = m_config->GetValue("MassCalibrationFile","empty");
67 if ( JMSFile.EqualTo("empty") ) {
68 ATH_MSG_FATAL("NO JMSFactorsFile specified. Aborting.");
69 return StatusCode::FAILURE;
70 }
71 if(m_dev){
72 JMSFile.Remove(0,33);
73 JMSFile.Insert(0,"JetCalibTools/");
74 }
75 else{JMSFile.Insert(14,m_calibAreaTag);}
76 TString fileName = PathResolverFindCalibFile(JMSFile.Data());
77 std::unique_ptr<TFile> inputFile(TFile::Open(fileName));
78 if (!inputFile){
79 ATH_MSG_FATAL("Cannot open JMS factors file" << fileName);
80 return StatusCode::FAILURE;
81 }
82
83 if (!m_use3Dhisto) setMassEtaBins( JetCalibUtils::VectorizeD( m_config->GetValue("MassEtaBins","") ) );
84
85 //Get a TList of TKeys pointing to the histograms contained in the ROOT file
86 inputFile->cd();
87 TList *keys = inputFile->GetListOfKeys();
88 //fill the names of the TKeys into a vector of TStrings
89 TIter ikeys(keys);
90 while ( TKey *iterobj = (TKey*)ikeys() ) {
91 TString histoName = iterobj->GetName();
92 if ( histoName.Contains(m_jetAlgo) )
93 {
94 if (m_use3Dhisto)
95 m_respFactorMass3D = JetCalibUtils::GetHisto3(*inputFile,histoName.Data());
96 else
97 m_respFactorsMass.push_back( JetCalibUtils::GetHisto2(*inputFile,histoName.Data()) );
98 }
99 }
100
101 //Make sure we put something in the vector of TH2Fs or we filled the TH3F
102 if ( !m_use3Dhisto && m_respFactorsMass.size() < 3 ) {
103 ATH_MSG_FATAL("Vector of mass correction histograms may be empty. Please check your mass calibration file: " << JMSFile);
104 return StatusCode::FAILURE;
105 }
106 else if ( m_use3Dhisto && !m_respFactorMass3D)
107 {
108 ATH_MSG_FATAL("3D mass correction histogram may be missing. Please check your mass calibration file: " << JMSFile);
109 return StatusCode::FAILURE;
110 }
111 else ATH_MSG_DEBUG("JMS Tool has been initialized with binning and eta fit factors from: " << fileName);
112
113 // Track-Assisted Jet Mass correction
114 m_trackAssistedJetMassCorr = m_config->GetValue("TrackAssistedJetMassCorr",false);
116 ATH_MSG_DEBUG("Track Assisted Jet Mass will be calibrated");
117 TString JMS_TrackAssisted_File(m_config->GetValue("TrackAssistedMassCalibrationFile","empty"));
118 if ( JMS_TrackAssisted_File.EqualTo("empty") ) {
119 ATH_MSG_FATAL("NO Track Assisted Mass Factors File specified. Aborting.");
120 return StatusCode::FAILURE;
121 }
122 if(m_dev){
123 JMS_TrackAssisted_File.Remove(0,33);
124 JMS_TrackAssisted_File.Insert(0,"JetCalibTools/");
125 }
126 else{JMS_TrackAssisted_File.Insert(14,m_calibAreaTag);}
127 TString file_trkAssisted_Name(PathResolverFindCalibFile(JMS_TrackAssisted_File.Data()));
128 std::unique_ptr<TFile> inputFile_trkAssisted(TFile::Open(file_trkAssisted_Name));
129 if (!inputFile_trkAssisted){
130 ATH_MSG_FATAL("Cannot open Track Assisted Mass factors file" << fileName);
131 return StatusCode::FAILURE;
132 }
133
134 //Get a TList of TKeys pointing to the histograms contained in the ROOT file
135 inputFile_trkAssisted->cd();
136 TList *keys_trkAssisted = inputFile_trkAssisted->GetListOfKeys();
137 //fill the names of the TKeys into a vector of TStrings
138 TIter ikeys_trkAssisted(keys_trkAssisted);
139 while ( TKey *iterobj = (TKey*)ikeys_trkAssisted() ) {
140 TString histoName = iterobj->GetName();
141 if ( histoName.Contains(m_jetAlgo) )
142 {
143 if (m_use3Dhisto)
144 m_respFactorTrackAssistedMass3D = JetCalibUtils::GetHisto3(*inputFile_trkAssisted,histoName);
145 else
146 m_respFactorsTrackAssistedMass.push_back( JetCalibUtils::GetHisto2(*inputFile_trkAssisted,histoName) );
147 }
148 }
149
150 //Make sure we put something in the vector of TH2Fs
151 if ( !m_use3Dhisto && m_respFactorsTrackAssistedMass.size() < 3 ) {
152 ATH_MSG_FATAL("Vector of track assisted mass correction histograms may be empty. Please check your track assisted mass calibration file: " << JMSFile);
153 return StatusCode::FAILURE;
154 }
156 {
157 ATH_MSG_FATAL("3D track assisted mass correction histogram may be missing. Please check your mass calibration file: " << JMSFile);
158 return StatusCode::FAILURE;
159 }
160 else ATH_MSG_DEBUG("JMS Tool has been initialized with binning and eta fit factors from: " << file_trkAssisted_Name);
161 }
162 }
163
164 // Combination
165 if(m_combination){
166 ATH_MSG_DEBUG("Mass Combination: ON");
167 TString Combination_File(m_config->GetValue("CombinationFile","empty"));
168 if ( Combination_File.EqualTo("empty") ) {
169 ATH_MSG_FATAL("NO Combination File specified. Aborting.");
170 return StatusCode::FAILURE;
171 }
172 if(m_dev){
173 Combination_File.Remove(0,33);
174 Combination_File.Insert(0,"JetCalibTools/");
175 }
176 else{Combination_File.Insert(14,m_calibAreaTag);}
177 TString file_combination_Name(PathResolverFindCalibFile(Combination_File.Data()));
178 std::unique_ptr<TFile> inputFile_combination(TFile::Open(file_combination_Name));
179 if (!inputFile_combination){
180 ATH_MSG_FATAL("Cannot open Mass Combination file " << file_combination_Name);
181 return StatusCode::FAILURE;
182 }
183
184 if (!m_use3Dhisto)
185 setMassCombinationEtaBins( JetCalibUtils::VectorizeD( m_config->GetValue("MassCombinationEtaBins","") ) );
186
187 // Identify which object is being tagged (QCD, Top, WZ, Hbb)
188 TString combObj = "";
189 if(m_jetOutScale.Contains("QCD")) combObj = "_QCD_";
190 else if(m_jetOutScale.Contains("Top")){ combObj = "_Top_";}
191 else if(m_jetOutScale.Contains("WZ")){ combObj = "_WZ_";}
192 else if(m_jetOutScale.Contains("Hbb")){ combObj = "_WZ_";} // Temporary due to missing Hbb weights
193 if(combObj==""){
194 ATH_MSG_FATAL("Wrong JMS Outgoing Scale");
195 return StatusCode::FAILURE;
196 }
197
198 //Get a TList of TKeys pointing to the histograms contained in the ROOT file
199 inputFile_combination->cd();
200 TList *keys_combination = inputFile_combination->GetListOfKeys();
201 //fill the names of the TKeys into a vector of TStrings
202 TIter ikeys_combination(keys_combination);
203 while ( TKey *iterobj = (TKey*)ikeys_combination() ) {
204 TString histoName = iterobj->GetName();
205 if ( histoName.Contains("CaloMass") && histoName.Contains(combObj.Data()) )
206 {
207 if (!m_use3Dhisto)
208 m_caloResolutionMassCombination.push_back( JetCalibUtils::GetHisto2(*inputFile_combination,histoName) );
209 else
210 m_caloResolutionMassCombination3D = JetCalibUtils::GetHisto3(*inputFile_combination,histoName);
211 }
212 if ( histoName.Contains("TAMass") && histoName.Contains(combObj.Data()) )
213 {
214 if (!m_use3Dhisto)
215 m_taResolutionMassCombination.push_back( JetCalibUtils::GetHisto2(*inputFile_combination,histoName) );
216 else
217 m_taResolutionMassCombination3D = JetCalibUtils::GetHisto3(*inputFile_combination,histoName);
218 }
219 if ( histoName.Contains("Correlation") && histoName.Contains(combObj.Data()) )
220 {
221 if (!m_use3Dhisto)
222 m_correlationMapMassCombination.push_back( JetCalibUtils::GetHisto2(*inputFile_combination,histoName) );
223 else
224 m_correlationMapMassCombination3D = JetCalibUtils::GetHisto3(*inputFile_combination,histoName);
225 }
226 }
227
228 //Make sure we put something in the vector of TH2Ds OR filled the TH3s
230 if ( !m_use3Dhisto)
231 {
232 if ( m_caloResolutionMassCombination.empty() ) {
233 ATH_MSG_FATAL("Vector of mass combination histograms with calo factors may be empty. Please check your mass combination file: " << JMSFile);
234 return StatusCode::FAILURE;
235 }
236 else if ( m_taResolutionMassCombination.empty() ) {
237 ATH_MSG_FATAL("Vector of mass combination histograms with trk-assisted factors may be empty. Please check your mass combination file: " << JMSFile);
238 return StatusCode::FAILURE;
239 }
240 }
241 else
242 {
244 {
245 ATH_MSG_FATAL("Mass combination 3D histogram with calo factors was not filled. Please check your mass combination file: " << JMSFile);
246 return StatusCode::FAILURE;
247 }
249 {
250 ATH_MSG_FATAL("Mass combination 3D histogram with trk-assisted factors was not filled. Please check your mass combination file: " << JMSFile);
251 return StatusCode::FAILURE;
252 }
253 }
254 } //m_onlyCombination
255
256 ATH_MSG_DEBUG("JMS Tool has been initialized with mass combination weights from: " << file_combination_Name);
257
258 }//m_combination
259
260 // Determine the binning strategy
261 // History is to use pt_mass_eta, with many past config files that don't specify
262 // As such, if nothing is specified, assume pt_mass_eta
263 // If something is specified and it's not understood, then that's a failure
264 // *Note* that it is assumed the calo and TA masses use the same binning parametrization
265 TString binParamString = m_config->GetValue("JMSBinningParam","");
266 if (binParamString == "")
267 {
269 ATH_MSG_DEBUG("JMS Tool will use the implied pt_mass_eta binning strategy");
270 }
271 else
272 {
273 // Check if we recognize what was specified
274 if (!binParamString.CompareTo("pt_mass_eta",TString::kIgnoreCase))
276 else if (!binParamString.CompareTo("e_LOGmOe_eta",TString::kIgnoreCase))
278 else if (!binParamString.CompareTo("e_LOGmOet_eta",TString::kIgnoreCase))
280 else if (!binParamString.CompareTo("e_LOGmOpt_eta",TString::kIgnoreCase))
282 else if (!binParamString.CompareTo("et_LOGmOet_eta",TString::kIgnoreCase))
284 else
285 {
286 // Failed to determine what was specified
287 ATH_MSG_FATAL("JMSBinningParam was specified, but input was not understood: " << binParamString);
288 return StatusCode::FAILURE;
289 }
290 ATH_MSG_DEBUG("JMS Tool will use the " << binParamString << " binning strategy");
291 }
292
293
294
295 return StatusCode::SUCCESS;
296
297}
298
299float JMSCorrection::getMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
300{
301 const double pTMax = m_respFactorMass3D->GetXaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsX()+1);
302 const double pTMin = m_respFactorMass3D->GetXaxis()->GetBinLowEdge(1);
303 const double massMax = m_respFactorMass3D->GetYaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsY()+1);
304 const double massMin = m_respFactorMass3D->GetYaxis()->GetBinLowEdge(1);
305 const double etaMax = m_respFactorMass3D->GetZaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsZ()+1);
306 const double etaMin = m_respFactorMass3D->GetZaxis()->GetBinLowEdge(1);
307 if ( pT_uncorr >= pTMax) pT_uncorr = pTMax-1e-6; // so it fits the up-most pt-bin
308 if ( pT_uncorr <= m_pTMinCorr ) return 1; // no correction
309 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
310 if ( std::isnan(mass_uncorr)) return 1; // no correction if the input is NaN, can happen for log(X)
311 if ( mass_uncorr >= massMax ) mass_uncorr = massMax-1e-6; //so it fits the up-most m-bin
312 if ( mass_uncorr <= massMin ) mass_uncorr = massMin+1e-6; //so it fits the low-most m-bin
313 if ( eta >= etaMax) eta = etaMax-1e-6; // so it fits the up-most eta-bin
314 if ( eta <= etaMin) eta = etaMin+1e-6; // so it fits the low-most eta-bin
315
316 float mass_corr = RootHelpers::Interpolate(m_respFactorMass3D.get(),pT_uncorr,mass_uncorr,eta);
317
318 return mass_corr;
319}
320
321float JMSCorrection::getMassCorr(double pT_uncorr, double mass_uncorr, int etabin) const {
322
323 // Asymptotic values
324 const double pTMax = m_respFactorsMass[etabin]->GetXaxis()->GetBinLowEdge(m_respFactorsMass[etabin]->GetNbinsX()+1);
325 const double pTMin = m_respFactorsMass[etabin]->GetXaxis()->GetBinLowEdge(1);
326 const double massMax = m_respFactorsMass[etabin]->GetYaxis()->GetBinLowEdge(m_respFactorsMass[etabin]->GetNbinsY()+1);
327 const double massMin = m_respFactorsMass[etabin]->GetYaxis()->GetBinLowEdge(1);
328 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
329 if ( pT_uncorr <= m_pTMinCorr ) return 1; // no correction
330 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
331 if ( std::isnan(mass_uncorr)) return 1; // no correction if the input is NaN, can happen for log(X)
332 if ( mass_uncorr >= massMax ) mass_uncorr = massMax-1e-6; //so it fits the up-most m-bin
333 if ( mass_uncorr <= massMin ) mass_uncorr = massMin+1e-6; //so it fits the low-most m-bin
334
335 float mass_corr = m_respFactorsMass[etabin]->Interpolate( pT_uncorr, mass_uncorr );
336
337 return mass_corr;
338}
339
340float JMSCorrection::getTrackAssistedMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
341{
342 const double pTMax = m_respFactorTrackAssistedMass3D->GetXaxis()->GetBinLowEdge(m_respFactorTrackAssistedMass3D->GetNbinsX()+1);
343 const double pTMin = m_respFactorTrackAssistedMass3D->GetXaxis()->GetBinLowEdge(1);
344 const double massMax = m_respFactorTrackAssistedMass3D->GetYaxis()->GetBinLowEdge(m_respFactorTrackAssistedMass3D->GetNbinsY()+1);
345 const double massMin = m_respFactorTrackAssistedMass3D->GetYaxis()->GetBinLowEdge(1);
346 const double etaMax = m_respFactorTrackAssistedMass3D->GetZaxis()->GetBinLowEdge(m_respFactorTrackAssistedMass3D->GetNbinsZ()+1);
347 const double etaMin = m_respFactorTrackAssistedMass3D->GetZaxis()->GetBinLowEdge(1);
348 if ( pT_uncorr >= pTMax) pT_uncorr = pTMax-1e-6; // so it fits the up-most pt-bin
349 if ( pT_uncorr <= m_pTMinCorr ) return 1; // no correction
350 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
351 if ( std::isnan(mass_uncorr)) return 1; // no correction if the input is NaN, can happen for log(X)
352 if ( mass_uncorr >= massMax ) mass_uncorr = massMax-1e-6; //so it fits the up-most m-bin
353 if ( mass_uncorr <= massMin ) mass_uncorr = massMin+1e-6; //so it fits the low-most m-bin
354 if ( eta >= etaMax) eta = etaMax-1e-6; // so it fits the up-most eta-bin
355 if ( eta <= etaMin) eta = etaMin+1e-6; // so it fits the low-most eta-bin
356
357 float mass_corr = RootHelpers::Interpolate(m_respFactorTrackAssistedMass3D.get(),pT_uncorr,mass_uncorr,eta);
358
359 return mass_corr;
360}
361
362float JMSCorrection::getTrackAssistedMassCorr(double pT_uncorr, double uncorr, int etabin) const {
363
364 // Asymptotic values
365 const double pTMax = m_respFactorsTrackAssistedMass[etabin]->GetXaxis()->GetBinLowEdge(m_respFactorsTrackAssistedMass[etabin]->GetNbinsX()+1);
366 const double pTMin = m_respFactorsTrackAssistedMass[etabin]->GetXaxis()->GetBinLowEdge(1);
367 const double massMax = m_respFactorsTrackAssistedMass[etabin]->GetYaxis()->GetBinLowEdge(m_respFactorsTrackAssistedMass[etabin]->GetNbinsY()+1);
368 const double massMin = m_respFactorsTrackAssistedMass[etabin]->GetYaxis()->GetBinLowEdge(1);
369 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
370 if ( pT_uncorr <= m_pTMinCorr ) return 1; // no correction
371 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
372 if ( std::isnan(uncorr)) return 1; // no correction if the input is NaN, can happen for log(X)
373 if ( uncorr >= massMax ) uncorr = massMax-1e-6; //so it fits the up-most m-bin
374 if ( uncorr <= massMin ) uncorr = massMin+1e-6; //so it fits the low-most m-bin
375
376 float mass_corr = m_respFactorsTrackAssistedMass[etabin]->Interpolate( pT_uncorr, uncorr );
377
378 return mass_corr;
379}
380
381float JMSCorrection::getRelCalo3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const {
382
383 // Asymptotic values
384 double pTMax = m_caloResolutionMassCombination3D->GetXaxis()->GetBinLowEdge(m_caloResolutionMassCombination3D->GetNbinsX()+1);
385 double pTMin = m_caloResolutionMassCombination3D->GetXaxis()->GetBinLowEdge(1);
386 double mass_over_pTMax = m_caloResolutionMassCombination3D->GetYaxis()->GetBinLowEdge(m_caloResolutionMassCombination3D->GetNbinsY()+1);
387 double mass_over_pTMin = m_caloResolutionMassCombination3D->GetYaxis()->GetBinLowEdge(1);
388 double etaMax = m_caloResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(m_caloResolutionMassCombination3D->GetNbinsZ()+1);
389 double etaMin = m_caloResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(1);
390 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
391 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
392 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
393 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
394 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
395 if (eta >= etaMax) eta = etaMax-1e-6; // so it fits the up-most eta-bin
396 if (eta <= etaMin) eta = etaMin+1e-6; // so it fits the low-most eta-bin
397
398 float rel = RootHelpers::Interpolate(m_caloResolutionMassCombination3D.get(),pT_uncorr,mass_over_pt_uncorr,eta);
399
400 return rel;
401}
402
403float JMSCorrection::getRelCalo(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const {
404
405 // Asymptotic values
406 double pTMax = m_caloResolutionMassCombination[etabin]->GetXaxis()->GetBinLowEdge(m_caloResolutionMassCombination[etabin]->GetNbinsX()+1);
407 double pTMin = m_caloResolutionMassCombination[etabin]->GetXaxis()->GetBinLowEdge(1);
408 double mass_over_pTMax = m_caloResolutionMassCombination[etabin]->GetYaxis()->GetBinLowEdge(m_caloResolutionMassCombination[etabin]->GetNbinsY()+1);
409 double mass_over_pTMin = m_caloResolutionMassCombination[etabin]->GetYaxis()->GetBinLowEdge(1);
410 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
411 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
412 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
413 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
414 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
415
416 float rel = m_caloResolutionMassCombination[etabin]->Interpolate( pT_uncorr, mass_over_pt_uncorr );
417
418 return rel;
419}
420
421
422float JMSCorrection::getRelTA3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const {
423
424 // Asymptotic values
425 double pTMax = m_taResolutionMassCombination3D->GetXaxis()->GetBinLowEdge(m_taResolutionMassCombination3D->GetNbinsX()+1);
426 double pTMin = m_taResolutionMassCombination3D->GetXaxis()->GetBinLowEdge(1);
427 double mass_over_pTMax = m_taResolutionMassCombination3D->GetYaxis()->GetBinLowEdge(m_taResolutionMassCombination3D->GetNbinsY()+1);
428 double mass_over_pTMin = m_taResolutionMassCombination3D->GetYaxis()->GetBinLowEdge(1);
429 double etaMax = m_taResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(m_taResolutionMassCombination3D->GetNbinsZ()+1);
430 double etaMin = m_taResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(1);
431 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
432 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
433 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
434 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
435 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
436 if (eta >= etaMax) eta = etaMax-1e-6; // so it fits the up-most eta-bin
437 if (eta <= etaMin) eta = etaMin+1e-6; // so it fits the low-most eta-bin
438
439 float rel = RootHelpers::Interpolate(m_taResolutionMassCombination3D.get(),pT_uncorr,mass_over_pt_uncorr,eta);
440
441 return rel;
442}
443
444float JMSCorrection::getRelTA(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const {
445
446 // Asymptotic values
447 double pTMax = m_taResolutionMassCombination[etabin]->GetXaxis()->GetBinLowEdge(m_taResolutionMassCombination[etabin]->GetNbinsX()+1);
448 double pTMin = m_taResolutionMassCombination[etabin]->GetXaxis()->GetBinLowEdge(1);
449 double mass_over_pTMax = m_taResolutionMassCombination[etabin]->GetYaxis()->GetBinLowEdge(m_taResolutionMassCombination[etabin]->GetNbinsY()+1);
450 double mass_over_pTMin = m_taResolutionMassCombination[etabin]->GetYaxis()->GetBinLowEdge(1);
451 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
452 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
453 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
454 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
455 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
456
457 float rel = m_taResolutionMassCombination[etabin]->Interpolate( pT_uncorr, mass_over_pt_uncorr );
458
459 return rel;
460}
461
462float JMSCorrection::getRho3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const {
463
464 // Asymptotic values
465 double pTMax = m_correlationMapMassCombination3D->GetXaxis()->GetBinLowEdge(m_correlationMapMassCombination3D->GetNbinsX()+1);
466 double pTMin = m_correlationMapMassCombination3D->GetXaxis()->GetBinLowEdge(1);
467 double mass_over_pTMax = m_correlationMapMassCombination3D->GetYaxis()->GetBinLowEdge(m_correlationMapMassCombination3D->GetNbinsY()+1);
468 double mass_over_pTMin = m_correlationMapMassCombination3D->GetYaxis()->GetBinLowEdge(1);
469 double etaMax = m_correlationMapMassCombination3D->GetZaxis()->GetBinLowEdge(m_correlationMapMassCombination3D->GetNbinsZ()+1);
470 double etaMin = m_correlationMapMassCombination3D->GetZaxis()->GetBinLowEdge(1);
471 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
472 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
473 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
474 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
475 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
476 if (eta >= etaMax) eta = etaMax-1e-6; // so it fits the up-most eta-bin
477 if (eta <= etaMin) eta = etaMin+1e-6; // so it fits the low-most eta-bin
478
479 float rel = RootHelpers::Interpolate(m_correlationMapMassCombination3D.get(),pT_uncorr,mass_over_pt_uncorr,eta);
480
481 return rel;
482}
483
484float JMSCorrection::getRho(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const {
485
486 // Asymptotic values
487 double pTMax = m_correlationMapMassCombination[etabin]->GetXaxis()->GetBinLowEdge(m_correlationMapMassCombination[etabin]->GetNbinsX()+1);
488 double pTMin = m_correlationMapMassCombination[etabin]->GetXaxis()->GetBinLowEdge(1);
489 double mass_over_pTMax = m_correlationMapMassCombination[etabin]->GetYaxis()->GetBinLowEdge(m_correlationMapMassCombination[etabin]->GetNbinsY()+1);
490 double mass_over_pTMin = m_correlationMapMassCombination[etabin]->GetYaxis()->GetBinLowEdge(1);
491 if ( pT_uncorr >= pTMax ) pT_uncorr = pTMax-1e-6 ; //so it fits the up-most pt-bin
492 if ( pT_uncorr <= pTMin ) pT_uncorr = pTMin+1e-6; //so it fits the low-most pt-bin
493 if ( std::isnan(mass_over_pt_uncorr)) return 0; // no weight if the input is NaN, can happen for log(X)
494 if ( mass_over_pt_uncorr >= mass_over_pTMax ) mass_over_pt_uncorr = mass_over_pTMax-1e-6; //so it fits the up-most m_over_pt-bin
495 if ( mass_over_pt_uncorr <= mass_over_pTMin ) mass_over_pt_uncorr = mass_over_pTMin+1e-6; //so it fits the low-most m_over_pt-bin
496
497 float rho = m_correlationMapMassCombination[etabin]->Interpolate( pT_uncorr, mass_over_pt_uncorr );
498
499 return rho;
500}
501
502
504
505 //Apply the JMS calibration scale factor
506
507 //Takes the uncorrected jet eta (in case the origin and/or 4vector jet area corrections were applied)
508 float detectorEta = jet.getAttribute<float>("DetectorEta");
509 double absdetectorEta = fabs(detectorEta);
510
511 xAOD::JetFourMom_t jetStartP4;
513 jetStartP4 = jet.jetP4();
514
515 xAOD::JetFourMom_t calibP4 = jet.jetP4();
516
517 float mass_corr = jetStartP4.mass();
518 double pT_corr = jetStartP4.pt();
519
520 TLorentzVector caloCalibJet;
521 float mass_ta = 0;
522
524 // Determine mass eta bin to use (if using 2D histograms)
525 int etabin=-99;
526 if (!m_use3Dhisto && (m_massEtaBins.empty() || m_respFactorsMass.size() != m_massEtaBins.size()-1)){
527 ATH_MSG_FATAL("Please check that the mass correction eta binning is properly set in your config file");
528 return StatusCode::FAILURE;
529 }
530 else if (m_use3Dhisto && !m_respFactorMass3D)
531 {
532 ATH_MSG_FATAL("Please check that the mass correction 3D histogram is provided");
533 return StatusCode::FAILURE;
534 }
535
536 // Originally was jet.getConstituents().size() > 1
537 // This essentially requires that the jet has a mass
538 // However, constituents are not stored now in rel21 (LCOrigTopoClusters are transient)
539 // Thus, getConstituents() breaks unless they are specifically written out
540 // Instead, this has been changed to require a non-zero mass
541 // Done by S. Schramm on Oct 21, 2017
542
543 if ( ( ( !m_use3Dhisto && absdetectorEta < m_massEtaBins.back() ) ||
544 ( m_use3Dhisto && absdetectorEta < m_respFactorMass3D->GetZaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsZ()+1))
545 ) && jetStartP4.mass() != 0 ) { // Fiducial cuts
546 if (!m_use3Dhisto)
547 {
548 for (uint i=0; i<m_massEtaBins.size()-1; ++i) {
549 if(absdetectorEta >= m_massEtaBins[i] && absdetectorEta < m_massEtaBins[i+1]) etabin = i;
550 }
551 if (etabin< 0){
552 ATH_MSG_FATAL("There was a problem determining the eta bin to use for the mass correction");
553 return StatusCode::FAILURE;
554 }
555 }
556
557 // Use the correct histogram binning parametrisation when reading the corrected mass
558 double massFactor = 1;
559 switch (m_binParam)
560 {
562 if (m_use3Dhisto)
563 massFactor = getMassCorr3D( jetStartP4.pt()/m_GeV, jetStartP4.mass()/m_GeV, absdetectorEta );
564 else
565 massFactor = getMassCorr( jetStartP4.pt()/m_GeV, jetStartP4.mass()/m_GeV, etabin );
566 break;
568 if (jetStartP4.mass() / jetStartP4.e() > 0)
569 {
570 if (m_use3Dhisto)
571 massFactor = getMassCorr3D( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.e()), absdetectorEta);
572 else
573 massFactor = getMassCorr( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.e()), etabin);
574 }
575 else
576 massFactor = 1; // Prevent log(X) for X <= 0
577 break;
579 if (jetStartP4.mass() / jetStartP4.Et() > 0)
580 {
581 if (m_use3Dhisto)
582 massFactor = getMassCorr3D( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.Et()), absdetectorEta);
583 else
584 massFactor = getMassCorr( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.Et()), etabin);
585 }
586 else
587 massFactor = 1; // Prevent log(X) for X <= 0
588 break;
590 if (jetStartP4.mass() / jetStartP4.pt() > 0)
591 {
592 if (m_use3Dhisto)
593 massFactor = getMassCorr3D( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.pt()), absdetectorEta);
594 else
595 massFactor = getMassCorr( jetStartP4.e()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.pt()), etabin);
596 }
597 else
598 massFactor = 1; // Prevent log(X) for X <= 0
599 break;
601 if (jetStartP4.mass() / jetStartP4.Et() > 0)
602 {
603 if (m_use3Dhisto)
604 massFactor = getMassCorr3D( jetStartP4.Et()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.Et()), absdetectorEta);
605 else
606 massFactor = getMassCorr( jetStartP4.Et()/m_GeV, std::log(jetStartP4.mass() / jetStartP4.Et()), etabin);
607 }
608 else
609 massFactor = 1; // Prevent log(X) for X <= 0
610 break;
611 default:
612 ATH_MSG_FATAL("This should never be reached - if it happens, it's because a new BinningParam enum option was added, but how to handle it for the calo mass was not. Please contact the tool developer(s) to fix this.");
613 return StatusCode::FAILURE;
614 break;
615 }
616 if (massFactor == 0.){
617 ATH_MSG_WARNING("Divisor 'massFactor' is zero; resetting to 1.");
618 massFactor = 1.;
619 }
620 mass_corr = jetStartP4.mass() / massFactor;
621 if (mass_corr > jetStartP4.e()) {
622 mass_corr = jetStartP4.mass();
623 }
624
625 if(!m_pTfixed) pT_corr = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_corr*mass_corr)/std::cosh( jetStartP4.eta() );
626 }
627
628 caloCalibJet.SetPtEtaPhiM(pT_corr, jetStartP4.eta(), jetStartP4.phi(), mass_corr);
629
630 if(!m_combination){
631 calibP4.SetPxPyPzE( caloCalibJet.Px(), caloCalibJet.Py(), caloCalibJet.Pz(), caloCalibJet.E() );
632
633 //Transfer calibrated jet properties to the Jet object
634 jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentum",calibP4);
635 jet.setJetP4( calibP4 );
636 }
637
638 // Track Assisted Mass Correction
640
641 double E_corr = jetStartP4.e();
642
643 // Determine mass eta bin to use
644 if (!m_use3Dhisto)
645 {
646 etabin=-99;
647 if (m_massEtaBins.empty() || m_respFactorsTrackAssistedMass.size() != m_massEtaBins.size()-1){
648 ATH_MSG_FATAL("Please check that the mass correction eta binning is properly set in your config file");
649 if(m_combination) return StatusCode::FAILURE;
650 }
651 }
653 {
654 ATH_MSG_FATAL("Please check that the track assisted mass correction 3D histogram is provided");
655 return StatusCode::FAILURE;
656 }
657
658 float trackSumMass;
659 std::string TrackSumMassStr = "TrackSumMass";
660 if(m_jetAlgo=="AntiKt4EMTopo" || m_jetAlgo=="AntiKt4LCTopo") TrackSumMassStr = "DFCommonJets_TrackSumMass";
661 std::string TrackSumPtStr = "TrackSumPt";
662 if(m_jetAlgo=="AntiKt4EMTopo" || m_jetAlgo=="AntiKt4LCTopo") TrackSumPtStr = "DFCommonJets_TrackSumPt";
663 if( !jet.getAttribute<float>(TrackSumMassStr,trackSumMass) ) {
664 if(!m_combination){
665 //ATH_MSG_WARNING("Failed to retrieve TrackSumMass! Track Assisted Mass Correction will NOT be applied\n\n");
666 [[maybe_unused]] static const bool warnedOnce = [&] {
667 ATH_MSG_WARNING("Failed to retrieve TrackSumMass! Track Assisted Mass Correction will NOT be applied");
668 return true;
669 }();
670 return StatusCode::SUCCESS;
671 } else{
672 ATH_MSG_FATAL("Failed to retrieve TrackSumMass! Mass Combination can NOT be performed. Aborting.");
673 return StatusCode::FAILURE;
674 }
675 }
676 float trackSumPt;
677 if( !jet.getAttribute<float>(TrackSumPtStr,trackSumPt) ) {
678 if(!m_combination){
679 //ATH_MSG_WARNING("Failed to retrieve TrackSumPt! Track Assisted Mass Correction will NOT be applied\n\n");
680 [[maybe_unused]] static const bool warnedOnce = [&] {
681 ATH_MSG_WARNING("Failed to retrieve TrackSumPt! Track Assisted Mass Correction will NOT be applied");
682 return true;
683 }();
684 return StatusCode::SUCCESS;
685 } else{
686 ATH_MSG_FATAL("Failed to retrieve TrackSumPt! Mass Combination can NOT be performed. Aborting.");
687 return StatusCode::FAILURE;
688 }
689 }
690 pT_corr = jetStartP4.pt();
691 float mTA;
692 if(trackSumPt==0) mTA = 0;
693 else{mTA = (jetStartP4.pt()/trackSumPt)*trackSumMass;}
694 if(mTA<0 || mTA > jetStartP4.e()) mTA = 0;
695 mass_corr = mTA;
696
697 if ( ( ( !m_use3Dhisto && absdetectorEta < m_massEtaBins.back() ) ||
698 ( m_use3Dhisto && absdetectorEta < m_respFactorMass3D->GetZaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsZ()+1))
699 ) && jetStartP4.mass() != 0 ) { // Fiducial cuts
700 if (!m_use3Dhisto)
701 {
702 for (uint i=0; i<m_massEtaBins.size()-1; ++i) {
703 if(absdetectorEta >= m_massEtaBins[i] && absdetectorEta < m_massEtaBins[i+1]) etabin = i;
704 }
705 if (etabin< 0){
706 ATH_MSG_FATAL("There was a problem determining the eta bin to use for the track assisted mass correction");
707 return StatusCode::FAILURE;
708 }
709 }
710
711 double mTAFactor = 1;
712
713 if(mTA!=0){ // Read the calibration values from histograms only when this value is non-zero
714 // Use the correct histogram binning parametrisation when reading the corrected mass
715 switch (m_binParam)
716 {
718 if (m_use3Dhisto)
719 mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.pt()/m_GeV, mTA/m_GeV, absdetectorEta );
720 else
721 mTAFactor = getTrackAssistedMassCorr( jetStartP4.pt()/m_GeV, mTA/m_GeV, etabin );
722 break;
724 if (mTA / jetStartP4.e() > 0)
725 {
726 if (m_use3Dhisto)
727 mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.e()), absdetectorEta);
728 else
729 mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.e()), etabin);
730 }
731 else
732 mTAFactor = 1; // Prevent log(X) for X <= 0
733 break;
735 if (mTA / jetStartP4.Et() > 0)
736 {
737 if (m_use3Dhisto)
738 mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.Et()), absdetectorEta);
739 else
740 mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.Et()), etabin);
741 }
742 else
743 mTAFactor = 1; // Prevent log(X) for X <= 0
744 break;
746 if (mTA / jetStartP4.pt() > 0)
747 {
748 if (m_use3Dhisto)
749 mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.pt()), absdetectorEta);
750 else
751 mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.pt()), etabin);
752 }
753 else
754 mTAFactor = 1; // Prevent log(X) for X <= 0
755 break;
757 if (mTA / jetStartP4.Et() > 0)
758 {
759 if (m_use3Dhisto)
760 mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.Et()/m_GeV, std::log(mTA / jetStartP4.Et()), absdetectorEta);
761 else
762 mTAFactor = getTrackAssistedMassCorr( jetStartP4.Et()/m_GeV, std::log(mTA / jetStartP4.Et()), etabin);
763 }
764 else
765 mTAFactor = 1; // Prevent log(X) for X <= 0
766 break;
767 default:
768 ATH_MSG_FATAL("This should never be reached - if it happens, it's because a new BinningParam enum option was added, but how to handle it for the TA mass was not. Please contact the tool developer(s) to fix this.");
769 return StatusCode::FAILURE;
770 break;
771 }
772 }
773
774 if(mTAFactor!=0) mass_corr = mTA/mTAFactor;
775 else{
776 ATH_MSG_FATAL("The calibration histogram may have a bad filling bin that is causing mTAFactor to be zero. This value should be different from zero in order to take the ratio. Please contact the tool developer to fix this since the calibration histogram may be corrupted. ");
777 return StatusCode::FAILURE;
778 }
779
780 if(!m_pTfixed) pT_corr = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_corr*mass_corr)/std::cosh( jetStartP4.eta() );
781 else{E_corr = std::sqrt(jetStartP4.P()*jetStartP4.P()+mass_corr*mass_corr);}
782 }
783 else{
784 mTA = 0;
785 mass_corr = 0;
786 if(!m_pTfixed) pT_corr = jetStartP4.e()/std::cosh( jetStartP4.eta() );
787 else{E_corr = jetStartP4.P();}
788 }
789
790 TLorentzVector TACalibJet;
791 xAOD::JetFourMom_t TACalibJet_pTfixed = jet.jetP4();
792 if(!m_pTfixed){
793 TACalibJet.SetPtEtaPhiM(pT_corr, jetStartP4.eta(), jetStartP4.phi(), mass_corr);
794 }else{
795 TACalibJet_pTfixed.SetPxPyPzE( jetStartP4.Px(), jetStartP4.Py(), jetStartP4.Pz(), E_corr );}
796
797 //Transfer calibrated track assisted mass property to the Jet object
798 jet.setAttribute<float>("JetTrackAssistedMassUnCalibrated",mTA);
799 jet.setAttribute<float>("JetTrackAssistedMassCalibrated",mass_corr);
800 if(!m_pTfixed) jet.setAttribute<float>("JetpTCorrByCalibratedTAMass",pT_corr);
801 else{jet.setAttribute<float>("JetECorrByCalibratedTAMass",E_corr);}
802
803 //float mass_ta;
804 mass_ta = mass_corr;
805
806 // Store calo and TA calibrated jets separetely to further apply insitu:
807 //Transfer calibrated calo mass property to the Jet object
808 xAOD::JetFourMom_t calibP4_calo = jet.jetP4();
809 calibP4_calo.SetCoordinates( caloCalibJet.Pt(), jetStartP4.eta(), jetStartP4.phi(), caloCalibJet.M() );
810 jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentumCalo",calibP4_calo);
811
812 //Transfer calibrated TA mass property to the Jet object
813 xAOD::JetFourMom_t calibP4_ta = jet.jetP4();
814 if(!m_pTfixed){
815 calibP4_ta.SetCoordinates( TACalibJet.Pt(), jetStartP4.eta(), jetStartP4.phi(), TACalibJet.M() );
816 }else{
817 calibP4_ta.SetPxPyPzE( TACalibJet_pTfixed.Px(), TACalibJet_pTfixed.Py(), TACalibJet_pTfixed.Pz(), TACalibJet_pTfixed.E() );}
818
819 jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentumTA",calibP4_ta);
820 } //m_trackAssistedJetMassCorr
821 }
822
823 if(m_combination){
824 float mass_calo;
825 float Mass_comb = 0.;
826 double pT_calo;
827 double E_calo;
828 double Et_calo;
829
831 // Read input values (calo and TA insitu calibrated jets) for combination:
832
833 xAOD::JetFourMom_t jetInsituP4_calo;
834 xAOD::JetFourMom_t calibP4Insitu_calo;
835 if(jet.getAttribute<xAOD::JetFourMom_t>("JetInsituScaleMomentumCalo",jetInsituP4_calo)){
836 calibP4Insitu_calo=jetInsituP4_calo;
837 }else{
838 ATH_MSG_FATAL( "Cannot retrieve JetInsituScaleMomentumCalo jets" );
839 return StatusCode::FAILURE;
840 }
841 TLorentzVector TLVCaloInsituCalib;
842 TLVCaloInsituCalib.SetPtEtaPhiM(calibP4Insitu_calo.pt(), calibP4Insitu_calo.eta(), calibP4Insitu_calo.phi(), calibP4Insitu_calo.mass());
843 mass_calo = TLVCaloInsituCalib.M();
844 pT_calo = TLVCaloInsituCalib.Pt();
845 E_calo = TLVCaloInsituCalib.E();
846 Et_calo = TLVCaloInsituCalib.Et();
847
848 xAOD::JetFourMom_t jetInsituP4_ta;
849 xAOD::JetFourMom_t calibP4Insitu_ta;
850 if(jet.getAttribute<xAOD::JetFourMom_t>("JetInsituScaleMomentumTA",jetInsituP4_ta)){
851 calibP4Insitu_ta=jetInsituP4_ta;
852 }else{
853 ATH_MSG_FATAL( "Cannot retrieve JetInsituScaleMomentumTA jets" );
854 return StatusCode::FAILURE;
855 }
856 TLorentzVector TLVTAInsituCalib;
857 TLVTAInsituCalib.SetPtEtaPhiM(calibP4Insitu_ta.pt(), calibP4Insitu_ta.eta(), calibP4Insitu_ta.phi(), calibP4Insitu_ta.mass());
858 mass_ta = TLVTAInsituCalib.M();
859 }else{
860 mass_calo = caloCalibJet.M(); // combined mass
861 pT_calo = caloCalibJet.Pt();
862 E_calo = caloCalibJet.E();
863 Et_calo = caloCalibJet.Et();
864 // mass_ta already defined above
865 }
866
867 // if one of the mass is null, use the other one
868 if( (mass_calo==0) || (mass_ta==0) ) {
869 Mass_comb = mass_ta+mass_calo;
870 }
871 else {
872 // Determine mass combination eta bin to use
873 int etabin=-99;
874 if (!m_use3Dhisto)
875 {
877 ATH_MSG_FATAL("Please check that the mass combination eta binning is properly set in your config file");
878 return StatusCode::FAILURE;
879 }
881 ATH_MSG_FATAL("Please check that the mass combination eta binning is properly set in your config file");
882 return StatusCode::FAILURE;
883 }
884 }
886 {
887 ATH_MSG_FATAL("Please check that the mass resolution 3D histogram is provided");
888 return StatusCode::FAILURE;
889 }
891 {
892 ATH_MSG_FATAL("Please check that the track assisted mass resolution 3D histogram is provided");
893 return StatusCode::FAILURE;
894 }
895
896 if ( ( ( !m_use3Dhisto && absdetectorEta < m_massCombinationEtaBins.back() ) ||
897 ( m_use3Dhisto && absdetectorEta < m_caloResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(m_caloResolutionMassCombination3D->GetNbinsZ()+1)) ) ) {
898
899 if (!m_use3Dhisto)
900 {
901 for (uint i=0; i<m_massCombinationEtaBins.size()-1; ++i) {
902 if(absdetectorEta >= m_massCombinationEtaBins[i] && absdetectorEta < m_massCombinationEtaBins[i+1]) etabin = i;
903 }
904 if (etabin< 0){
905 ATH_MSG_FATAL("There was a problem determining the eta bin to use for the mass combination");
906 return StatusCode::FAILURE;
907 }
908 }
909
910 // Use the correct histogram binning parametrisation when reading the combined mass weights
911 double relCalo = 0;
912 double relTA = 0;
913 double rho = 0;
914 switch (m_binParam)
915 {
917 if (m_use3Dhisto)
918 {
919 relCalo = getRelCalo3D( pT_calo/m_GeV, mass_calo/pT_calo, absdetectorEta );
920 relTA = getRelTA3D( pT_calo/m_GeV, mass_ta/pT_calo, absdetectorEta );
922 rho = getRho3D( pT_calo/m_GeV, mass_calo/pT_calo, absdetectorEta );
923 }
924 else
925 {
926 relCalo = getRelCalo( pT_calo/m_GeV, mass_calo/pT_calo, etabin );
927 relTA = getRelTA( pT_calo/m_GeV, mass_ta/pT_calo, etabin );
929 rho = getRho( pT_calo/m_GeV, mass_calo/pT_calo, etabin );
930 }
931 break;
933 if (m_use3Dhisto)
934 {
935 relCalo = mass_calo/E_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/E_calo), absdetectorEta ) : 0;
936 relTA = mass_ta/E_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/E_calo), absdetectorEta ) : 0;
938 rho = mass_calo/E_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/E_calo), absdetectorEta ) : 0;
939 }
940 else
941 {
942 relCalo = mass_calo/E_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/E_calo), etabin ) : 0;
943 relTA = mass_ta/E_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/E_calo), etabin ) : 0;
945 rho = mass_calo/E_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/E_calo), etabin ) : 0;
946 }
947 break;
949 if (m_use3Dhisto)
950 {
951 relCalo = mass_calo/Et_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
952 relTA = mass_ta/Et_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/Et_calo), absdetectorEta ) : 0;
954 rho = mass_calo/Et_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
955 }
956 else
957 {
958 relCalo = mass_calo/Et_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
959 relTA = mass_ta/Et_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/Et_calo), etabin ) : 0;
961 rho = mass_calo/Et_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
962 }
963 break;
965 if (m_use3Dhisto)
966 {
967 relCalo = mass_calo/pT_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/pT_calo), absdetectorEta ) : 0;
968 relTA = mass_ta/pT_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/pT_calo), absdetectorEta ) : 0;
970 rho = mass_calo/pT_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/pT_calo), absdetectorEta ) : 0;
971 }
972 else
973 {
974 relCalo = mass_calo/pT_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/pT_calo), etabin ) : 0;
975 relTA = mass_ta/pT_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/pT_calo), etabin ) : 0;
977 rho = mass_calo/pT_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/pT_calo), etabin ) : 0;
978 }
979 break;
981 if (m_use3Dhisto)
982 {
983 relCalo = mass_calo/Et_calo > 0 ? getRelCalo3D( Et_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
984 relTA = mass_ta/Et_calo > 0 ? getRelTA3D( Et_calo/m_GeV, std::log(mass_ta/Et_calo), absdetectorEta ) : 0;
986 rho = mass_calo/Et_calo > 0 ? getRho3D( Et_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
987 }
988 else
989 {
990 relCalo = mass_calo/Et_calo > 0 ? getRelCalo( Et_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
991 relTA = mass_ta/Et_calo > 0 ? getRelTA( Et_calo/m_GeV, std::log(mass_ta/Et_calo), etabin ) : 0;
993 rho = mass_calo/Et_calo > 0 ? getRho( Et_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
994 }
995 break;
996 default:
997 ATH_MSG_FATAL("This should never be reached - if it happens, it's because a new BinningParam enum option was added, but how to handle it for the TA mass was not. Please contact the tool developer(s) to fix this.");
998 return StatusCode::FAILURE;
999 break;
1000 }
1001
1002 // Watch for division by zero
1003 if(relCalo*relCalo + relTA*relTA - 2 * rho* relCalo * relTA == 0.){
1004 ATH_MSG_ERROR("Encountered division by zero when calculating mass combination weight using correlated weights");
1005 return StatusCode::FAILURE;
1006 }
1007
1008 const double Weight = ( relTA*relTA - rho *relCalo*relTA ) / ( relCalo*relCalo + relTA*relTA - 2 * rho* relCalo * relTA );
1009
1010 // Zero should be only returned by resolution functions if jet mass is negative
1011 if(relCalo == 0 && relTA == 0)
1012 Mass_comb = 0;
1013 else if(relCalo == 0)
1014 Mass_comb = mass_ta;
1015 else if(relTA == 0)
1016 Mass_comb = mass_calo;
1017 else
1018 Mass_comb = ( mass_calo * Weight ) + ( mass_ta * ( 1 - Weight) );
1019 // Protection
1020 if(Mass_comb>jetStartP4.e()) Mass_comb = mass_calo;
1021 else if(!m_pTfixed) pT_calo = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_calo*mass_calo)/std::cosh( jetStartP4.eta() );
1022 }
1023 }
1024
1025 TLorentzVector TLVjet;
1026 TLVjet.SetPtEtaPhiM( pT_calo, jetStartP4.eta(), jetStartP4.phi(), Mass_comb );
1027 calibP4.SetPxPyPzE( TLVjet.Px(), TLVjet.Py(), TLVjet.Pz(), TLVjet.E() );
1028
1029 //Transfer calibrated jet properties to the Jet object
1030 jet.setAttribute<xAOD::JetFourMom_t>(m_jetOutScale.Data(),calibP4);
1031 jet.setJetP4( calibP4 );
1032
1033 } //m_combination
1034
1035 return StatusCode::SUCCESS;
1036
1037}
Scalar eta() const
pseudorapidity method
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
double mTA(const double trackMass, const double trackPt, const double caloPt)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
VecTH2 m_correlationMapMassCombination
bool m_useCorrelatedWeights
TString m_jetOutScale
float getRelTA(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
void setMassEtaBins(const VecD &etabins)
unsigned int uint
float getMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
float getRelTA3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
float getRelCalo3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
float getMassCorr(double pT_uncorr, double mass_uncorr, int etabin) const
VecTH2 m_caloResolutionMassCombination
float getRelCalo(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
VecD m_massCombinationEtaBins
VecTH2 m_respFactorsTrackAssistedMass
std::unique_ptr< const TH3 > m_caloResolutionMassCombination3D
TString m_jetAlgo
float getTrackAssistedMassCorr(double pT_uncorr, double mass_uncorr, int etabin) const
BinningParam m_binParam
TString m_calibAreaTag
void setMassCombinationEtaBins(const VecD &etabins)
std::unique_ptr< const TH3 > m_respFactorTrackAssistedMass3D
std::unique_ptr< const TH3 > m_correlationMapMassCombination3D
float getTrackAssistedMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
std::unique_ptr< const TH3 > m_respFactorMass3D
VecTH2 m_taResolutionMassCombination
std::unique_ptr< const TH3 > m_taResolutionMassCombination3D
virtual StatusCode calibrate(xAOD::Jet &jet, JetEventInfo &) const override
bool m_trackAssistedJetMassCorr
float getRho(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
VecTH2 m_respFactorsMass
virtual StatusCode initialize() override
float getRho3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
virtual StatusCode setStartP4(xAOD::Jet &jet) const
JetCalibrationStep(const char *name="JetCalibrationStep")
std::unique_ptr< const TH2 > GetHisto2(TFile &file, const TString &hname)
VecD VectorizeD(const TString &str, const TString &sep=" ")
std::unique_ptr< const TH3 > GetHisto3(TFile &file, const TString &hname)
double Interpolate(const TH1 *histo, const double x)
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