00001 #include "TopQuarkAnalysis/TopKinFitter/interface/TtFullLepKinSolver.h"
00002 #include "TF2.h"
00003
00004 TtFullLepKinSolver::TtFullLepKinSolver():
00005 topmass_begin(0),
00006 topmass_end(0),
00007 topmass_step(0),
00008 mw(80.4),
00009 mb(4.8),
00010 pxmiss_(0),
00011 pymiss_(0)
00012 {
00013
00014
00015 EventShape_ = new TF2("landau2D","[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)",0,500,0,500);
00016 EventShape_->SetParameters(30.7137,56.2880,23.0744,59.1015,24.9145);
00017 }
00018
00019 TtFullLepKinSolver::TtFullLepKinSolver(const double b, const double e, const double s, const std::vector<double>& nupars, const double mW, const double mB):
00020 topmass_begin(b),
00021 topmass_end(e),
00022 topmass_step(s),
00023 mw(mW),
00024 mb(mB),
00025 pxmiss_(0),
00026 pymiss_(0)
00027 {
00028 EventShape_ = new TF2("landau2D","[0]*TMath::Landau(x,[1],[2],0)*TMath::Landau(y,[3],[4],0)",0,500,0,500);
00029 EventShape_->SetParameters(nupars[0],nupars[1],nupars[2],nupars[3],nupars[4]);
00030 }
00031
00032
00033
00034
00035 TtFullLepKinSolver::~TtFullLepKinSolver()
00036 {
00037 delete EventShape_;
00038 }
00039
00040 TtDilepEvtSolution TtFullLepKinSolver::addKinSolInfo(TtDilepEvtSolution * asol)
00041 {
00042 TtDilepEvtSolution fitsol(*asol);
00043
00044
00045 TLorentzVector LV_e, LV_e_;
00046
00047 TLorentzVector LV_b, LV_b_;
00048
00049 bool hasMCinfo = true;
00050 if(fitsol.getGenN()) {
00051 genLV_n = TLorentzVector(fitsol.getGenN()->px(), fitsol.getGenN()->py(),
00052 fitsol.getGenN()->pz(), fitsol.getGenN()->energy());
00053 } else hasMCinfo = false;
00054
00055 if(fitsol.getGenNbar()) {
00056 genLV_n_ = TLorentzVector(fitsol.getGenNbar()->px(), fitsol.getGenNbar()->py(),
00057 fitsol.getGenNbar()->pz(), fitsol.getGenNbar()->energy());
00058 } else hasMCinfo = false;
00059
00060
00061 if(useMCforBest_&&!hasMCinfo) return fitsol;
00062
00063
00064 if (fitsol.getWpDecay() == "muon") {
00065 LV_e = TLorentzVector(fitsol.getMuonp().px(), fitsol.getMuonp().py(),
00066 fitsol.getMuonp().pz(), fitsol.getMuonp().energy());
00067 } else if (fitsol.getWpDecay() == "electron") {
00068 LV_e = TLorentzVector(fitsol.getElectronp().px(), fitsol.getElectronp().py(),
00069 fitsol.getElectronp().pz(), fitsol.getElectronp().energy());
00070 } else if (fitsol.getWpDecay() == "tau") {
00071 LV_e = TLorentzVector(fitsol.getTaup().px(), fitsol.getTaup().py(),
00072 fitsol.getTaup().pz(), fitsol.getTaup().energy());
00073 }
00074
00075
00076 if (fitsol.getWmDecay() == "muon") {
00077 LV_e_ = TLorentzVector(fitsol.getMuonm().px(), fitsol.getMuonm().py(),
00078 fitsol.getMuonm().pz(), fitsol.getMuonm().energy());
00079 } else if (fitsol.getWmDecay() == "electron") {
00080 LV_e_ = TLorentzVector(fitsol.getElectronm().px(), fitsol.getElectronm().py(),
00081 fitsol.getElectronm().pz(), fitsol.getElectronm().energy());
00082 } else if (fitsol.getWmDecay() == "tau") {
00083 LV_e_ = TLorentzVector(fitsol.getTaum().px(), fitsol.getTaum().py(),
00084 fitsol.getTaum().pz(), fitsol.getTaum().energy());
00085 }
00086
00087
00088 LV_b = TLorentzVector(fitsol.getCalJetB().px(), fitsol.getCalJetB().py(),
00089 fitsol.getCalJetB().pz(), fitsol.getCalJetB().energy());
00090
00091
00092 LV_b_ = TLorentzVector(fitsol.getCalJetBbar().px(), fitsol.getCalJetBbar().py(),
00093 fitsol.getCalJetBbar().pz(), fitsol.getCalJetBbar().energy());
00094
00095
00096 double weightmax = -1e30;
00097 double mtmax = 0;
00098 for (double mt = topmass_begin;
00099 mt < topmass_end + 0.5*topmass_step;
00100 mt += topmass_step) {
00101
00102 double q_coeff[5], q_sol[4];
00103 FindCoeff(LV_e, LV_e_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
00104 int NSol = quartic(q_coeff, q_sol);
00105
00106
00107 for (int isol = 0; isol < NSol; isol++) {
00108 TopRec(LV_e, LV_e_, LV_b, LV_b_, q_sol[isol]);
00109 double weight = useMCforBest_ ? WeightSolfromMC() : WeightSolfromShape();
00110 if (weight > weightmax) {
00111 weightmax =weight;
00112 mtmax = mt;
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 }
00123
00124 fitsol.setRecTopMass(mtmax);
00125 fitsol.setRecWeightMax(weightmax);
00126
00127 return fitsol;
00128 }
00129
00130 void
00131 TtFullLepKinSolver::SetConstraints(const double xx, const double yy)
00132 {
00133 pxmiss_ = xx;
00134 pymiss_ = yy;
00135 }
00136
00137 TtFullLepKinSolver::NeutrinoSolution
00138 TtFullLepKinSolver::getNuSolution(const TLorentzVector& LV_l,
00139 const TLorentzVector& LV_l_,
00140 const TLorentzVector& LV_b,
00141 const TLorentzVector& LV_b_)
00142 {
00143 math::XYZTLorentzVector maxLV_n = math::XYZTLorentzVector(0,0,0,0);
00144 math::XYZTLorentzVector maxLV_n_ = math::XYZTLorentzVector(0,0,0,0);
00145
00146
00147 double weightmax = -1;
00148 for(double mt = topmass_begin;
00149 mt < topmass_end + 0.5*topmass_step;
00150 mt += topmass_step) {
00151 double q_coeff[5], q_sol[4];
00152 FindCoeff(LV_l, LV_l_, LV_b, LV_b_, mt, mt, pxmiss_, pymiss_, q_coeff);
00153 int NSol = quartic(q_coeff, q_sol);
00154
00155
00156 for (int isol = 0; isol < NSol; isol++) {
00157 TopRec(LV_l, LV_l_, LV_b, LV_b_, q_sol[isol]);
00158 double weight = WeightSolfromShape();
00159 if (weight > weightmax) {
00160 weightmax =weight;
00161 maxLV_n.SetPxPyPzE(LV_n.Px(), LV_n.Py(), LV_n.Pz(), LV_n.E());
00162 maxLV_n_.SetPxPyPzE(LV_n_.Px(), LV_n_.Py(), LV_n_.Pz(), LV_n_.E());
00163 }
00164 }
00165 }
00166 TtFullLepKinSolver::NeutrinoSolution nuSol;
00167 nuSol.neutrino = reco::LeafCandidate(0, maxLV_n );
00168 nuSol.neutrinoBar = reco::LeafCandidate(0, maxLV_n_ );
00169 nuSol.weight = weightmax;
00170 return nuSol;
00171 }
00172
00173 void
00174 TtFullLepKinSolver::FindCoeff(const TLorentzVector& al,
00175 const TLorentzVector& l,
00176 const TLorentzVector& b_al,
00177 const TLorentzVector& b_l,
00178 const double mt,
00179 const double mat,
00180 const double px_miss,
00181 const double py_miss,
00182 double* koeficienty)
00183 {
00184 double E, apom1, apom2, apom3;
00185 double k11, k21, k31, k41, cpom1, cpom2, cpom3, l11, l21, l31, l41, l51, l61, k1, k2, k3, k4, k5,k6;
00186 double l1, l2, l3, l4, l5, l6, k15, k25, k35, k45;
00187
00188 C = -al.Px()-b_al.Px()-l.Px()-b_l.Px() + px_miss;
00189 D = -al.Py()-b_al.Py()-l.Py()-b_l.Py() + py_miss;
00190
00191
00192
00193 E = (sqr(mt)-sqr(mw)-sqr(mb))/(2*b_al.E())-sqr(mw)/(2*al.E())-al.E()+al.Px()*b_al.Px()/b_al.E()+al.Py()*b_al.Py()/b_al.E()+al.Pz()*b_al.Pz()/b_al.E();
00194 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()+l.Py()*b_l.Py()/b_l.E()+l.Pz()*b_l.Pz()/b_l.E();
00195
00196 m1 = al.Px()/al.E()-b_al.Px()/b_al.E();
00197 m2 = al.Py()/al.E()-b_al.Py()/b_al.E();
00198 m3 = al.Pz()/al.E()-b_al.Pz()/b_al.E();
00199
00200 n1 = l.Px()/l.E()-b_l.Px()/b_l.E();
00201 n2 = l.Py()/l.E()-b_l.Py()/b_l.E();
00202 n3 = l.Pz()/l.E()-b_l.Pz()/b_l.E();
00203
00204 pom = E-m1*C-m2*D;
00205 apom1 = sqr(al.Px())-sqr(al.E());
00206 apom2 = sqr(al.Py())-sqr(al.E());
00207 apom3 = sqr(al.Pz())-sqr(al.E());
00208
00209 k11 = 1/sqr(al.E())*(pow(mw,4)/4+sqr(C)*apom1+sqr(D)*apom2+apom3*sqr(pom)/sqr(m3)+sqr(mw)*(al.Px()*C+al.Py()*D+al.Pz()*pom/m3)+2*al.Px()*al.Py()*C*D+2*al.Px()*al.Pz()*C*pom/m3+2*al.Py()*al.Pz()*D*pom/m3);
00210 k21 = 1/sqr(al.E())*(-2*C*m3*n3*apom1+2*apom3*n3*m1*pom/m3-sqr(mw)*m3*n3*al.Px()+sqr(mw)*m1*n3*al.Pz()-2*al.Px()*al.Py()*D*m3*n3+2*al.Px()*al.Pz()*C*m1*n3-2*al.Px()*al.Pz()*n3*pom+2*al.Py()*al.Pz()*D*m1*n3);
00211 k31 = 1/sqr(al.E())*(-2*D*m3*n3*apom2+2*apom3*n3*m2*pom/m3-sqr(mw)*m3*n3*al.Py()+sqr(mw)*m2*n3*al.Pz()-2*al.Px()*al.Py()*C*m3*n3+2*al.Px()*al.Pz()*C*m2*n3-2*al.Py()*al.Pz()*n3*pom+2*al.Py()*al.Pz()*D*m2*n3);
00212 k41 = 1/sqr(al.E())*(2*apom3*m1*m2*sqr(n3)+2*al.Px()*al.Py()*sqr(m3)*sqr(n3)-2*al.Px()*al.Pz()*m2*m3*sqr(n3)-2*al.Py()*al.Pz()*m1*m3*sqr(n3));
00213 k51 = 1/sqr(al.E())*(apom1*sqr(m3)*sqr(n3)+apom3*sqr(m1)*sqr(n3)-2*al.Px()*al.Pz()*m1*m3*sqr(n3));
00214 k61 = 1/sqr(al.E())*(apom2*sqr(m3)*sqr(n3)+apom3*sqr(m2)*sqr(n3)-2*al.Py()*al.Pz()*m2*m3*sqr(n3));
00215
00216 cpom1 = sqr(l.Px())-sqr(l.E());
00217 cpom2 = sqr(l.Py())-sqr(l.E());
00218 cpom3 = sqr(l.Pz())-sqr(l.E());
00219
00220 l11 = 1/sqr(l.E())*(pow(mw,4)/4+cpom3*sqr(F)/sqr(n3)+sqr(mw)*l.Pz()*F/n3);
00221 l21 = 1/sqr(l.E())*(-2*cpom3*F*m3*n1/n3+sqr(mw)*(l.Px()*m3*n3-l.Pz()*n1*m3)+2*l.Px()*l.Pz()*F*m3);
00222 l31 = 1/sqr(l.E())*(-2*cpom3*F*m3*n2/n3+sqr(mw)*(l.Py()*m3*n3-l.Pz()*n2*m3)+2*l.Py()*l.Pz()*F*m3);
00223 l41 = 1/sqr(l.E())*(2*cpom3*n1*n2*sqr(m3)+2*l.Px()*l.Py()*sqr(m3)*sqr(n3)-2*l.Px()*l.Pz()*n2*n3*sqr(m3)-2*l.Py()*l.Pz()*n1*n3*sqr(m3));
00224 l51 = 1/sqr(l.E())*(cpom1*sqr(m3)*sqr(n3)+cpom3*sqr(n1)*sqr(m3)-2*l.Px()*l.Pz()*n1*n3*sqr(m3));
00225 l61 = 1/sqr(l.E())*(cpom2*sqr(m3)*sqr(n3)+cpom3*sqr(n2)*sqr(m3)-2*l.Py()*l.Pz()*n2*n3*sqr(m3));
00226
00227 k1 = k11*k61;
00228 k2 = k61*k21/k51;
00229 k3 = k31;
00230 k4 = k41/k51;
00231 k5 = k61/k51;
00232 k6 = 1;
00233
00234 l1 = l11*k61;
00235 l2 = l21*k61/k51;
00236 l3 = l31;
00237 l4 = l41/k51;
00238 l5 = l51*k61/(sqr(k51));
00239 l6 = l61/k61;
00240
00241 k15 = k1*l5-l1*k5;
00242 k25 = k2*l5-l2*k5;
00243 k35 = k3*l5-l3*k5;
00244 k45 = k4*l5-l4*k5;
00245
00246 k16 = k1*l6-l1*k6;
00247 k26 = k2*l6-l2*k6;
00248 k36 = k3*l6-l3*k6;
00249 k46 = k4*l6-l4*k6;
00250 k56 = k5*l6-l5*k6;
00251
00252 koeficienty[0] = k15*sqr(k36)-k35*k36*k16-k56*sqr(k16);
00253 koeficienty[1] = 2*k15*k36*k46+k25*sqr(k36)+k35*(-k46*k16-k36*k26)-k45*k36*k16-2*k56*k26*k16;
00254 koeficienty[2] = k15*sqr(k46)+2*k25*k36*k46+k35*(-k46*k26-k36*k56)-k56*(sqr(k26)+2*k56*k16)-k45*(k46*k16+k36*k26);
00255 koeficienty[3] = k25*sqr(k46)-k35*k46*k56-k45*(k46*k26+k36*k56)-2*sqr(k56)*k26;
00256 koeficienty[4] = -k45*k46*k56-pow(k56,3);
00257
00258
00259 int moc=(int(log10(fabs(koeficienty[0])))+int(log10(fabs(koeficienty[4]))))/2;
00260
00261 koeficienty[0]=koeficienty[0]/TMath::Power(10,moc);
00262 koeficienty[1]=koeficienty[1]/TMath::Power(10,moc);
00263 koeficienty[2]=koeficienty[2]/TMath::Power(10,moc);
00264 koeficienty[3]=koeficienty[3]/TMath::Power(10,moc);
00265 koeficienty[4]=koeficienty[4]/TMath::Power(10,moc);
00266 }
00267
00268 void TtFullLepKinSolver::TopRec(const TLorentzVector& al,
00269 const TLorentzVector& l,
00270 const TLorentzVector& b_al,
00271 const TLorentzVector& b_l,
00272 const double sol)
00273 {
00274 TVector3 t_ttboost;
00275 TLorentzVector aux;
00276 double pxp, pyp, pzp, pup, pvp, pwp;
00277
00278 pxp = sol*(m3*n3/k51);
00279 pyp = -(m3*n3/k61)*(k56*pow(sol,2) + k26*sol + k16)/(k36 + k46*sol);
00280 pzp = -1/n3*(n1*pxp + n2*pyp - F);
00281 pwp = 1/m3*(m1*pxp + m2*pyp + pom);
00282 pup = C - pxp;
00283 pvp = D - pyp;
00284
00285 LV_n_.SetXYZM(pxp, pyp, pzp, 0.0);
00286 LV_n.SetXYZM(pup, pvp, pwp, 0.0);
00287
00288 LV_t_ = b_l + l + LV_n_;
00289 LV_t = b_al + al + LV_n;
00290
00291 aux = (LV_t_ + LV_t);
00292 t_ttboost = -aux.BoostVector();
00293 LV_tt_t_ = LV_t_;
00294 LV_tt_t = LV_t;
00295 LV_tt_t_.Boost(t_ttboost);
00296 LV_tt_t.Boost(t_ttboost);
00297 }
00298
00299 double
00300 TtFullLepKinSolver::WeightSolfromMC() const
00301 {
00302 double weight = 1;
00303 weight = ((LV_n.E() > genLV_n.E())? genLV_n.E()/LV_n.E(): LV_n.E()/genLV_n.E())
00304 *((LV_n_.E() > genLV_n_.E())? genLV_n_.E()/LV_n_.E(): LV_n_.E()/genLV_n_.E());
00305 return weight;
00306 }
00307
00308 double
00309 TtFullLepKinSolver::WeightSolfromShape() const
00310 {
00311 return EventShape_->Eval(LV_n.E(),LV_n_.E());
00312 }
00313
00314 int
00315 TtFullLepKinSolver::quartic(double *koeficienty, double* koreny) const
00316 {
00317 double w, b0, b1, b2;
00318 double c[4];
00319 double d0, d1, h, t, z;
00320 double *px;
00321
00322 if (koeficienty[4]==0.0)
00323 return cubic(koeficienty, koreny);
00324
00325 w = koeficienty[3]/(4*koeficienty[4]);
00326
00327 b2 = -6*sqr(w) + koeficienty[2]/koeficienty[4];
00328
00329 b1 = (8*sqr(w) - 2*koeficienty[2]/koeficienty[4])*w + koeficienty[1]/koeficienty[4];
00330 b0 = ((-3*sqr(w) + koeficienty[2]/koeficienty[4])*w - koeficienty[1]/koeficienty[4])*w + koeficienty[0]/koeficienty[4];
00331
00332 c[3] = 1.0;
00333
00334 c[2] = b2;
00335 c[1] = -4*b0;
00336 c[0] = sqr(b1) - 4*b0*b2;
00337
00338 cubic(c, koreny);
00339 z = koreny[0];
00340
00341
00342
00343
00344
00345
00346 int nreal = 0;
00347 px = koreny;
00348 t = sqrt(0.25*sqr(z) - b0);
00349 for(int i=-1; i<=1; i+=2) {
00350 d0 = -0.5*z + i*t;
00351
00352 d1 = (t!=0.0)? -i*0.5*b1/t : i*sqrt(-z - b2);
00353 h = 0.25*sqr(d1) - d0;
00354 if (h>=0.0) {
00355 h = sqrt(h);
00356 nreal += 2;
00357 *px++ = -0.5*d1 - h - w;
00358 *px++ = -0.5*d1 + h - w;
00359 }
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 return nreal;
00371
00372 }
00373
00374 int
00375 TtFullLepKinSolver::cubic(const double *coeffs, double* koreny) const
00376 {
00377 unsigned nreal;
00378 double w, p, q, dis, h, phi;
00379
00380 if (coeffs[3]!=0.0) {
00381
00382 w = coeffs[2]/(3*coeffs[3]);
00383 p = sqr(coeffs[1]/(3*coeffs[3])-sqr(w))*(coeffs[1]/(3*coeffs[3])-sqr(w));
00384 q = -0.5*(2*sqr(w)*w-(coeffs[1]*w-coeffs[0])/coeffs[3]);
00385 dis = sqr(q)+p;
00386
00387 if (dis<0.0) {
00388
00389 h = q/sqrt(-p);
00390 if (h>1.0) h = 1.0;
00391
00392 if (h<-1.0) h = -1.0;
00393
00394 phi = acos(h);
00395 p = 2*TMath::Power(-p, 1.0/6.0);
00396 for(unsigned i=0; i<3; i++)
00397 koreny[i] = p*cos((phi+2*i*TMath::Pi())/3.0) - w;
00398 if (koreny[1]<koreny[0]) SWAP(koreny[0], koreny[1]);
00399
00400 if (koreny[2]<koreny[1]) SWAP(koreny[1], koreny[2]);
00401 if (koreny[1]<koreny[0]) SWAP(koreny[0], koreny[1]);
00402 nreal = 3;
00403 }
00404 else {
00405
00406 dis = sqrt(dis);
00407 h = TMath::Power(fabs(q+dis), 1.0/3.0);
00408 p = TMath::Power(fabs(q-dis), 1.0/3.0);
00409 koreny[0] = ((q+dis>0.0)? h : -h) + ((q-dis>0.0)? p : -p) - w;
00410 nreal = 1;
00411 }
00412
00413
00414
00415 for(unsigned i=0; i<nreal; i++) {
00416 h = coeffs[1] + koreny[i] * (2 * coeffs[2] + 3 * koreny[i] * coeffs[3]);
00417 if (h != 0.0)
00418 koreny[i] -= (coeffs[0] + koreny[i] * (coeffs[1] + koreny[i] * (coeffs[2] + koreny[i] * coeffs[3])))/h;
00419 }
00420 }
00421
00422 else if (coeffs[2]!=0.0) {
00423
00424 p = 0.5*coeffs[1]/coeffs[2];
00425 dis = sqr(p) - coeffs[0]/coeffs[2];
00426 if (dis>=0.0) {
00427
00428 dis = sqrt(dis);
00429 koreny[0] = -p - dis;
00430 koreny[1] = -p + dis;
00431 nreal = 2;
00432 }
00433 else
00434
00435 nreal = 0;
00436 }
00437
00438 else if (coeffs[1]!=0.0) {
00439
00440 koreny[0] = -coeffs[0]/coeffs[1];
00441 nreal = 1;
00442 }
00443
00444 else
00445
00446 nreal = 0;
00447
00448 return nreal;
00449 }
00450
00451
00452 void
00453 TtFullLepKinSolver::SWAP(double& realone, double& realtwo) const
00454 {
00455 if (realtwo < realone) {
00456 double aux = realtwo;
00457 realtwo = realone;
00458 realone = aux;
00459 }
00460 }