File indexing completed on 2024-09-26 05:07:18
0001 #include "TopQuarkAnalysis/TopKinFitter/interface/TtFullLepKinSolver.h"
0002 #include "TF2.h"
0003
0004 TtFullLepKinSolver::TtFullLepKinSolver()
0005 : topmass_begin(0), topmass_end(0), topmass_step(0), mw(80.4), mb(4.8), pxmiss_(0), pymiss_(0) {
0006
0007
0008 EventShape_ = new TF2("landau2D", "[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)", 0, 500, 0, 500);
0009 EventShape_->SetParameters(30.7137, 56.2880, 23.0744, 59.1015, 24.9145);
0010 }
0011
0012 TtFullLepKinSolver::TtFullLepKinSolver(
0013 const double b, const double e, const double s, const std::vector<double>& nupars, const double mW, const double mB)
0014 : topmass_begin(b), topmass_end(e), topmass_step(s), mw(mW), mb(mB), pxmiss_(0), pymiss_(0) {
0015 EventShape_ = new TF2("landau2D", "[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)", 0, 500, 0, 500);
0016 EventShape_->SetParameters(nupars[0], nupars[1], nupars[2], nupars[3], nupars[4]);
0017 }
0018
0019
0020
0021
0022 TtFullLepKinSolver::~TtFullLepKinSolver() { delete EventShape_; }
0023
0024 TtDilepEvtSolution TtFullLepKinSolver::addKinSolInfo(TtDilepEvtSolution* asol) {
0025 TtDilepEvtSolution fitsol(*asol);
0026
0027
0028 TLorentzVector LV_e, LV_e_;
0029
0030 TLorentzVector LV_b, LV_b_;
0031
0032 bool hasMCinfo = true;
0033 if (fitsol.getGenN()) {
0034 genLV_n = TLorentzVector(
0035 fitsol.getGenN()->px(), fitsol.getGenN()->py(), fitsol.getGenN()->pz(), fitsol.getGenN()->energy());
0036 } else
0037 hasMCinfo = false;
0038
0039 if (fitsol.getGenNbar()) {
0040 genLV_n_ = TLorentzVector(
0041 fitsol.getGenNbar()->px(), fitsol.getGenNbar()->py(), fitsol.getGenNbar()->pz(), fitsol.getGenNbar()->energy());
0042 } else
0043 hasMCinfo = false;
0044
0045
0046 if (useMCforBest_ && !hasMCinfo)
0047 return fitsol;
0048
0049
0050 if (fitsol.getWpDecay() == "muon") {
0051 LV_e = TLorentzVector(
0052 fitsol.getMuonp().px(), fitsol.getMuonp().py(), fitsol.getMuonp().pz(), fitsol.getMuonp().energy());
0053 } else if (fitsol.getWpDecay() == "electron") {
0054 LV_e = TLorentzVector(fitsol.getElectronp().px(),
0055 fitsol.getElectronp().py(),
0056 fitsol.getElectronp().pz(),
0057 fitsol.getElectronp().energy());
0058 } else if (fitsol.getWpDecay() == "tau") {
0059 LV_e =
0060 TLorentzVector(fitsol.getTaup().px(), fitsol.getTaup().py(), fitsol.getTaup().pz(), fitsol.getTaup().energy());
0061 }
0062
0063
0064 if (fitsol.getWmDecay() == "muon") {
0065 LV_e_ = TLorentzVector(
0066 fitsol.getMuonm().px(), fitsol.getMuonm().py(), fitsol.getMuonm().pz(), fitsol.getMuonm().energy());
0067 } else if (fitsol.getWmDecay() == "electron") {
0068 LV_e_ = TLorentzVector(fitsol.getElectronm().px(),
0069 fitsol.getElectronm().py(),
0070 fitsol.getElectronm().pz(),
0071 fitsol.getElectronm().energy());
0072 } else if (fitsol.getWmDecay() == "tau") {
0073 LV_e_ =
0074 TLorentzVector(fitsol.getTaum().px(), fitsol.getTaum().py(), fitsol.getTaum().pz(), fitsol.getTaum().energy());
0075 }
0076
0077
0078 LV_b = TLorentzVector(
0079 fitsol.getCalJetB().px(), fitsol.getCalJetB().py(), fitsol.getCalJetB().pz(), fitsol.getCalJetB().energy());
0080
0081
0082 LV_b_ = TLorentzVector(fitsol.getCalJetBbar().px(),
0083 fitsol.getCalJetBbar().py(),
0084 fitsol.getCalJetBbar().pz(),
0085 fitsol.getCalJetBbar().energy());
0086
0087
0088 double weightmax = -1e30;
0089 double mtmax = 0;
0090 for (double mt = topmass_begin; mt < topmass_end + 0.5 * topmass_step; mt += topmass_step) {
0091
0092 double q_coeff[5], q_sol[4];
0093 FindCoeff(LV_e, LV_e_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
0094 int NSol = quartic(q_coeff, q_sol);
0095
0096
0097 for (int isol = 0; isol < NSol; isol++) {
0098 TopRec(LV_e, LV_e_, LV_b, LV_b_, q_sol[isol]);
0099 double weight = useMCforBest_ ? WeightSolfromMC() : WeightSolfromShape();
0100 if (weight > weightmax) {
0101 weightmax = weight;
0102 mtmax = mt;
0103 }
0104 }
0105
0106
0107
0108
0109
0110
0111
0112 }
0113
0114 fitsol.setRecTopMass(mtmax);
0115 fitsol.setRecWeightMax(weightmax);
0116
0117 return fitsol;
0118 }
0119
0120 void TtFullLepKinSolver::SetConstraints(const double xx, const double yy) {
0121 pxmiss_ = xx;
0122 pymiss_ = yy;
0123 }
0124
0125 TtFullLepKinSolver::NeutrinoSolution TtFullLepKinSolver::getNuSolution(const TLorentzVector& LV_l,
0126 const TLorentzVector& LV_l_,
0127 const TLorentzVector& LV_b,
0128 const TLorentzVector& LV_b_) {
0129 math::XYZTLorentzVector maxLV_n = math::XYZTLorentzVector(0, 0, 0, 0);
0130 math::XYZTLorentzVector maxLV_n_ = math::XYZTLorentzVector(0, 0, 0, 0);
0131
0132
0133 double weightmax = -1;
0134 for (double mt = topmass_begin; mt < topmass_end + 0.5 * topmass_step; mt += topmass_step) {
0135 double q_coeff[5], q_sol[4];
0136 FindCoeff(LV_l, LV_l_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
0137 int NSol = quartic(q_coeff, q_sol);
0138
0139
0140 for (int isol = 0; isol < NSol; isol++) {
0141 TopRec(LV_l, LV_l_, LV_b, LV_b_, q_sol[isol]);
0142 double weight = WeightSolfromShape();
0143 if (weight > weightmax) {
0144 weightmax = weight;
0145 maxLV_n.SetPxPyPzE(LV_n.Px(), LV_n.Py(), LV_n.Pz(), LV_n.E());
0146 maxLV_n_.SetPxPyPzE(LV_n_.Px(), LV_n_.Py(), LV_n_.Pz(), LV_n_.E());
0147 }
0148 }
0149 }
0150 TtFullLepKinSolver::NeutrinoSolution nuSol;
0151 nuSol.neutrino = reco::LeafCandidate(0, maxLV_n);
0152 nuSol.neutrinoBar = reco::LeafCandidate(0, maxLV_n_);
0153 nuSol.weight = weightmax;
0154 return nuSol;
0155 }
0156
0157 void TtFullLepKinSolver::FindCoeff(const TLorentzVector& al,
0158 const TLorentzVector& l,
0159 const TLorentzVector& b_al,
0160 const TLorentzVector& b_l,
0161 const double mt,
0162 const double mat,
0163 const double px_miss,
0164 const double py_miss,
0165 double* koeficienty) {
0166 double E, apom1, apom2, apom3;
0167 double k11, k21, k31, k41, cpom1, cpom2, cpom3, l11, l21, l31, l41, l51, l61, k1, k2, k3, k4, k5, k6;
0168 double l1, l2, l3, l4, l5, l6, k15, k25, k35, k45;
0169
0170 C = -al.Px() - b_al.Px() - l.Px() - b_l.Px() + px_miss;
0171 D = -al.Py() - b_al.Py() - l.Py() - b_l.Py() + py_miss;
0172
0173
0174
0175 E = (sqr(mt) - sqr(mw) - sqr(mb)) / (2 * b_al.E()) - sqr(mw) / (2 * al.E()) - al.E() +
0176 al.Px() * b_al.Px() / b_al.E() + al.Py() * b_al.Py() / b_al.E() + al.Pz() * b_al.Pz() / b_al.E();
0177 F = (sqr(mat) - sqr(mw) - sqr(mb)) / (2 * b_l.E()) - sqr(mw) / (2 * l.E()) - l.E() + l.Px() * b_l.Px() / b_l.E() +
0178 l.Py() * b_l.Py() / b_l.E() + l.Pz() * b_l.Pz() / b_l.E();
0179
0180 m1 = al.Px() / al.E() - b_al.Px() / b_al.E();
0181 m2 = al.Py() / al.E() - b_al.Py() / b_al.E();
0182 m3 = al.Pz() / al.E() - b_al.Pz() / b_al.E();
0183
0184 n1 = l.Px() / l.E() - b_l.Px() / b_l.E();
0185 n2 = l.Py() / l.E() - b_l.Py() / b_l.E();
0186 n3 = l.Pz() / l.E() - b_l.Pz() / b_l.E();
0187
0188 pom = E - m1 * C - m2 * D;
0189 apom1 = sqr(al.Px()) - sqr(al.E());
0190 apom2 = sqr(al.Py()) - sqr(al.E());
0191 apom3 = sqr(al.Pz()) - sqr(al.E());
0192
0193 k11 = 1 / sqr(al.E()) *
0194 (pow(mw, 4) / 4 + sqr(C) * apom1 + sqr(D) * apom2 + apom3 * sqr(pom) / sqr(m3) +
0195 sqr(mw) * (al.Px() * C + al.Py() * D + al.Pz() * pom / m3) + 2 * al.Px() * al.Py() * C * D +
0196 2 * al.Px() * al.Pz() * C * pom / m3 + 2 * al.Py() * al.Pz() * D * pom / m3);
0197 k21 = 1 / sqr(al.E()) *
0198 (-2 * C * m3 * n3 * apom1 + 2 * apom3 * n3 * m1 * pom / m3 - sqr(mw) * m3 * n3 * al.Px() +
0199 sqr(mw) * m1 * n3 * al.Pz() - 2 * al.Px() * al.Py() * D * m3 * n3 + 2 * al.Px() * al.Pz() * C * m1 * n3 -
0200 2 * al.Px() * al.Pz() * n3 * pom + 2 * al.Py() * al.Pz() * D * m1 * n3);
0201 k31 = 1 / sqr(al.E()) *
0202 (-2 * D * m3 * n3 * apom2 + 2 * apom3 * n3 * m2 * pom / m3 - sqr(mw) * m3 * n3 * al.Py() +
0203 sqr(mw) * m2 * n3 * al.Pz() - 2 * al.Px() * al.Py() * C * m3 * n3 + 2 * al.Px() * al.Pz() * C * m2 * n3 -
0204 2 * al.Py() * al.Pz() * n3 * pom + 2 * al.Py() * al.Pz() * D * m2 * n3);
0205 k41 = 1 / sqr(al.E()) *
0206 (2 * apom3 * m1 * m2 * sqr(n3) + 2 * al.Px() * al.Py() * sqr(m3) * sqr(n3) -
0207 2 * al.Px() * al.Pz() * m2 * m3 * sqr(n3) - 2 * al.Py() * al.Pz() * m1 * m3 * sqr(n3));
0208 k51 = 1 / sqr(al.E()) *
0209 (apom1 * sqr(m3) * sqr(n3) + apom3 * sqr(m1) * sqr(n3) - 2 * al.Px() * al.Pz() * m1 * m3 * sqr(n3));
0210 k61 = 1 / sqr(al.E()) *
0211 (apom2 * sqr(m3) * sqr(n3) + apom3 * sqr(m2) * sqr(n3) - 2 * al.Py() * al.Pz() * m2 * m3 * sqr(n3));
0212
0213 cpom1 = sqr(l.Px()) - sqr(l.E());
0214 cpom2 = sqr(l.Py()) - sqr(l.E());
0215 cpom3 = sqr(l.Pz()) - sqr(l.E());
0216
0217 l11 = 1 / sqr(l.E()) * (pow(mw, 4) / 4 + cpom3 * sqr(F) / sqr(n3) + sqr(mw) * l.Pz() * F / n3);
0218 l21 =
0219 1 / sqr(l.E()) *
0220 (-2 * cpom3 * F * m3 * n1 / n3 + sqr(mw) * (l.Px() * m3 * n3 - l.Pz() * n1 * m3) + 2 * l.Px() * l.Pz() * F * m3);
0221 l31 =
0222 1 / sqr(l.E()) *
0223 (-2 * cpom3 * F * m3 * n2 / n3 + sqr(mw) * (l.Py() * m3 * n3 - l.Pz() * n2 * m3) + 2 * l.Py() * l.Pz() * F * m3);
0224 l41 = 1 / sqr(l.E()) *
0225 (2 * cpom3 * n1 * n2 * sqr(m3) + 2 * l.Px() * l.Py() * sqr(m3) * sqr(n3) -
0226 2 * l.Px() * l.Pz() * n2 * n3 * sqr(m3) - 2 * l.Py() * l.Pz() * n1 * n3 * sqr(m3));
0227 l51 = 1 / sqr(l.E()) *
0228 (cpom1 * sqr(m3) * sqr(n3) + cpom3 * sqr(n1) * sqr(m3) - 2 * l.Px() * l.Pz() * n1 * n3 * sqr(m3));
0229 l61 = 1 / sqr(l.E()) *
0230 (cpom2 * sqr(m3) * sqr(n3) + cpom3 * sqr(n2) * sqr(m3) - 2 * l.Py() * l.Pz() * n2 * n3 * sqr(m3));
0231
0232 k1 = k11 * k61;
0233 k2 = k61 * k21 / k51;
0234 k3 = k31;
0235 k4 = k41 / k51;
0236 k5 = k61 / k51;
0237 k6 = 1;
0238
0239 l1 = l11 * k61;
0240 l2 = l21 * k61 / k51;
0241 l3 = l31;
0242 l4 = l41 / k51;
0243 l5 = l51 * k61 / (sqr(k51));
0244 l6 = l61 / k61;
0245
0246 k15 = k1 * l5 - l1 * k5;
0247 k25 = k2 * l5 - l2 * k5;
0248 k35 = k3 * l5 - l3 * k5;
0249 k45 = k4 * l5 - l4 * k5;
0250
0251 k16 = k1 * l6 - l1 * k6;
0252 k26 = k2 * l6 - l2 * k6;
0253 k36 = k3 * l6 - l3 * k6;
0254 k46 = k4 * l6 - l4 * k6;
0255 k56 = k5 * l6 - l5 * k6;
0256
0257 koeficienty[0] = k15 * sqr(k36) - k35 * k36 * k16 - k56 * sqr(k16);
0258 koeficienty[1] =
0259 2 * k15 * k36 * k46 + k25 * sqr(k36) + k35 * (-k46 * k16 - k36 * k26) - k45 * k36 * k16 - 2 * k56 * k26 * k16;
0260 koeficienty[2] = k15 * sqr(k46) + 2 * k25 * k36 * k46 + k35 * (-k46 * k26 - k36 * k56) -
0261 k56 * (sqr(k26) + 2 * k56 * k16) - k45 * (k46 * k16 + k36 * k26);
0262 koeficienty[3] = k25 * sqr(k46) - k35 * k46 * k56 - k45 * (k46 * k26 + k36 * k56) - 2 * sqr(k56) * k26;
0263 koeficienty[4] = -k45 * k46 * k56 - pow(k56, 3);
0264
0265
0266 int moc = (int(log10(fabs(koeficienty[0]))) + int(log10(fabs(koeficienty[4])))) / 2;
0267
0268 koeficienty[0] = koeficienty[0] / TMath::Power(10, moc);
0269 koeficienty[1] = koeficienty[1] / TMath::Power(10, moc);
0270 koeficienty[2] = koeficienty[2] / TMath::Power(10, moc);
0271 koeficienty[3] = koeficienty[3] / TMath::Power(10, moc);
0272 koeficienty[4] = koeficienty[4] / TMath::Power(10, moc);
0273 }
0274
0275 void TtFullLepKinSolver::TopRec(const TLorentzVector& al,
0276 const TLorentzVector& l,
0277 const TLorentzVector& b_al,
0278 const TLorentzVector& b_l,
0279 const double sol) {
0280 TVector3 t_ttboost;
0281 TLorentzVector aux;
0282 double pxp, pyp, pzp, pup, pvp, pwp;
0283
0284 pxp = sol * (m3 * n3 / k51);
0285 pyp = -(m3 * n3 / k61) * (k56 * pow(sol, 2) + k26 * sol + k16) / (k36 + k46 * sol);
0286 pzp = -1 / n3 * (n1 * pxp + n2 * pyp - F);
0287 pwp = 1 / m3 * (m1 * pxp + m2 * pyp + pom);
0288 pup = C - pxp;
0289 pvp = D - pyp;
0290
0291 LV_n_.SetXYZM(pxp, pyp, pzp, 0.0);
0292 LV_n.SetXYZM(pup, pvp, pwp, 0.0);
0293
0294 LV_t_ = b_l + l + LV_n_;
0295 LV_t = b_al + al + LV_n;
0296
0297 aux = (LV_t_ + LV_t);
0298 t_ttboost = -aux.BoostVector();
0299 LV_tt_t_ = LV_t_;
0300 LV_tt_t = LV_t;
0301 LV_tt_t_.Boost(t_ttboost);
0302 LV_tt_t.Boost(t_ttboost);
0303 }
0304
0305 double TtFullLepKinSolver::WeightSolfromMC() const {
0306 double weight = 1;
0307 weight = ((LV_n.E() > genLV_n.E()) ? genLV_n.E() / LV_n.E() : LV_n.E() / genLV_n.E()) *
0308 ((LV_n_.E() > genLV_n_.E()) ? genLV_n_.E() / LV_n_.E() : LV_n_.E() / genLV_n_.E());
0309 return weight;
0310 }
0311
0312 double TtFullLepKinSolver::WeightSolfromShape() const { return EventShape_->Eval(LV_n.E(), LV_n_.E()); }
0313
0314 int TtFullLepKinSolver::quartic(double* koeficienty, double* koreny) const {
0315 double w, b0, b1, b2;
0316 double c[4];
0317 double d0, d1, h, t, z;
0318 double* px;
0319
0320 if (koeficienty[4] == 0.0) {
0321 return cubic(koeficienty, koreny);
0322 }
0323
0324 w = koeficienty[3] / (4 * koeficienty[4]);
0325
0326 b2 = -6 * sqr(w) + koeficienty[2] / koeficienty[4];
0327
0328 b1 = (8 * sqr(w) - 2 * koeficienty[2] / koeficienty[4]) * w + koeficienty[1] / koeficienty[4];
0329 b0 = ((-3 * sqr(w) + koeficienty[2] / koeficienty[4]) * w - koeficienty[1] / koeficienty[4]) * w +
0330 koeficienty[0] / koeficienty[4];
0331
0332 c[3] = 1.0;
0333
0334 c[2] = b2;
0335 c[1] = -4 * b0;
0336 c[0] = sqr(b1) - 4 * b0 * b2;
0337
0338 if (cubic(c, koreny) == 0) {
0339
0340 return 0;
0341 } else {
0342 z = koreny[0];
0343 }
0344
0345
0346
0347
0348
0349
0350 int nreal = 0;
0351 px = koreny;
0352 t = sqrt(0.25 * sqr(z) - b0);
0353 for (int i = -1; i <= 1; i += 2) {
0354 d0 = -0.5 * z + i * t;
0355
0356 d1 = (t != 0.0) ? -i * 0.5 * b1 / t : i * sqrt(-z - b2);
0357 h = 0.25 * sqr(d1) - d0;
0358 if (h >= 0.0) {
0359 h = sqrt(h);
0360 nreal += 2;
0361 *px++ = -0.5 * d1 - h - w;
0362 *px++ = -0.5 * d1 + h - w;
0363 }
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 return nreal;
0375 }
0376
0377 unsigned int TtFullLepKinSolver::cubic(const double* coeffs, double* koreny) const {
0378 unsigned nreal;
0379 double w, p, q, dis, h, phi;
0380
0381 if (coeffs[3] != 0.0) {
0382
0383 w = coeffs[2] / (3 * coeffs[3]);
0384 p = sqr(coeffs[1] / (3 * coeffs[3]) - sqr(w)) * (coeffs[1] / (3 * coeffs[3]) - sqr(w));
0385 q = -0.5 * (2 * sqr(w) * w - (coeffs[1] * w - coeffs[0]) / coeffs[3]);
0386 dis = sqr(q) + p;
0387
0388 if (dis < 0.0) {
0389
0390 h = q / sqrt(-p);
0391 if (h > 1.0)
0392 h = 1.0;
0393
0394 if (h < -1.0)
0395 h = -1.0;
0396
0397 phi = acos(h);
0398 p = 2 * TMath::Power(-p, 1.0 / 6.0);
0399 for (unsigned i = 0; i < 3; i++)
0400 koreny[i] = p * cos((phi + 2 * i * TMath::Pi()) / 3.0) - w;
0401 if (koreny[1] < koreny[0])
0402 SWAP(koreny[0], koreny[1]);
0403
0404 if (koreny[2] < koreny[1])
0405 SWAP(koreny[1], koreny[2]);
0406 if (koreny[1] < koreny[0])
0407 SWAP(koreny[0], koreny[1]);
0408 nreal = 3;
0409 } else {
0410
0411 dis = sqrt(dis);
0412 h = TMath::Power(fabs(q + dis), 1.0 / 3.0);
0413 p = TMath::Power(fabs(q - dis), 1.0 / 3.0);
0414 koreny[0] = ((q + dis > 0.0) ? h : -h) + ((q - dis > 0.0) ? p : -p) - w;
0415 nreal = 1;
0416 }
0417
0418
0419
0420 for (unsigned i = 0; i < nreal; i++) {
0421 h = coeffs[1] + koreny[i] * (2 * coeffs[2] + 3 * koreny[i] * coeffs[3]);
0422 if (h != 0.0)
0423 koreny[i] -= (coeffs[0] + koreny[i] * (coeffs[1] + koreny[i] * (coeffs[2] + koreny[i] * coeffs[3]))) / h;
0424 }
0425 }
0426
0427 else if (coeffs[2] != 0.0) {
0428
0429 p = 0.5 * coeffs[1] / coeffs[2];
0430 dis = sqr(p) - coeffs[0] / coeffs[2];
0431 if (dis >= 0.0) {
0432
0433 dis = sqrt(dis);
0434 koreny[0] = -p - dis;
0435 koreny[1] = -p + dis;
0436 nreal = 2;
0437 } else
0438
0439 nreal = 0;
0440 }
0441
0442 else if (coeffs[1] != 0.0) {
0443
0444 koreny[0] = -coeffs[0] / coeffs[1];
0445 nreal = 1;
0446 }
0447
0448 else {
0449
0450 nreal = 0;
0451 }
0452 return nreal;
0453 }
0454
0455 void TtFullLepKinSolver::SWAP(double& realone, double& realtwo) const {
0456 if (realtwo < realone) {
0457 double aux = realtwo;
0458 realtwo = realone;
0459 realone = aux;
0460 }
0461 }