BlockB.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 
20 #include <momemta/ParameterSet.h>
21 #include <momemta/Module.h>
22 #include <momemta/Solution.h>
23 #include <momemta/Types.h>
24 #include <momemta/Math.h>
25 
26 
86 class BlockB: public Module {
87  public:
88 
89  BlockB(PoolPtr pool, const ParameterSet& parameters): Module(pool, parameters.getModuleName()) {
90 
91  sqrt_s = parameters.globalParameters().get<double>("energy");
92  pT_is_met = parameters.get<bool>("pT_is_met", false);
93 
94  m1 = parameters.get<double>("m1", 0.);
95 
96  s12 = get<double>(parameters.get<InputTag>("s12"));
97 
98  p2 = get<LorentzVector>(parameters.get<InputTag>("p2"));
99 
100  if (parameters.exists("branches")) {
101  auto branches_tags = parameters.get<std::vector<InputTag>>("branches");
102  for (auto& t: branches_tags)
103  m_branches.push_back(get<LorentzVector>(t));
104  }
105 
106  // If the met input is specified, get it, otherwise retrieve default
107  // one ("met::p4")
108  InputTag met_tag;
109  if (parameters.exists("met")) {
110  met_tag = parameters.get<InputTag>("met");
111  } else {
112  met_tag = InputTag({"met", "p4"});
113  }
114 
115  m_met = get<LorentzVector>(met_tag);
116  };
117 
118  virtual Status work() override {
119 
120  solutions->clear();
121 
122  // Equations to solve:
123  //(1) (p1 + p2)^2 = s12 = M1^2 + M2^2 + 2 E1 E2 - 2 p1x p2x - 2 p1y p2y - 2 p1z p2z
124  //(2) p1x = - pTx #Coming from pT neutrino = -pT visible = - (p2 + ISR)
125  //(3) p1y = - pTy #Coming from pT neutrino = -pT visible = - (p2 + ISR)
126  //(4) E1^2 - p1x^2 - p1y^2 - p1z^2 = M1^2
127 
128  const double p11 = SQ(m1);
129  const double p22 = p2->M2();
130 
131  // Don't spend time on unphysical part of phase-space
132  if (*s12 >= SQ(sqrt_s) || *s12 <= p11 + p22)
133  return Status::NEXT;
134 
135  LorentzVector pT;
136  if (pT_is_met) {
137  pT = - *m_met;
138  } else {
139  pT = *p2;
140  for (size_t i = 0; i < m_branches.size(); i++) {
141  pT += *m_branches[i];
142  }
143  }
144 
145  // From eq.(1) p1z = B*E1 + A
146  // From eq.(4) + eq.(1) (1 - B^2) E1^2 - 2 A B E1 + C - A^2 - M1^2 = 0
147 
148  const double A = - (*s12 - p11 - p22 - 2 * (pT.Px() * p2->Px() + pT.Py() * p2->Py())) / (2 * p2->Pz());
149  const double B = p2->E() / p2->Pz();
150  const double C = - SQ(pT.Px()) - SQ(pT.Py());
151 
152  // Solve quadratic a*E1^2 + b*E1 + c = 0
153  const double a = 1 - SQ(B);
154  const double b = - 2 * A * B;
155  const double c = C - SQ(A) - p11;
156 
157  std::vector<double> E1;
158 
159  solveQuadratic(a, b, c, E1, false);
160 
161  if (E1.size() == 0)
162  return Status::NEXT;
163 
164  for (unsigned int i = 0; i < E1.size(); i++){
165  const double e1 = E1.at(i);
166 
167  if (e1 <= 0) continue;
168 
169  LorentzVector p1(-pT.Px(), -pT.Py(), A + B*e1, e1);
170 
171  // Check if solutions are physical
172  LorentzVector tot = p1 + *p2;
173  for (size_t i = 0; i < m_branches.size(); i++)
174  tot += *m_branches[i];
175  double q1Pz = std::abs(tot.Pz() + tot.E()) / 2.;
176  double q2Pz = std::abs(tot.Pz() - tot.E()) / 2.;
177  if (q1Pz > sqrt_s / 2 || q2Pz > sqrt_s / 2)
178  continue;
179 
180  if (!ApproxComparison(p1.M() / p1.E(), m1 / p1.E())) {
181 #ifndef NDEBUG
182  LOG(trace) << "[BlockB] Throwing solution because of invalid mass. " <<
183  "Expected " << m1 << ", got " << p1.M();
184 #endif
185  continue;
186  }
187 
188  if (!ApproxComparison((p1 + *p2).M2(), *s12)) {
189 #ifndef NDEBUG
190  LOG(trace) << "[BlockB] Throwing solution because of invalid invariant mass. " <<
191  "Expected " << *s12 << ", got " << (p1 + *p2).M2();
192 #endif
193  continue;
194  }
195 
196  const double inv_jacobian = SQ(sqrt_s) * std::abs(p2->Pz() * e1 - p2->E() * p1.Pz());
197 
198  Solution s { {p1}, M_PI / inv_jacobian, true };
199  solutions->push_back(s);
200  }
201 
202  return solutions->size() > 0 ? Status::OK : Status::NEXT;
203  }
204 
205  private:
206  double sqrt_s;
207  bool pT_is_met;
208  double m1;
209 
210  // Inputs
211  Value<double> s12;
213  std::vector<Value<LorentzVector>> m_branches;
214  Value<LorentzVector> m_met;
215 
216  // Outputs
217  std::shared_ptr<SolutionCollection> solutions = produce<SolutionCollection>("solutions");
218 };
219 
220 REGISTER_MODULE(BlockB)
221  .Input("s12")
222  .Input("p2")
223  .OptionalInputs("branches")
224  .Input("met=met::p4")
225  .Output("solutions")
226  .GlobalAttr("energy:double")
227  .Attr("pT_is_met:bool=false")
228  .Attr("m1:double=0.");
bool ApproxComparison(double value, double expected)
Compare two doubles and return true if they are approximatively equal.
Definition: Math.cc:409
Generic solution structure representing a set of particles, along with its jacobian.
Definition: Solution.h:28
Mathematical functions.
bool solveQuadratic(const double a, const double b, const double c, std::vector< double > &roots, bool verbose=false)
Finds the real solutions to .
Definition: Math.cc:26
virtual Status work() override
Main function.
Definition: BlockB.cc:118
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
Final (main) Block B, describing
Definition: BlockB.cc:86