Loading [MathJax]/extensions/tex2jax.js

Search Results

 /*
  *  MoMEMta: a modular implementation of the Matrix Element Method
  *  Copyright (C) 2016  Universite catholique de Louvain (UCL), Belgium
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 #include <momemta/ParameterSet.h>
 #include <momemta/Module.h>
 #include <momemta/Solution.h>
 #include <momemta/Types.h>
 #include <momemta/Math.h>
 
 
 class BlockB: public Module {
     public:
 
         BlockB(PoolPtr pool, const ParameterSet& parameters): Module(pool, parameters.getModuleName()) {
 
             sqrt_s = parameters.globalParameters().get<double>("energy");
             pT_is_met = parameters.get<bool>("pT_is_met", false);
 
             m1 = parameters.get<double>("m1", 0.);
 
             s12 = get<double>(parameters.get<InputTag>("s12"));
 
             p2 = get<LorentzVector>(parameters.get<InputTag>("p2"));
 
             if (parameters.exists("branches")) {
                 auto branches_tags = parameters.get<std::vector<InputTag>>("branches");
                 for (auto& t: branches_tags)
                     m_branches.push_back(get<LorentzVector>(t));
             }
 
             // If the met input is specified, get it, otherwise retrieve default
             // one ("met::p4")
             InputTag met_tag;
             if (parameters.exists("met")) {
                 met_tag = parameters.get<InputTag>("met");
             } else {
                 met_tag = InputTag({"met", "p4"});
             }
 
             m_met = get<LorentzVector>(met_tag);
         };
 
         virtual Status work() override {
 
             solutions->clear();
 
             // Equations to solve:
             //(1) (p1 + p2)^2 = s12 = M1^2 + M2^2 + 2 E1 E2 - 2 p1x p2x - 2 p1y p2y - 2 p1z p2z
             //(2)  p1x = - pTx  #Coming from pT neutrino = -pT visible = - (p2 + ISR)
             //(3)  p1y = - pTy  #Coming from pT neutrino = -pT visible = - (p2 + ISR)
             //(4)  E1^2 - p1x^2 - p1y^2 - p1z^2 = M1^2
 
             const double p11 = SQ(m1);
             const double p22 = p2->M2();
 
             // Don't spend time on unphysical part of phase-space
             if (*s12 >= SQ(sqrt_s) || *s12 <= p11 + p22)
                 return Status::NEXT;
 
             LorentzVector pT;
             if (pT_is_met) {
                 pT = - *m_met;
             } else {
                 pT = *p2;
                 for (size_t i = 0; i < m_branches.size(); i++) {
                     pT += *m_branches[i];
                 }
             }
 
             // From eq.(1) p1z = B*E1 + A
             // From eq.(4) + eq.(1) (1 - B^2) E1^2 - 2 A B E1 + C - A^2 - M1^2 = 0
 
             const double A = - (*s12 - p11 - p22 - 2 * (pT.Px() * p2->Px() + pT.Py() * p2->Py())) / (2 * p2->Pz());
             const double B = p2->E() / p2->Pz();
             const double C = - SQ(pT.Px()) - SQ(pT.Py());
 
             // Solve quadratic a*E1^2 + b*E1 + c = 0
             const double a = 1 - SQ(B);
             const double b = - 2 * A * B;
             const double c = C - SQ(A) - p11;
 
             std::vector<double> E1;
 
             solveQuadratic(a, b, c, E1, false);
 
             if (E1.size() == 0)
                 return Status::NEXT;
 
             for (unsigned int i = 0; i < E1.size(); i++){
                 const double e1 = E1.at(i);
 
                 if (e1 <= 0) continue;
 
                 LorentzVector p1(-pT.Px(), -pT.Py(), A + B*e1, e1);
 
                 // Check if solutions are physical
                 LorentzVector tot = p1 + *p2;
                 for (size_t i = 0; i < m_branches.size(); i++)
                     tot += *m_branches[i];
                 double q1Pz = std::abs(tot.Pz() + tot.E()) / 2.;
                 double q2Pz = std::abs(tot.Pz() - tot.E()) / 2.;
                 if (q1Pz > sqrt_s / 2 || q2Pz > sqrt_s / 2)
                     continue;
 
                 if (!ApproxComparison(p1.M() / p1.E(), m1 / p1.E())) {
 #ifndef NDEBUG
                     LOG(trace) << "[BlockB] Throwing solution because of invalid mass. " <<
                                "Expected " << m1 << ", got " << p1.M();
 #endif
                     continue;
                 }
 
                 if (!ApproxComparison((p1 + *p2).M2(), *s12)) {
 #ifndef NDEBUG
                     LOG(trace) << "[BlockB] Throwing solution because of invalid invariant mass. " <<
                                "Expected " << *s12 << ", got " << (p1 + *p2).M2();
 #endif
                     continue;
                 }
 
                 const double inv_jacobian = SQ(sqrt_s) * std::abs(p2->Pz() * e1 - p2->E() * p1.Pz());
 
                 Solution s { {p1}, M_PI / inv_jacobian, true };
                 solutions->push_back(s);
             }
 
             return solutions->size() > 0 ? Status::OK : Status::NEXT;
         }
 
     private:
         double sqrt_s;
         bool pT_is_met;
         double m1;
 
         // Inputs
         Value<double> s12;
         Value<LorentzVector> p2;
         std::vector<Value<LorentzVector>> m_branches;
         Value<LorentzVector> m_met;
 
         // Outputs
         std::shared_ptr<SolutionCollection> solutions = produce<SolutionCollection>("solutions");
 };
 
 REGISTER_MODULE(BlockB)
         .Input("s12")
         .Input("p2")
         .OptionalInputs("branches")
         .Input("met=met::p4")
         .Output("solutions")
         .GlobalAttr("energy:double")
         .Attr("pT_is_met:bool=false")
         .Attr("m1:double=0.");
All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Modules Pages