ATLAS Offline Software
JMSCorrection.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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 
27  m_config(nullptr), m_jetAlgo(""), m_calibAreaTag(""), m_dev(false)
28 { }
29 
30 
31 JMSCorrection::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 
67  if(!m_onlyCombination){
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)
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
231  if(!m_onlyCombination){
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 
301 float 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 
323 float 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 
342 float 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 
364 float 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 
383 float 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 
405 float 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 
424 float 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 
446 float 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 
464 float 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 
486 float 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 
525  if(!m_onlyCombination){
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 
621  if(!m_pTfixed) pT_corr = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_corr*mass_corr)/std::cosh( jetStartP4.eta() );
622  }
623 
624  caloCalibJet.SetPtEtaPhiM(pT_corr, jetStartP4.eta(), jetStartP4.phi(), mass_corr);
625 
626  if(!m_combination){
627  calibP4.SetPxPyPzE( caloCalibJet.Px(), caloCalibJet.Py(), caloCalibJet.Pz(), caloCalibJet.E() );
628 
629  //Transfer calibrated jet properties to the Jet object
630  jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentum",calibP4);
631  jet.setJetP4( calibP4 );
632  }
633 
634  // Track Assisted Mass Correction
636 
637  double E_corr = jetStartP4.e();
638 
639  // Determine mass eta bin to use
640  if (!m_use3Dhisto)
641  {
642  etabin=-99;
643  if (m_massEtaBins.empty() || m_respFactorsTrackAssistedMass.size() != m_massEtaBins.size()-1){
644  ATH_MSG_FATAL("Please check that the mass correction eta binning is properly set in your config file");
645  if(m_combination) return StatusCode::FAILURE;
646  }
647  }
649  {
650  ATH_MSG_FATAL("Please check that the track assisted mass correction 3D histogram is provided");
651  return StatusCode::FAILURE;
652  }
653 
654  float trackSumMass;
655  std::string TrackSumMassStr = "TrackSumMass";
656  if(m_jetAlgo=="AntiKt4EMTopo" || m_jetAlgo=="AntiKt4LCTopo") TrackSumMassStr = "DFCommonJets_TrackSumMass";
657  std::string TrackSumPtStr = "TrackSumPt";
658  if(m_jetAlgo=="AntiKt4EMTopo" || m_jetAlgo=="AntiKt4LCTopo") TrackSumPtStr = "DFCommonJets_TrackSumPt";
659  if( !jet.getAttribute<float>(TrackSumMassStr,trackSumMass) ) {
660  if(!m_combination){
661  //ATH_MSG_WARNING("Failed to retrieve TrackSumMass! Track Assisted Mass Correction will NOT be applied\n\n");
662  [[maybe_unused]] static const bool warnedOnce = [&] {
663  ATH_MSG_WARNING("Failed to retrieve TrackSumMass! Track Assisted Mass Correction will NOT be applied");
664  return true;
665  }();
666  return StatusCode::SUCCESS;
667  } else{
668  ATH_MSG_FATAL("Failed to retrieve TrackSumMass! Mass Combination can NOT be performed. Aborting.");
669  return StatusCode::FAILURE;
670  }
671  }
672  float trackSumPt;
673  if( !jet.getAttribute<float>(TrackSumPtStr,trackSumPt) ) {
674  if(!m_combination){
675  //ATH_MSG_WARNING("Failed to retrieve TrackSumPt! Track Assisted Mass Correction will NOT be applied\n\n");
676  [[maybe_unused]] static const bool warnedOnce = [&] {
677  ATH_MSG_WARNING("Failed to retrieve TrackSumPt! Track Assisted Mass Correction will NOT be applied");
678  return true;
679  }();
680  return StatusCode::SUCCESS;
681  } else{
682  ATH_MSG_FATAL("Failed to retrieve TrackSumPt! Mass Combination can NOT be performed. Aborting.");
683  return StatusCode::FAILURE;
684  }
685  }
686  pT_corr = jetStartP4.pt();
687  float mTA;
688  if(trackSumPt==0) mTA = 0;
689  else{mTA = (jetStartP4.pt()/trackSumPt)*trackSumMass;}
690  if(mTA<0 || mTA > jetStartP4.e()) mTA = 0;
691  mass_corr = mTA;
692 
693  if ( ( ( !m_use3Dhisto && absdetectorEta < m_massEtaBins.back() ) ||
694  ( m_use3Dhisto && absdetectorEta < m_respFactorMass3D->GetZaxis()->GetBinLowEdge(m_respFactorMass3D->GetNbinsZ()+1))
695  ) && jetStartP4.mass() != 0 ) { // Fiducial cuts
696  if (!m_use3Dhisto)
697  {
698  for (uint i=0; i<m_massEtaBins.size()-1; ++i) {
699  if(absdetectorEta >= m_massEtaBins[i] && absdetectorEta < m_massEtaBins[i+1]) etabin = i;
700  }
701  if (etabin< 0){
702  ATH_MSG_FATAL("There was a problem determining the eta bin to use for the track assisted mass correction");
703  return StatusCode::FAILURE;
704  }
705  }
706 
707  double mTAFactor = 1;
708 
709  if(mTA!=0){ // Read the calibration values from histograms only when this value is non-zero
710  // Use the correct histogram binning parametrisation when reading the corrected mass
711  switch (m_binParam)
712  {
714  if (m_use3Dhisto)
715  mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.pt()/m_GeV, mTA/m_GeV, absdetectorEta );
716  else
717  mTAFactor = getTrackAssistedMassCorr( jetStartP4.pt()/m_GeV, mTA/m_GeV, etabin );
718  break;
720  if (mTA / jetStartP4.e() > 0)
721  {
722  if (m_use3Dhisto)
723  mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.e()), absdetectorEta);
724  else
725  mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.e()), etabin);
726  }
727  else
728  mTAFactor = 1; // Prevent log(X) for X <= 0
729  break;
731  if (mTA / jetStartP4.Et() > 0)
732  {
733  if (m_use3Dhisto)
734  mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.Et()), absdetectorEta);
735  else
736  mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.Et()), etabin);
737  }
738  else
739  mTAFactor = 1; // Prevent log(X) for X <= 0
740  break;
742  if (mTA / jetStartP4.pt() > 0)
743  {
744  if (m_use3Dhisto)
745  mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.pt()), absdetectorEta);
746  else
747  mTAFactor = getTrackAssistedMassCorr( jetStartP4.e()/m_GeV, std::log(mTA / jetStartP4.pt()), etabin);
748  }
749  else
750  mTAFactor = 1; // Prevent log(X) for X <= 0
751  break;
753  if (mTA / jetStartP4.Et() > 0)
754  {
755  if (m_use3Dhisto)
756  mTAFactor = getTrackAssistedMassCorr3D( jetStartP4.Et()/m_GeV, std::log(mTA / jetStartP4.Et()), absdetectorEta);
757  else
758  mTAFactor = getTrackAssistedMassCorr( jetStartP4.Et()/m_GeV, std::log(mTA / jetStartP4.Et()), etabin);
759  }
760  else
761  mTAFactor = 1; // Prevent log(X) for X <= 0
762  break;
763  default:
764  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.");
765  return StatusCode::FAILURE;
766  break;
767  }
768  }
769 
770  if(mTAFactor!=0) mass_corr = mTA/mTAFactor;
771  else{
772  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. ");
773  return StatusCode::FAILURE;
774  }
775 
776  if(!m_pTfixed) pT_corr = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_corr*mass_corr)/std::cosh( jetStartP4.eta() );
777  else{E_corr = std::sqrt(jetStartP4.P()*jetStartP4.P()+mass_corr*mass_corr);}
778  }
779  else{
780  mTA = 0;
781  mass_corr = 0;
782  if(!m_pTfixed) pT_corr = jetStartP4.e()/std::cosh( jetStartP4.eta() );
783  else{E_corr = jetStartP4.P();}
784  }
785 
786  TLorentzVector TACalibJet;
787  xAOD::JetFourMom_t TACalibJet_pTfixed = jet.jetP4();
788  if(!m_pTfixed){
789  TACalibJet.SetPtEtaPhiM(pT_corr, jetStartP4.eta(), jetStartP4.phi(), mass_corr);
790  }else{
791  TACalibJet_pTfixed.SetPxPyPzE( jetStartP4.Px(), jetStartP4.Py(), jetStartP4.Pz(), E_corr );}
792 
793  //Transfer calibrated track assisted mass property to the Jet object
794  jet.setAttribute<float>("JetTrackAssistedMassUnCalibrated",mTA);
795  jet.setAttribute<float>("JetTrackAssistedMassCalibrated",mass_corr);
796  if(!m_pTfixed) jet.setAttribute<float>("JetpTCorrByCalibratedTAMass",pT_corr);
797  else{jet.setAttribute<float>("JetECorrByCalibratedTAMass",E_corr);}
798 
799  //float mass_ta;
800  mass_ta = mass_corr;
801 
802  // Store calo and TA calibrated jets separetely to further apply insitu:
803  //Transfer calibrated calo mass property to the Jet object
804  xAOD::JetFourMom_t calibP4_calo = jet.jetP4();
805  calibP4_calo.SetCoordinates( caloCalibJet.Pt(), jetStartP4.eta(), jetStartP4.phi(), caloCalibJet.M() );
806  jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentumCalo",calibP4_calo);
807 
808  //Transfer calibrated TA mass property to the Jet object
809  xAOD::JetFourMom_t calibP4_ta = jet.jetP4();
810  if(!m_pTfixed){
811  calibP4_ta.SetCoordinates( TACalibJet.Pt(), jetStartP4.eta(), jetStartP4.phi(), TACalibJet.M() );
812  }else{
813  calibP4_ta.SetPxPyPzE( TACalibJet_pTfixed.Px(), TACalibJet_pTfixed.Py(), TACalibJet_pTfixed.Pz(), TACalibJet_pTfixed.E() );}
814 
815  jet.setAttribute<xAOD::JetFourMom_t>("JetJMSScaleMomentumTA",calibP4_ta);
816  } //m_trackAssistedJetMassCorr
817  }
818 
819  if(m_combination){
820  float mass_calo;
821  float Mass_comb = 0.;
822  double pT_calo;
823  double E_calo;
824  double Et_calo;
825 
826  if(m_onlyCombination){
827  // Read input values (calo and TA insitu calibrated jets) for combination:
828 
829  xAOD::JetFourMom_t jetInsituP4_calo;
830  xAOD::JetFourMom_t calibP4Insitu_calo;
831  if(jet.getAttribute<xAOD::JetFourMom_t>("JetInsituScaleMomentumCalo",jetInsituP4_calo)){
832  calibP4Insitu_calo=jetInsituP4_calo;
833  }else{
834  ATH_MSG_FATAL( "Cannot retrieve JetInsituScaleMomentumCalo jets" );
835  return StatusCode::FAILURE;
836  }
837  TLorentzVector TLVCaloInsituCalib;
838  TLVCaloInsituCalib.SetPtEtaPhiM(calibP4Insitu_calo.pt(), calibP4Insitu_calo.eta(), calibP4Insitu_calo.phi(), calibP4Insitu_calo.mass());
839  mass_calo = TLVCaloInsituCalib.M();
840  pT_calo = TLVCaloInsituCalib.Pt();
841  E_calo = TLVCaloInsituCalib.E();
842  Et_calo = TLVCaloInsituCalib.Et();
843 
844  xAOD::JetFourMom_t jetInsituP4_ta;
845  xAOD::JetFourMom_t calibP4Insitu_ta;
846  if(jet.getAttribute<xAOD::JetFourMom_t>("JetInsituScaleMomentumTA",jetInsituP4_ta)){
847  calibP4Insitu_ta=jetInsituP4_ta;
848  }else{
849  ATH_MSG_FATAL( "Cannot retrieve JetInsituScaleMomentumTA jets" );
850  return StatusCode::FAILURE;
851  }
852  TLorentzVector TLVTAInsituCalib;
853  TLVTAInsituCalib.SetPtEtaPhiM(calibP4Insitu_ta.pt(), calibP4Insitu_ta.eta(), calibP4Insitu_ta.phi(), calibP4Insitu_ta.mass());
854  mass_ta = TLVTAInsituCalib.M();
855  }else{
856  mass_calo = caloCalibJet.M(); // combined mass
857  pT_calo = caloCalibJet.Pt();
858  E_calo = caloCalibJet.E();
859  Et_calo = caloCalibJet.Et();
860  // mass_ta already defined above
861  }
862 
863  // if one of the mass is null, use the other one
864  if( (mass_calo==0) || (mass_ta==0) ) {
865  Mass_comb = mass_ta+mass_calo;
866  }
867  else {
868  // Determine mass combination eta bin to use
869  int etabin=-99;
870  if (!m_use3Dhisto)
871  {
873  ATH_MSG_FATAL("Please check that the mass combination eta binning is properly set in your config file");
874  return StatusCode::FAILURE;
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  }
880  }
882  {
883  ATH_MSG_FATAL("Please check that the mass resolution 3D histogram is provided");
884  return StatusCode::FAILURE;
885  }
887  {
888  ATH_MSG_FATAL("Please check that the track assisted mass resolution 3D histogram is provided");
889  return StatusCode::FAILURE;
890  }
891 
892  if ( ( ( !m_use3Dhisto && absdetectorEta < m_massCombinationEtaBins.back() ) ||
893  ( m_use3Dhisto && absdetectorEta < m_caloResolutionMassCombination3D->GetZaxis()->GetBinLowEdge(m_caloResolutionMassCombination3D->GetNbinsZ()+1)) ) ) {
894 
895  if (!m_use3Dhisto)
896  {
897  for (uint i=0; i<m_massCombinationEtaBins.size()-1; ++i) {
898  if(absdetectorEta >= m_massCombinationEtaBins[i] && absdetectorEta < m_massCombinationEtaBins[i+1]) etabin = i;
899  }
900  if (etabin< 0){
901  ATH_MSG_FATAL("There was a problem determining the eta bin to use for the mass combination");
902  return StatusCode::FAILURE;
903  }
904  }
905 
906  // Use the correct histogram binning parametrisation when reading the combined mass weights
907  double relCalo = 0;
908  double relTA = 0;
909  double rho = 0;
910  switch (m_binParam)
911  {
913  if (m_use3Dhisto)
914  {
915  relCalo = getRelCalo3D( pT_calo/m_GeV, mass_calo/pT_calo, absdetectorEta );
916  relTA = getRelTA3D( pT_calo/m_GeV, mass_ta/pT_calo, absdetectorEta );
918  rho = getRho3D( pT_calo/m_GeV, mass_calo/pT_calo, absdetectorEta );
919  }
920  else
921  {
922  relCalo = getRelCalo( pT_calo/m_GeV, mass_calo/pT_calo, etabin );
923  relTA = getRelTA( pT_calo/m_GeV, mass_ta/pT_calo, etabin );
925  rho = getRho( pT_calo/m_GeV, mass_calo/pT_calo, etabin );
926  }
927  break;
929  if (m_use3Dhisto)
930  {
931  relCalo = mass_calo/E_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/E_calo), absdetectorEta ) : 0;
932  relTA = mass_ta/E_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/E_calo), absdetectorEta ) : 0;
934  rho = mass_calo/E_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/E_calo), absdetectorEta ) : 0;
935  }
936  else
937  {
938  relCalo = mass_calo/E_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/E_calo), etabin ) : 0;
939  relTA = mass_ta/E_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/E_calo), etabin ) : 0;
941  rho = mass_calo/E_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/E_calo), etabin ) : 0;
942  }
943  break;
945  if (m_use3Dhisto)
946  {
947  relCalo = mass_calo/Et_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
948  relTA = mass_ta/Et_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/Et_calo), absdetectorEta ) : 0;
950  rho = mass_calo/Et_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
951  }
952  else
953  {
954  relCalo = mass_calo/Et_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
955  relTA = mass_ta/Et_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/Et_calo), etabin ) : 0;
957  rho = mass_calo/Et_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
958  }
959  break;
961  if (m_use3Dhisto)
962  {
963  relCalo = mass_calo/pT_calo > 0 ? getRelCalo3D( E_calo/m_GeV, std::log(mass_calo/pT_calo), absdetectorEta ) : 0;
964  relTA = mass_ta/pT_calo > 0 ? getRelTA3D( E_calo/m_GeV, std::log(mass_ta/pT_calo), absdetectorEta ) : 0;
966  rho = mass_calo/pT_calo > 0 ? getRho3D( E_calo/m_GeV, std::log(mass_calo/pT_calo), absdetectorEta ) : 0;
967  }
968  else
969  {
970  relCalo = mass_calo/pT_calo > 0 ? getRelCalo( E_calo/m_GeV, std::log(mass_calo/pT_calo), etabin ) : 0;
971  relTA = mass_ta/pT_calo > 0 ? getRelTA( E_calo/m_GeV, std::log(mass_ta/pT_calo), etabin ) : 0;
973  rho = mass_calo/pT_calo > 0 ? getRho( E_calo/m_GeV, std::log(mass_calo/pT_calo), etabin ) : 0;
974  }
975  break;
977  if (m_use3Dhisto)
978  {
979  relCalo = mass_calo/Et_calo > 0 ? getRelCalo3D( Et_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
980  relTA = mass_ta/Et_calo > 0 ? getRelTA3D( Et_calo/m_GeV, std::log(mass_ta/Et_calo), absdetectorEta ) : 0;
982  rho = mass_calo/Et_calo > 0 ? getRho3D( Et_calo/m_GeV, std::log(mass_calo/Et_calo), absdetectorEta ) : 0;
983  }
984  else
985  {
986  relCalo = mass_calo/Et_calo > 0 ? getRelCalo( Et_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
987  relTA = mass_ta/Et_calo > 0 ? getRelTA( Et_calo/m_GeV, std::log(mass_ta/Et_calo), etabin ) : 0;
989  rho = mass_calo/Et_calo > 0 ? getRho( Et_calo/m_GeV, std::log(mass_calo/Et_calo), etabin ) : 0;
990  }
991  break;
992  default:
993  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.");
994  return StatusCode::FAILURE;
995  break;
996  }
997 
998  // Watch for division by zero
999  if(m_useCorrelatedWeights && (relCalo*relCalo + relTA*relTA - 2 * rho* relCalo * relTA == 0)){
1000  ATH_MSG_ERROR("Encountered division by zero when calculating mass combination weight using correlated weights");
1001  return StatusCode::FAILURE;
1002  }
1003  const double Weight = ( relTA*relTA - rho *relCalo*relTA ) / ( relCalo*relCalo + relTA*relTA - 2 * rho* relCalo * relTA );
1004 
1005  // Zero should be only returned by resolution functions if jet mass is negative
1006  if(relCalo == 0 && relTA == 0)
1007  Mass_comb = 0;
1008  else if(relCalo == 0)
1009  Mass_comb = mass_ta;
1010  else if(relTA == 0)
1011  Mass_comb = mass_calo;
1012  else
1013  Mass_comb = ( mass_calo * Weight ) + ( mass_ta * ( 1 - Weight) );
1014  // Protection
1015  if(Mass_comb>jetStartP4.e()) Mass_comb = mass_calo;
1016  else if(!m_pTfixed) pT_calo = std::sqrt(jetStartP4.e()*jetStartP4.e()-mass_calo*mass_calo)/std::cosh( jetStartP4.eta() );
1017  }
1018  }
1019 
1020  TLorentzVector TLVjet;
1021  TLVjet.SetPtEtaPhiM( pT_calo, jetStartP4.eta(), jetStartP4.phi(), Mass_comb );
1022  calibP4.SetPxPyPzE( TLVjet.Px(), TLVjet.Py(), TLVjet.Pz(), TLVjet.E() );
1023 
1024  //Transfer calibrated jet properties to the Jet object
1025  jet.setAttribute<xAOD::JetFourMom_t>(m_jetOutScale.Data(),calibP4);
1026  jet.setJetP4( calibP4 );
1027 
1028  } //m_combination
1029 
1030  return StatusCode::SUCCESS;
1031 
1032 }
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
JMSCorrection::getRelCalo3D
float getRelCalo3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
Definition: JMSCorrection.cxx:383
JMSCorrection::getRelTA
float getRelTA(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
Definition: JMSCorrection.cxx:446
JMSCorrection.h
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
skel.rel
rel
Announce start of JO checkingrelease nimber checking.
Definition: skel.GENtoEVGEN.py:182
JMSCorrection::m_taResolutionMassCombination
VecTH2 m_taResolutionMassCombination
Definition: JMSCorrection.h:92
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
mTA
double mTA(const double trackMass, const double trackPt, const double caloPt)
Definition: JetCalibTools_PlotJMSFactors.cxx:40
JetCalibrationStep::setStartP4
virtual StatusCode setStartP4(xAOD::Jet &jet) const
Definition: JetCalibrationStep.cxx:21
mapkey::uncorr
@ uncorr
Definition: TElectronEfficiencyCorrectionTool.cxx:41
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
JetCalibUtils::GetHisto2
std::unique_ptr< const TH2 > GetHisto2(TFile &file, const TString &hname)
Definition: JetCalibUtils.cxx:53
JMSCorrection::m_respFactorsTrackAssistedMass
VecTH2 m_respFactorsTrackAssistedMass
Definition: JMSCorrection.h:89
JMSCorrection::m_pTfixed
bool m_pTfixed
Definition: JMSCorrection.h:71
JMSCorrection::m_correlationMapMassCombination3D
std::unique_ptr< const TH3 > m_correlationMapMassCombination3D
Definition: JMSCorrection.h:100
xAOD::etaMax
etaMax
Definition: HIEventShape_v2.cxx:46
JMSCorrection::calibrate
virtual StatusCode calibrate(xAOD::Jet &jet, JetEventInfo &) const override
Definition: JMSCorrection.cxx:505
JMSCorrection::m_taResolutionMassCombination3D
std::unique_ptr< const TH3 > m_taResolutionMassCombination3D
Definition: JMSCorrection.h:99
JMSCorrection::m_jetOutScale
TString m_jetOutScale
Definition: JMSCorrection.h:64
JMSCorrection::setMassCombinationEtaBins
void setMassCombinationEtaBins(const VecD &etabins)
Definition: JMSCorrection.h:55
JMSCorrection::BinningParam::et_LOGmOet_eta
@ et_LOGmOet_eta
JMSCorrection::m_trackAssistedJetMassCorr
bool m_trackAssistedJetMassCorr
Definition: JMSCorrection.h:69
JMSCorrection::getMassCorr3D
float getMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
Definition: JMSCorrection.cxx:301
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
JetEventInfo
Definition: JetEventInfo.h:8
JMSCorrection::m_calibAreaTag
TString m_calibAreaTag
Definition: JMSCorrection.h:64
JMSCorrection::m_useCorrelatedWeights
bool m_useCorrelatedWeights
Definition: JMSCorrection.h:74
JMSCorrection::m_respFactorMass3D
std::unique_ptr< const TH3 > m_respFactorMass3D
Definition: JMSCorrection.h:96
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
JMSCorrection::BinningParam::e_LOGmOet_eta
@ e_LOGmOet_eta
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
JMSCorrection::m_onlyCombination
bool m_onlyCombination
Definition: JMSCorrection.h:75
JMSCorrection::getRho3D
float getRho3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
Definition: JMSCorrection.cxx:464
CaloCondBlobAlgs_fillNoiseFromASCII.inputFile
string inputFile
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:17
lumiFormat.i
int i
Definition: lumiFormat.py:85
JMSCorrection::getRho
float getRho(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
Definition: JMSCorrection.cxx:486
RootHelpers.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
JMSCorrection::m_combination
bool m_combination
Definition: JMSCorrection.h:73
JMSCorrection::m_massEtaBins
VecD m_massEtaBins
Definition: JMSCorrection.h:88
JetCalibUtils::GetHisto3
std::unique_ptr< const TH3 > GetHisto3(TFile &file, const TString &hname)
Definition: JetCalibUtils.cxx:57
JMSCorrection::m_respFactorsMass
VecTH2 m_respFactorsMass
Definition: JMSCorrection.h:87
RootHelpers::Interpolate
double Interpolate(const TH1 *histo, const double x)
Definition: RootHelpers.cxx:39
JMSCorrection::m_massCombinationEtaBins
VecD m_massCombinationEtaBins
Definition: JMSCorrection.h:90
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
JMSCorrection::getRelTA3D
float getRelTA3D(double pT_uncorr, double mass_over_pt_uncorr, double eta) const
Definition: JMSCorrection.cxx:424
JMSCorrection::initialize
virtual StatusCode initialize() override
Definition: JMSCorrection.cxx:36
JMSCorrection::BinningParam::e_LOGmOe_eta
@ e_LOGmOe_eta
JMSCorrection::JMSCorrection
JMSCorrection()
Definition: JMSCorrection.cxx:25
JMSCorrection::getMassCorr
float getMassCorr(double pT_uncorr, double mass_uncorr, int etabin) const
Definition: JMSCorrection.cxx:323
JMSCorrection::getRelCalo
float getRelCalo(double pT_uncorr, double mass_over_pt_uncorr, int etabin) const
Definition: JMSCorrection.cxx:405
xAOD::JetFourMom_t
ROOT::Math::LorentzVector< ROOT::Math::PtEtaPhiM4D< double > > JetFourMom_t
Base 4 Momentum type for Jet.
Definition: JetTypes.h:17
PathResolver.h
JetCalibUtils.h
JetCalibrationStep::m_jetStartScale
std::string m_jetStartScale
Definition: JetCalibrationStep.h:41
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
JMSCorrection::m_jetAlgo
TString m_jetAlgo
Definition: JMSCorrection.h:64
JMSCorrection::m_pTMinCorr
double m_pTMinCorr
Definition: JMSCorrection.h:67
JMSCorrection::getTrackAssistedMassCorr
float getTrackAssistedMassCorr(double pT_uncorr, double mass_uncorr, int etabin) const
Definition: JMSCorrection.cxx:364
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
JMSCorrection::setMassEtaBins
void setMassEtaBins(const VecD &etabins)
Definition: JMSCorrection.h:50
LArCellBinning.etaMin
etaMin
Definition: LArCellBinning.py:84
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
JMSCorrection::m_binParam
BinningParam m_binParam
Definition: JMSCorrection.h:79
JMSCorrection::m_correlationMapMassCombination
VecTH2 m_correlationMapMassCombination
Definition: JMSCorrection.h:93
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
JMSCorrection::m_config
TEnv * m_config
Definition: JMSCorrection.h:63
JMSCorrection::getTrackAssistedMassCorr3D
float getTrackAssistedMassCorr3D(double pT_uncorr, double mass_uncorr, double eta) const
Definition: JMSCorrection.cxx:342
JMSCorrection::BinningParam::pt_mass_eta
@ pt_mass_eta
JMSCorrection::BinningParam::e_LOGmOpt_eta
@ e_LOGmOpt_eta
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
JMSCorrection::m_respFactorTrackAssistedMass3D
std::unique_ptr< const TH3 > m_respFactorTrackAssistedMass3D
Definition: JMSCorrection.h:97
JetCalibUtils::VectorizeD
VecD VectorizeD(const TString &str, const TString &sep=" ")
Definition: JetCalibUtils.cxx:25
JMSCorrection::m_use3Dhisto
bool m_use3Dhisto
Definition: JMSCorrection.h:83
JMSCorrection::m_caloResolutionMassCombination
VecTH2 m_caloResolutionMassCombination
Definition: JMSCorrection.h:91
JMSCorrection::uint
unsigned int uint
Definition: JMSCorrection.h:30
JMSCorrection::m_caloResolutionMassCombination3D
std::unique_ptr< const TH3 > m_caloResolutionMassCombination3D
Definition: JMSCorrection.h:98
fitman.rho
rho
Definition: fitman.py:532
JMSCorrection::m_dev
bool m_dev
Definition: JMSCorrection.h:65
JetCalibrationStep::m_GeV
double m_GeV
Definition: JetCalibrationStep.h:40
JetCalibrationStep
Definition: JetCalibrationStep.h:20