20 #include <momemta/Logging.h> 21 #include <momemta/ParameterSet.h> 22 #include <momemta/Module.h> 23 #include <momemta/Solution.h> 24 #include <momemta/Types.h> 25 #include <momemta/Utils.h> 28 #include <Math/GenVector/VectorUtil.h> 84 sqrt_s = parameters.globalParameters().get<
double>(
"energy");
86 s12 = get<double>(parameters.get<
InputTag>(
"s12"));
87 s34 = get<double>(parameters.get<
InputTag>(
"s34"));
89 m_particles.push_back(get<LorentzVector>(parameters.get<
InputTag>(
"p1")));
90 m_particles.push_back(get<LorentzVector>(parameters.get<
InputTag>(
"p2")));
91 m_particles.push_back(get<LorentzVector>(parameters.get<
InputTag>(
"p3")));
92 m_particles.push_back(get<LorentzVector>(parameters.get<
InputTag>(
"p4")));
94 if (parameters.exists(
"branches")) {
95 auto branches_tags = parameters.get<std::vector<InputTag>>(
"branches");
96 for (
auto& t: branches_tags)
97 m_branches.push_back(get<LorentzVector>(t));
101 virtual Status
work()
override {
105 if (*s12 + *s34 >=
SQ(sqrt_s))
108 const LorentzVector& p1 = *m_particles[0];
109 const LorentzVector& p2 = *m_particles[1];
110 const LorentzVector& p3 = *m_particles[2];
111 const LorentzVector& p4 = *m_particles[3];
114 for (
size_t i = 0; i < m_branches.size(); i++) {
115 pb += *m_branches[i];
118 const double pbx = pb.Px();
119 const double pby = pb.Py();
120 const double sin_theta_1 = std::sin(p1.Theta());
121 const double sin_theta_2 = std::sin(p2.Theta());
122 const double sin_theta_3 = std::sin(p3.Theta());
123 const double sin_theta_4 = std::sin(p4.Theta());
124 const double phi_1 = p1.Phi();
125 const double phi_2 = p2.Phi();
126 const double phi_3 = p3.Phi();
127 const double phi_4 = p4.Phi();
128 const double sin_phi_3_2 = std::sin(phi_3 - phi_2);
129 const double sin_phi_2_1 = std::sin(phi_2 - phi_1);
130 const double sin_phi_4_2 = std::sin(phi_4 - phi_2);
131 const double sin_phi_1_3 = std::sin(phi_1 - phi_3);
132 const double sin_phi_1_4 = std::sin(phi_1 - phi_4);
139 const double denom_1 = sin_theta_1 * sin_phi_2_1;
140 const double denom_2 = sin_theta_2 * sin_phi_2_1;
142 const double alpha_1 = sin_theta_3 * sin_phi_3_2 / denom_1;
143 const double beta_1 = sin_theta_4 * sin_phi_4_2 / denom_1;
144 const double gamma_1 = ( std::cos(phi_2) * pby - std::sin(phi_2) * pbx ) / denom_1;
146 const double alpha_2 = sin_theta_3 * sin_phi_1_3 / denom_2;
147 const double beta_2 = sin_theta_4 * sin_phi_1_4 / denom_2;
148 const double gamma_2 = ( std::sin(phi_1) * pbx - std::cos(phi_1) * pby ) / denom_2;
150 const double cos_theta_34 = ROOT::Math::VectorUtil::CosTheta(p3, p4);
151 const double cos_theta_12 = ROOT::Math::VectorUtil::CosTheta(p1, p2);
152 const double X = 0.5 * (*s34) / (1 - cos_theta_34);
153 const double Y = 0.5 * (*s12) / (1 - cos_theta_12);
155 std::vector<double> gen_p3_solutions;
158 alpha_1 * gamma_2 + gamma_1 * alpha_2,
159 gamma_1 * gamma_2 + (beta_1 * alpha_2 + alpha_1 * beta_2) * X - Y,
160 (beta_1 * gamma_2 + gamma_1 * beta_2) * X,
161 beta_1 * beta_2 *
SQ(X),
165 for (
const auto& p3_sol: gen_p3_solutions) {
167 const double p4_sol = X / p3_sol;
168 const double p1_sol = alpha_1 * p3_sol + beta_1 * p4_sol + gamma_1;
169 const double p2_sol = alpha_2 * p3_sol + beta_2 * p4_sol + gamma_2;
171 if (p1_sol < 0 || p2_sol < 0 || p3_sol < 0 || p4_sol < 0)
174 LorentzVector gen_p1(p1_sol * sin_theta_1 * std::cos(phi_1), p1_sol * sin_theta_1 * std::sin(phi_1), p1_sol * std::cos(p1.Theta()), p1_sol);
175 LorentzVector gen_p2(p2_sol * sin_theta_2 * std::cos(phi_2), p2_sol * sin_theta_2 * std::sin(phi_2), p2_sol * std::cos(p2.Theta()), p2_sol);
176 LorentzVector gen_p3(p3_sol * sin_theta_3 * std::cos(phi_3), p3_sol * sin_theta_3 * std::sin(phi_3), p3_sol * std::cos(p3.Theta()), p3_sol);
177 LorentzVector gen_p4(p4_sol * sin_theta_4 * std::cos(phi_4), p4_sol * sin_theta_4 * std::sin(phi_4), p4_sol * std::cos(p4.Theta()), p4_sol);
180 LorentzVector tot = gen_p1 + gen_p2 + gen_p3 + gen_p4 + pb;
181 double q1Pz = std::abs(tot.Pz() + tot.E()) / 2.;
182 double q2Pz = std::abs(tot.Pz() - tot.E()) / 2.;
183 if (q1Pz > sqrt_s / 2 || q2Pz > sqrt_s / 2)
188 LOG(trace) <<
"[BlockG] Throwing solution because total Pt is incorrect. " 189 <<
"Expected " << 0. <<
", got " << tot.Pt();
196 LOG(trace) <<
"[BlockG] Throwing solution because of invalid invariant mass. " <<
197 "Expected " << *s12 <<
", got " << (gen_p1 + gen_p2).M2();
204 LOG(trace) <<
"[BlockG] Throwing solution because of invalid invariant mass. " <<
205 "Expected " << *s34 <<
", got " << (gen_p3 + gen_p4).M2();
210 double jacobian = 1 / std::abs( 2 *
211 (1 - cos_theta_12) * (1 - cos_theta_34) * (
212 alpha_1 * gamma_2 * p3_sol + alpha_2 * p3_sol * (gamma_1 + 2 * alpha_1 * p3_sol) -
213 p4_sol * (beta_2 * gamma_1 + beta_1 * gamma_2 + 2 * beta_1 * beta_2 * p4_sol)
214 ) *
SQ(sqrt_s) * sin_phi_2_1 );
215 jacobian *= ( sin_theta_3 * sin_theta_4 * p1_sol * p2_sol * p3_sol * p4_sol ) / ( 16 * pow(2*M_PI, 8) );
217 Solution s = { { gen_p1, gen_p2, gen_p3, gen_p4 }, jacobian,
true };
218 solutions->push_back(s);
221 if (!solutions->size())
232 std::vector<Value<LorentzVector>> m_branches;
233 std::vector<Value<LorentzVector>> m_particles;
236 std::shared_ptr<SolutionCollection> solutions = produce<SolutionCollection>(
"solutions");
246 .OptionalInputs(
"branches")
248 .GlobalAttr(
"energy:double");
bool solveQuartic(const double a, const double b, const double c, const double d, const double e, std::vector< double > &roots, bool verbose=false)
Finds the real solutions to .
virtual Status work() override
Main function.
bool ApproxComparison(double value, double expected)
Compare two doubles and return true if they are approximatively equal.
Generic solution structure representing a set of particles, along with its jacobian.
Final (main) Block G, describing .
Parent class for all the modules.
A class encapsulating a lua table.
Module(PoolPtr pool, const std::string &name)
Constructor.