BinnedTransferFunctionOnPt.cc
1 /*
2  * MoMEMta: a modular implementation of the Matrix Element Method
3  * Copyright (C) 2016 Universite catholique de Louvain (UCL), Belgium
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <momemta/Logging.h>
20 #include <momemta/Module.h>
21 #include <momemta/ParameterSet.h>
22 #include <momemta/Types.h>
23 #include <momemta/Math.h>
24 
25 #include <TFile.h>
26 #include <TH2.h>
27 #include <TAxis.h>
28 
38  public:
39 
40  BinnedTransferFunctionOnPtBase(PoolPtr pool, const ParameterSet& parameters): Module(pool, parameters.getModuleName()) {
41  m_reco_input = get<LorentzVector>(parameters.get<InputTag>("reco_particle"));
42 
43  std::string file_path = parameters.get<std::string>("file");
44  std::string th2_name = parameters.get<std::string>("th2_name");
45 
46  std::unique_ptr<TFile> file(TFile::Open(file_path.c_str()));
47  if(!file->IsOpen() || file->IsZombie())
48  throw file_not_found_error("Could not open file " + file_path);
49 
50  m_th2 = std::unique_ptr<TH2>(static_cast<TH2*>(file->Get(th2_name.c_str())));
51  if(!m_th2->InheritsFrom("TH2") || !m_th2.get())
52  throw th2_not_found_error("Could not retrieve object " + th2_name + " deriving from class TH2 in file " + file_path + ".");
53  m_th2->SetDirectory(0);
54 
55  TAxis* yAxis = m_th2->GetYaxis();
56  m_deltaMin = yAxis->GetXmin();
57  m_deltaMax = yAxis->GetXmax();
58  m_deltaRange = m_deltaMax - m_deltaMin;
59 
60  TAxis* xAxis = m_th2->GetXaxis();
61  double Pt_cut = parameters.get<double>("min_Pt", 0.);
62  m_PtgenMin = std::max(xAxis->GetXmin(), Pt_cut);
63  m_PtgenMax = xAxis->GetXmax();
64 
65  // Since we assume the TF continues as a constant for Pt->infty,
66  // we need to be able to retrieve the X axis' last bin, to avoid
67  // fetching the TH2's overflow bin.
68  m_fallBackPtgenMax = xAxis->GetBinCenter(xAxis->GetNbins());
69 
70  LOG(debug) << "Loaded TH2 " << th2_name << " from file " << file_path << ".";
71  LOG(debug) << "\tDelta range is " << m_deltaMin << " to " << m_deltaMax << ".";
72  LOG(debug) << "\tPt range is " << m_PtgenMin << " to " << m_PtgenMax << ".";
73  LOG(debug) << "\tWill use values at Ptgen = " << m_fallBackPtgenMax << " for out-of-range values.";
74 
75  file->Close();
76  file.reset();
77  };
78 
79  protected:
80  std::unique_ptr<TH2> m_th2;
81 
82  double m_deltaMin, m_deltaMax, m_deltaRange;
83  double m_PtgenMin, m_PtgenMax;
84  double m_fallBackPtgenMax;
85 
86  // Input
87  Value<LorentzVector> m_reco_input;
88 
89  private:
90  class file_not_found_error: public std::runtime_error{
91  using std::runtime_error::runtime_error;
92  };
93 
94  class th2_not_found_error: public std::runtime_error{
95  using std::runtime_error::runtime_error;
96  };
97 };
98 
143  public:
144 
145  BinnedTransferFunctionOnPt(PoolPtr pool, const ParameterSet& parameters): BinnedTransferFunctionOnPtBase(pool, parameters) {
146  m_ps_point = get<double>(parameters.get<InputTag>("ps_point"));
147  }
148 
149  virtual Status work() override {
150  const double rec_Pt = m_reco_input->Pt();
151  const double cosh_eta = std::cosh(m_reco_input->Eta());
152  const double range = GetDeltaRange(rec_Pt);
153  const double gen_Pt = rec_Pt - GetDeltaMax(rec_Pt) + range * (*m_ps_point);
154  const double delta = rec_Pt - gen_Pt;
155 
156  // To change the particle's Pt without changing its direction and mass:
157  const double gen_E = std::sqrt(SQ(m_reco_input->M()) + SQ(cosh_eta * gen_Pt));
158  output->SetCoordinates(
159  gen_Pt * std::cos(m_reco_input->Phi()),
160  gen_Pt * std::sin(m_reco_input->Phi()),
161  gen_Pt * std::sinh(m_reco_input->Eta()),
162  gen_E);
163 
164  // The bin number is a ROOT "global bin number" using a 1D representation of the TH2
165  const int bin = m_th2->FindFixBin(std::min(gen_Pt, m_fallBackPtgenMax), delta);
166 
167  // Compute TF*jacobian, where the jacobian includes the transformation of [0,1]->[range_min,range_max] and d|P|/dP_T = cosh(eta)
168  *TF_times_jacobian = m_th2->GetBinContent(bin) * range * cosh_eta;
169 
170  return Status::OK;
171  }
172 
173  private:
174 
175  // Input
176  Value<double> m_ps_point;
177 
178  // Outputs
179  std::shared_ptr<LorentzVector> output = produce<LorentzVector>("output");
180  std::shared_ptr<double> TF_times_jacobian = produce<double>("TF_times_jacobian");
181 
182  // We assume TF=0 for Ptgen < lower limit of the TH2, and
183  // TF=constant for Ptgen > upper limit of the TH2
184  // In the former case, the integrated range is adapted (shortened) to the range where TF!=0
185  inline double GetDeltaRange(const double Ptrec) const {
186  return GetDeltaMax(Ptrec) - m_deltaMin;
187  }
188 
189  inline double GetDeltaMax(const double Ptrec) const {
190  return std::min(m_deltaMax, Ptrec - m_PtgenMin);
191  }
192 };
193 
232  public:
233 
234  BinnedTransferFunctionOnPtEvaluator(PoolPtr pool, const ParameterSet& parameters): BinnedTransferFunctionOnPtBase(pool, parameters) {
235  m_gen_input = get<LorentzVector>(parameters.get<InputTag>("gen_particle"));
236  }
237 
238  virtual Status work() override {
239  const double rec_Pt = m_reco_input->Pt();
240  const double gen_Pt = m_gen_input->Pt();
241  double delta = rec_Pt - gen_Pt;
242  if (delta <= m_deltaMin || delta >= m_deltaMax) {
243  *TF_value = 0;
244  return Status::OK;
245  }
246 
247  // The bin number is a ROOT "global bin number" using a 1D representation of the TH2
248  const int bin = m_th2->FindFixBin(std::min(gen_Pt, m_fallBackPtgenMax), delta);
249 
250  // Retrieve TF value
251  *TF_value = m_th2->GetBinContent(bin);
252 
253  return Status::OK;
254  }
255 
256  private:
257 
258  // Input
259  Value<LorentzVector> m_gen_input;
260 
261  // Outputs
262  std::shared_ptr<double> TF_value = produce<double>("TF");
263 };
264 
265 REGISTER_MODULE(BinnedTransferFunctionOnPt)
266  .Input("reco_particle")
267  .Input("ps_point")
268  .Output("output")
269  .Output("TF_times_jacobian")
270  .Attr("file:string")
271  .Attr("th2_name:string")
272  .Attr("min_Pt:double=0");
273 
275  .Input("reco_particle")
276  .Input("gen_particle")
277  .Output("TF")
278  .Attr("file:string")
279  .Attr("th2_name:string")
280  .Attr("min_Pt:double=0");
virtual Status work() override
Main function.
Mathematical functions.
Helper class for binned transfer function modules.
virtual Status work() override
Main function.
Integrate over a transfer function on Pt described by a 2D histogram retrieved from a ROOT file...
Evaluate a transfer function on Pt described by a 2D histogram retrieved from a ROOT file...
An identifier of a module&#39;s output.
Definition: InputTag_fwd.h:37
Parent class for all the modules.
Definition: Module.h:37
A class encapsulating a lua table.
Definition: ParameterSet.h:82
#define SQ(x)
Compute .
Definition: Math.h:25
Module(PoolPtr pool, const std::string &name)
Constructor.
Definition: Module.h:61