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