static TVector3 floorXYZ(double zvtx, double physeta, double physphi) { // Function to calculate detector position when particle is extrapolated // to 3rd layer of em calorimeter. // Note that we assume an x,y vertex position of zero. // Also, the x,y cal shifts are not implemented...yet. TVector3 v; double phi = physphi; double eta = physeta; double theta = PTools::etaToTheta(eta); double ztmp = zvtx + CC_3R/TMath::Tan(theta); if( TMath::Abs(ztmp) >= EC_DIV ){ // in EC (eta>=0) ? v.SetZ(EC_3Z_SOUTH) : v.SetZ(EC_3Z_NORTH); v.SetX( (v.Z()-zvtx) * TMath::Tan(theta) * TMath::Cos(phi)); v.SetY( (v.Z()-zvtx) * TMath::Tan(theta) * TMath::Sin(phi)); } else{ // in CC v.SetZ(ztmp); v.SetX( CC_3R * TMath::Cos(phi)); v.SetY( CC_3R * TMath::Sin(phi)); } return v; }
int get_circ_wg_efield_vert(TVector3 &pos, TVector3 &efield) { //returns the TE_11 efield inside an infinite circ. waveguide //efield normalized the jackson way with 1/cm units //waveguide extends in x-direction // wavelength of 27 GHz radiation is 1.1 cm double p11 = 1.841; //1st zero of the derivate of bessel function //k11 is angular wavenumber for cutoff frequency for TE11 double k11 = p11 / tl_data.rO; //convert position to cylindrical pos.SetZ(0); double radius = pos.Mag(); double phi = pos.Phi();//azimuthal position //double phi = acos(pos.Y()/radius);//azimuthal position, see definition of phase double J1 = TMath::BesselJ1(k11 * radius);//this term cancels in dot product w/ vel double Jp = TMath::BesselJ0(k11 * radius) - TMath::BesselJ1(k11 * radius) / k11 / radius; double e_amp = 1.63303/tl_data.rO;//cm int status = 0; if (radius > tl_data.rO) { cout << "Problem!!! Electron hit a wall! At radius " << radius << endl; status = 1; } efield.SetX(e_amp * (J1 / k11 / radius * cos(phi) * sin(phi) - Jp * sin(phi) * cos(phi))); efield.SetY(e_amp * (J1 / k11 / radius * sin(phi) * sin(phi) + Jp * cos(phi) * cos(phi))); efield.SetZ(0); //only true for TE mode if (radius == 0) { Jp = 1.0/2; phi = 0; efield.SetX(e_amp * (1. / 2 * cos(phi) * sin(phi) - Jp * sin(phi) * cos(phi))); efield.SetY(e_amp * (1. / 2 * sin(phi) * sin(phi) + Jp * cos(phi) * cos(phi))); } return status; }
int getSurfacePoint(TVector3 intPos, TVector3 &intDir, TVector3 &surfPos) { Double_t b=intDir.X()*intPos.X() + intDir.Y()*intPos.Y() + intDir.Z()*intPos.Z(); Double_t c = intPos.X()*intPos.X() + intPos.Y()*intPos.Y() + intPos.Z()*intPos.Z() - rEarth*rEarth; if(b*b < c) return 0; Double_t l1=-1*b + TMath::Sqrt(b*b - c); Double_t l2=-1*b - TMath::Sqrt(b*b - c); if(intPos.Mag2()> rEarth*rEarth) { //Start outside take l1 //return 0; // cout << "Outside:\t" << l1 << "\t" << l2 << endl; intDir*=-1; l1*=-1; surfPos.SetX(intPos.X() + l1*intDir.X()); surfPos.SetY(intPos.Y() + l1*intDir.Y()); surfPos.SetZ(intPos.Z() + l1*intDir.Z()); // cout << surfPos.Mag() << endl; } else { //Start inside take l2 // cout << "Inside:\t" << l1 << "\t" << l2 << endl; // cout << l2 << endl; // return 0; surfPos.SetX(intPos.X() + l2*intDir.X()); surfPos.SetY(intPos.Y() + l2*intDir.Y()); surfPos.SetZ(intPos.Z() + l2*intDir.Z()); // cout << surfPos.Mag() << endl; } return 1; }
static TVector3 toGlobal(const TVector3 &local){ TVector3 global = local; if(TMath::Abs(local.Z()) < EC_DIV){ //CC global.SetX(global.X()+CC_XSHIFT); global.SetY(global.Y()+CC_YSHIFT); global.SetZ(global.Z()+CC_ZSHIFT); }else{ if (local.Z() < 0) global.SetX(local.X()+EC_XSHIFT_NORTH); global.SetZ( (local.Z()>0) ? EC_3Z_SOUTH : EC_3Z_NORTH ); } return global; }
static TVector3 toLocal(const TVector3 &global){ TVector3 local = global; if(TMath::Abs(global.Z()) < EC_DIV){ //CC local.SetX(local.X()-CC_XSHIFT); local.SetY(local.Y()-CC_YSHIFT); local.SetZ(local.Z()-CC_ZSHIFT); }else{ if (global.Z() < 0) local.SetX(local.X()-EC_XSHIFT_NORTH); local.SetZ( (global.Z()>0) ? EC_3Z : -EC_3Z ); } return local; }
int get_tl_efield(TVector3 &p,TVector3 &efield) { //function returns the electric field between two infinite parallel wires //efield normalized the jackson way with 1/cm units //wires extend in z-direction and are can be offset double e_amp = 1. / 2.0 / M_PI * sqrt(tl_data.C / (EPS0 / M2CM)); //calculate effective wire position for efield TVector3 x1(tl_data.x1, 0, 0); //real position of first wire in cm TVector3 x2(tl_data.x2, 0, 0); //real position of second wire in cm TVector3 l = x1 - x2; l *= 1./2; double a = sqrt(l.Mag2() - pow(tl_data.rI, 2)); //effective wire half separation in cm TVector3 a1 = x1 - l + a*l.Unit(); //effective position of first wire in cm TVector3 a2 = x1 - l - a*l.Unit(); //effective position of second wire in cm //vector from point to wires p.SetZ(0); TVector3 r1 = p + a1; TVector3 r2 = p + a2; //check for hitting wires int status = 0; if ( ( (x1-r1).Mag() < tl_data.rI ) || ( (x2-r2).Mag() < tl_data.rI ) ) { cout << "Problem!!! Electron hit a wire! Radius " << p.Mag() << endl; status = 1; } //efield = e_amp * (r1 * 1/r1.Mag2() - r2 * 1/r2.Mag2()); efield.SetX( e_amp * ( r1.X() / r1.Mag2() - r2.X() / r2.Mag2() ) ); efield.SetY( e_amp * ( r1.Y() / r1.Mag2() - r2.Y() / r2.Mag2() ) ); efield.SetZ( 0 ); //only true for TE or TEM modes return status; }
// This is the pt corrected delta phi between the 2 leptons // P and L2 are the 4-vectors for the 2 hemispheres, or in you case, // the two leptons - setting mass to 0 should be fine // MET is the MET 3 vector (don't forget to set the z-component of // MET to 0) // This function will do the correct Lorentz transformations of the // leptons for you double HWWKinematics::CalcDeltaPhiRFRAME(){ // first calculate pt-corrected MR float mymrnew = CalcMRNEW(); // Now, boost lepton system to rest in z // (approximate accounting for longitudinal boost) TVector3 BL = L1.Vect()+L2.Vect(); BL.SetX(0.0); BL.SetY(0.0); BL = (1./(L1.P()+L2.P()))*BL; L1.Boost(-BL); L2.Boost(-BL); // Next, calculate the transverse Lorentz transformation // to go to Higgs approximate rest frame TVector3 B = L1.Vect()+L2.Vect()+MET; B.SetZ(0.0); B = (-1./(sqrt(4.*mymrnew*mymrnew+B.Dot(B))))*B; L1.Boost(B); L2.Boost(B); //Now, re-calculate the delta phi // in the new reference frame: return L1.DeltaPhi(L2); }
// This is the deltaphi between the di-lepton system and the Higgs // boost in the approximate Higgs rest frame, or R-FRAME // L1 and L2 are the 4-vectors for the 2 hemispheres, or in you case, // the two leptons - setting mass to 0 should be fine // MET is the MET 3 vector (don't forget to set the z-component of // MET to 0) // This function will do the correct Lorentz transformations of the // leptons for you double HWWKinematics::CalcDoubleDphiRFRAME(){ // first calculate pt-corrected MR float mymrnew = CalcMRNEW(); TVector3 BL = L1.Vect()+L2.Vect(); BL.SetX(0.0); BL.SetY(0.0); BL = (1./(L1.P()+L2.P()))*BL; L1.Boost(-BL); L2.Boost(-BL); //Next, calculate the transverse Lorentz transformation TVector3 B = L1.Vect()+L2.Vect()+MET; B.SetZ(0.0); B = (-1./(sqrt(4.*mymrnew*mymrnew+B.Dot(B))))*B; L1.Boost(B); L2.Boost(B); // Now, calculate the delta phi // between di-lepton axis and boost // in new reference frame return B.DeltaPhi(L1.Vect()+L2.Vect()); }
int get_coax_efield(TVector3 &p, TVector3 &efield) { //function returns the electric field inside an infinite coaxial cable //efield normalized the jackson way with 1/cm units //cable extend in z-direction double e_amp = 1 / sqrt(2.0 * M_PI * log(tl_data.rO / tl_data.rI)); int status = 0; p.SetZ(0); if (p.Mag() < tl_data.rI || p.Mag() > tl_data.rO) { cout << "Problem!!! Electron hit the cable! " << endl; status = 1; } efield.SetX( e_amp * p.X() / p.Mag2() ); efield.SetY( e_amp * p.Y() / p.Mag2() ); efield.SetZ( 0 ); //only true for TE or TEM modes return status; }
int get_sq_wg_efield(TVector3 &pos, TVector3 &efield) { //function returns the TE_10 efield inside an infinite square waveguide //centered at x=0, y=0 (not with corner at origin as is standard) //efield normalized the jackson way with 1/cm units //waveguide extends in z-direction // wavelength of 27 GHz radiation is 1.1 cm double e_amp = sqrt(2 / tl_data.x1 / tl_data.y1); int status = 0; if ((pos.X() > tl_data.x1 / 2.) || (pos.X() < -tl_data.x1 / 2.)) { cout << "Problem!!! Electron hit a wall in x-dir! " << endl; status = 1; } if ((pos.Y() > tl_data.y1 / 2.) || (pos.Y() < -tl_data.y1 / 2.)) { cout << "Problem!!! Electron hit a wall in y-dir! " << endl; status = 1; } efield.SetX( 0 ); efield.SetY( e_amp * sin(M_PI * (pos.X() + tl_data.x1 / 2.) / tl_data.x1) ); efield.SetZ( 0 ); //is true for TE mode return status; }
int get_pp_efield(TVector3 &p, TVector3 &efield) { //function returns the electric field between two parallel plates //amplitude corrected for capacitance of finite width strips //not valid outside plates //efield normalized the jackson way with 1/cm units //strips extend in y- and z- directions, so the field is in the x-direction double e_amp = sqrt(1 / (tl_data.n * tl_data.l * (tl_data.x2 - tl_data.x1))); //factor of sqrt(n=1.8) lower than ideal capacitor int status = 0; if ((p.X() < tl_data.x1) || (p.X() > tl_data.x2)) { cout << "Problem!!! Electron hit a plate! " << endl; status = 1; } if ((p.Y() < -tl_data.l / 2) || (p.Y() > tl_data.l / 2)) { cout << "Problem!!! Electron outside plates! " << endl; status = 1; } efield.SetX( e_amp ); efield.SetY( 0 ); efield.SetZ( 0 ); //only true for TE or TEM modes return status; }
void RJ_ttbar(){ setstyle(); //give transverse momenta to CM system in lab frame? double PT = 0.1; //In units of sqrt{shat} //gamma factor associated with 'off-threshold-ness' of tops double gamma = 1.2; //Now, we also have the option to take gamma, event-by-event, //from a more realistic distribution //to do this, set 'b_gamma' to true and the rest //of the variables below appropriately bool b_gamma = true; rootS = 13.; type = 1; //0 quark-antiquark 1 gluon-gluon M = 175./1000.; //TeV units //Number of toy events to throw int N = 1000; // // Generate fake events taking flat ME's for all decay angles // //here, we set up the stuff for dynamic gamma TH1D *h_gamma = (TH1D*) new TH1D("newgamma","newgamma",500,1.0,10.0); if(b_gamma){ cout << "generating gamma distribution" << endl; for(int ibin = 1; ibin <= 500; ibin++){ double g = h_gamma->GetBinCenter(ibin); double entry = Calc_dsigma_dgamma(g); if(entry > 0.) h_gamma->SetBinContent(ibin, entry); } cout << "done" << endl; } ////////////////////////////////////////////////////////////// // Setup rest frames code ////////////////////////////////////////////////////////////// cout << " Initialize lists of visible, invisible particles and intermediate states " << endl; RLabFrame* LAB = new RLabFrame("LAB","lab"); RDecayFrame* TT = new RDecayFrame("TT","t #bar{t}"); RDecayFrame* T1 = new RDecayFrame("T1","t_{a}"); RDecayFrame* T2 = new RDecayFrame("T2","t_{b}"); RVisibleFrame* Bjet1 = new RVisibleFrame("B1","b_{a}"); RVisibleFrame* Bjet2 = new RVisibleFrame("B2","b_{b}"); RDecayFrame* W1 = new RDecayFrame("W1","W_{a}"); RDecayFrame* W2 = new RDecayFrame("W2","W_{b}"); RVisibleFrame* Lep1 = new RVisibleFrame("L1","#it{l}_{a}"); RVisibleFrame* Lep2 = new RVisibleFrame("L2","#it{l}_{b}"); RInvisibleFrame* Neu1 = new RInvisibleFrame("NU1","#nu_{a}"); RInvisibleFrame* Neu2 = new RInvisibleFrame("NU2","#nu_{b}"); cout << " Define invisible and combinatoric groups " << endl; InvisibleGroup INV("INV","Invisible State Jigsaws"); INV.AddFrame(Neu1); INV.AddFrame(Neu2); CombinatoricGroup BTAGS("BTAGS","B-tagged jet Jigsaws"); BTAGS.AddFrame(Bjet1); BTAGS.SetNElementsForFrame(Bjet1,1,true); BTAGS.AddFrame(Bjet2); BTAGS.SetNElementsForFrame(Bjet2,1,true); cout << " Build decay tree " << endl; LAB->SetChildFrame(TT); TT->AddChildFrame(T1); TT->AddChildFrame(T2); T1->AddChildFrame(Bjet1); T1->AddChildFrame(W1); T2->AddChildFrame(Bjet2); T2->AddChildFrame(W2); W1->AddChildFrame(Lep1); W1->AddChildFrame(Neu1); W2->AddChildFrame(Lep2); W2->AddChildFrame(Neu2); //check that tree topology is consistent cout << "Is consistent topology: " << LAB->InitializeTree() << endl; cout << "Initializing jigsaw rules" << endl; InvisibleMassJigsaw MinMassJigsaw("MINMASS_JIGSAW", "Invisible system mass Jigsaw"); INV.AddJigsaw(MinMassJigsaw); InvisibleRapidityJigsaw RapidityJigsaw("RAPIDITY_JIGSAW", "Invisible system rapidity Jigsaw"); INV.AddJigsaw(RapidityJigsaw); RapidityJigsaw.AddVisibleFrame((LAB->GetListVisibleFrames())); ContraBoostInvariantJigsaw TopJigsaw("TOP_JIGSAW","Contraboost invariant Jigsaw"); INV.AddJigsaw(TopJigsaw); TopJigsaw.AddVisibleFrame((T1->GetListVisibleFrames()), 0); TopJigsaw.AddVisibleFrame((T2->GetListVisibleFrames()), 1); TopJigsaw.AddInvisibleFrame((T1->GetListInvisibleFrames()), 0); TopJigsaw.AddInvisibleFrame((T2->GetListInvisibleFrames()), 1); MinimizeMassesCombinatoricJigsaw BLJigsaw("BL_JIGSAW","Minimize m_{b#it{l}}'s Jigsaw"); BTAGS.AddJigsaw(BLJigsaw); BLJigsaw.AddFrame(Bjet1,0); BLJigsaw.AddFrame(Lep1,0); BLJigsaw.AddFrame(Bjet2,1); BLJigsaw.AddFrame(Lep2,1); cout << "Initializing the tree for analysis : " << LAB->InitializeAnalysis() << endl; //draw tree with jigsaws FramePlot* jigsaw_plot = new FramePlot("tree","Decay Tree"); jigsaw_plot->AddFrameTree(LAB); jigsaw_plot->AddJigsaw(TopJigsaw); jigsaw_plot->AddJigsaw(BLJigsaw); jigsaw_plot->DrawFramePlot(); for(int i = 0; i < N; i++){ if(b_gamma){ gamma = h_gamma->GetRandom(); } ////////////////////////////////////////////////////////////// // BEGIN CODE TO generate toy GEN LEVEL events ////////////////////////////////////////////////////////////// double Mt1 = 175.; double MW1 = 80.; double Mt2 = 175.; double MW2 = 80.; double Mnu1 = 0.; double Mnu2 = 0.; GetLepTopHem(0, Mt1, MW1, 5., 0.005, Mnu1); GetLepTopHem(1, Mt2, MW2, 5., 0.005, Mnu2); double EB1 = (Mt1*Mt1 - MW1*MW1)/(2.*Mt1); double EB2 = (Mt2*Mt2 - MW2*MW2)/(2.*Mt2); double EVIS1 = (Mt1*Mt1 - Mnu1*Mnu1)/(Mt1); double EVIS2 = (Mt2*Mt2 - Mnu2*Mnu2)/(Mt2); double EW1 = (Mt1*Mt1 + MW1*MW1)/(2.*Mt1); double EW2 = (Mt2*Mt2 + MW2*MW2)/(2.*Mt2); double EL1 = (MW1*MW1-Mnu1*Mnu1)/(2.*MW1); double EL2 = (MW2*MW2-Mnu2*Mnu2)/(2.*MW2); double gamma1 = EW1/MW1; double gamma2 = EW2/MW2; double beta1 = 1.; double beta2 = 1.; //put them in the lab frame BoostToLabFrame(gamma); // effective gamma factor for parents in CM frame double g_eff = (P[0]+P[1]).M()/(2.*sqrt(P[0].M()*P[1].M())); PtBoost(PT); ////////////////////////////////////////////////////////////// // END CODE TO generate toy GEN LEVEL event ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // BEGIN CODE TO analyze GEN LEVEL events ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // First, we calculate approximate neutrino 4-vectors // in W frames using two different strategies ////////////////////////////////////////////////////////////// TLorentzVector NU1_top, NU2_top, NU1_W, NU2_W; // // first, we will assign 4-vectos in the lab frame for // NU1_top and NU2_top by drawing a contraboost invariant symmetry // between the two BL systems and neutrinos. // Here, the tops are assumed to have the same boost factor in TT // rest frame. // for(;;){ // get MET in lab frame TVector3 MET = (vMiss[0]+vMiss[1]).Vect(); MET.SetZ(0.0); // get b-quarks in lab frame TLorentzVector B1, B2; B1 = C_2[0]; B2 = C_2[1]; // get leptons in lab frame TLorentzVector L1, L2; L1 = C_1_1[0]; L2 = C_1_1[1]; // // We separate the objects into decay hemispheres // practice we will need to assign BL pairs according to // metric (see commented below) // TLorentzVector VISTOT = B1+L1+B2+L2; TVector3 boostTOT = VISTOT.BoostVector(); B1.Boost(-boostTOT); B2.Boost(-boostTOT); L1.Boost(-boostTOT); L2.Boost(-boostTOT); if( (B1+L2).P() > (B1+L1).P() ){ TLorentzVector temp = B1; B1 = B2; B2 = temp; } B1.Boost(boostTOT); B2.Boost(boostTOT); L1.Boost(boostTOT); L2.Boost(boostTOT); // // visible hemispheres of top decays // TLorentzVector H1 = (B1+L1); TLorentzVector H2 = (B2+L2); // // We will now attempt to travel through approximations of each of the rest frames // of interest, beginning in the lab frame and ending in the TT rest frame, where // we will specify the neutrino 4-momenta according to a contraboost invariant // symmetry between the visible and invisible decay products of the two tops // // // first, we boost from the lab frame to intermediate 'CMz' frame // i.e. with the visible hemispheres' vectoral sum zero // TVector3 BL = H1.Vect()+H2.Vect(); BL.SetX(0.0); BL.SetY(0.0); BL = (1./(H1.E()+H2.E()))*BL; B1.Boost(-BL); L1.Boost(-BL); B2.Boost(-BL); L2.Boost(-BL); H1.Boost(-BL); H2.Boost(-BL); // // Now, we need to 'guess' the invariant mass of the weakly interacting system // as a Lorentz-invariant quantity which is a function of the visible system // masses, and large enough to accomodate the contraboost invariant // solution we will use in the following TT CM frame. This allows us to write down // the transverse part of the boost from lab to TT CM frame. // double Minv2 = (H1+H2).M2() - 4.*H1.M()*H2.M(); //double Minv2 = (H1+H2).M2() - 4.*min(H1.M2(),H2.M2()); // // transverse momentum of total TT system in lab frame // NOTE: (H1+H2).Pz() == 0 due to previous longitudinal boost // TVector3 PT = MET+(H1+H2).Vect(); double Einv2 = MET.Mag2() + Minv2; PT.SetZ(0.0); // redundant // // transverse boost from 'CMz' frame to TT CM frame // TVector3 BT = (1./( (H1+H2).E() + sqrt(Einv2) ))*PT; B1.Boost(-BT); L1.Boost(-BT); B2.Boost(-BT); L2.Boost(-BT); H1.Boost(-BT); H2.Boost(-BT); // // Now, in TT CM approx frame we will make a contraboost invariant choise for the assymmetric boost, then specifying // neutrino 4-vectors // // // contra-boost invariant quantities (for this boost) // double m1 = H1.M(); double m2 = H2.M(); double MC2 = 2.*( H1.E()*H2.E() + H1.Vect().Dot(H2.Vect()) ); // // contra-boost invariant coefficients // double k1 = m1*m1-m2*m2 + MC2 - 2.*m1*m2; double k2 = m2*m2-m1*m1 + MC2 - 2.*m1*m2; double N = ( fabs(k1*m1*m1 - k2*m2*m2) - 0.5*fabs(k2-k1)*MC2 + 0.5*(k1+k2)*sqrt(MC2*MC2-4.*m1*m1*m2*m2) )/(k1*k1*m1*m1+k2*k2*m2*m2+k1*k2*MC2); double c1 = 0.5*(1.+N*k1); double c2 = 0.5*(1.+N*k2); //c1 = 1; //c2 = 1; // // adjust coefficients such that di-neutrino invariant mass is equal to the Lorentz-invariant value we chose earlier, // maintaining a contra-boost invariant ratio // double A = ( H1.E()+H2.E() + sqrt( (H1.E()+H2.E())*(H1.E()+H2.E()) -(H1+H2).M2() + Minv2 ))/(c1*H1.E()+c2*H2.E())/2.; c1 *= A; c2 *= A; double Enu1 = (c1-1.)*H1.E() + c2*H2.E(); double Enu2 = c1*H1.E() + (c2-1.)*H2.E(); TVector3 pnu1 = (c1-1.)*H1.Vect() - c2*H2.Vect(); TVector3 pnu2 = (c2-1.)*H2.Vect() - c1*H1.Vect(); // // define neutrino 4-vectors // NU1_top.SetPxPyPzE(pnu1.X(),pnu1.Y(),pnu1.Z(),Enu1); NU2_top.SetPxPyPzE(pnu2.X(),pnu2.Y(),pnu2.Z(),Enu2); // // now, transform neutrinos back into lab frame // NU1_top.Boost(BT); NU2_top.Boost(BT); NU1_top.Boost(BL); NU2_top.Boost(BL); break; } // // Next, we will assign 4-vectos in the lab frame for // NU1_W and NU2_W by drawing a contraboost invariant symmetry // between the two L systems and neutrinos. // Here, the W's are assumed to have the same boost factor in the WW // rest frame. // for(;;){ TVector3 MET = (vMiss[0]+vMiss[1]).Vect(); MET.SetZ(0.0); //get b-quarks in lab frame TLorentzVector B1, B2; B1 = C_2[0]; B2 = C_2[1]; //get leptons in lab frame TLorentzVector L1, L2; L1 = C_1_1[0]; L2 = C_1_1[1]; // // We separate the objects into decay hemispheres // practice we will need to assign BL pairs according to // metric (see commented below) // TLorentzVector VISTOT = B1+L1+B2+L2; TVector3 boostTOT = VISTOT.BoostVector(); B1.Boost(-boostTOT); B2.Boost(-boostTOT); L1.Boost(-boostTOT); L2.Boost(-boostTOT); if( (B1+L2).P() > (B1+L1).P() ){ TLorentzVector temp = B1; B1 = B2; B2 = temp; } B1.Boost(boostTOT); B2.Boost(boostTOT); L1.Boost(boostTOT); L2.Boost(boostTOT); // // visible hemispheres of top decays // TLorentzVector H1 = (B1+L1); TLorentzVector H2 = (B2+L2); // // We will now attempt to travel through approximations of each of the rest frames // of interest, beginning in the lab frame and ending in the WW rest frame, where // we will specify the neutrino 4-momenta according to a contraboost invariant // symmetry between the visible and invisible decay products of the two W's // // // first, we boost from the lab frame to intermediate 'CMz' frame // i.e. with the visible hemispheres' vectoral sum zero // TVector3 BL = H1.Vect()+H2.Vect(); BL.SetX(0.0); BL.SetY(0.0); BL = (1./(H1.E()+H2.E()))*BL; B1.Boost(-BL); L1.Boost(-BL); B2.Boost(-BL); L2.Boost(-BL); H1.Boost(-BL); H2.Boost(-BL); // // Now, we need to 'guess' the invariant mass of the weakly interacting system // as a Lorentz-invariant quantity which is a function of the visible system // masses, and large enough to accomodate the contraboost invariant // solution we will use in the following WW CM frame. This allows us to write down // the transverse part of the boost from lab to WW CM frame. // double Minv2 = (L1+L2).M2(); TVector3 PT = MET+(L1+L2).Vect(); double Einv2 = MET.Mag2() + Minv2; TVector3 BT = (1./( (L1+L2).E() + sqrt(Einv2) ))*PT; L1.Boost(-BT); L2.Boost(-BT); // // Now, in WW CM approx frame we will make a contraboost invariant choise for the assymmetric boost, then specifying // neutrino 4-vectors // // // contra-boost invariant coefficients are both 1, scaling factor to fix di-neutrino invariant mass // is 1, since (L1+L2).M2() = Minv2 // double c = ( L1.E()+L2.E() + sqrt( (L1.E()+L2.E())*(L1.E()+L2.E()) -(L1+L2).M2() + Minv2 ))/(L1.E()+L2.E())/2.; //obviously redundant double Enu1 = (c-1.)*L1.E() + c*L2.E(); double Enu2 = c*L1.E() + (c-1.)*L2.E(); TVector3 pnu1 = (c-1.)*L1.Vect() - c*L2.Vect(); TVector3 pnu2 = (c-1.)*L2.Vect() - c*L1.Vect(); //define neutrino 4-vectors NU1_W.SetPxPyPzE(pnu1.X(),pnu1.Y(),pnu1.Z(),Enu1); NU2_W.SetPxPyPzE(pnu2.X(),pnu2.Y(),pnu2.Z(),Enu2); //now, go back to lab frame NU1_W.Boost(BT); NU2_W.Boost(BT); NU1_W.Boost(BL); NU2_W.Boost(BL); break; } // // Now we have our guess for the neutrino 4-vectors in the lab frame // using two different approaches (top or W symmetry, NUi_top and NUi_W // 4-vectors, respectively), along with the 'truth' values. // We will now go through all of the relevant reference frames in our approximate // reconstructions and in truth simultaenously to calculate observables // TLorentzVector B1, B2; B1 = C_2[0]; B2 = C_2[1]; //get leptons in lab frame TLorentzVector L1, L2; L1 = C_1_1[0]; L2 = C_1_1[1]; //get truth neutrinos in lab frame TLorentzVector NU1, NU2; NU1 = C_1_2[0]; NU2 = C_1_2[1]; TVector3 MET = (vMiss[0]+vMiss[1]).Vect(); MET.SetZ(0.0); INV.ClearEvent(); BTAGS.ClearEvent(); Lep1->SetLabFrameFourVector(L1); Lep2->SetLabFrameFourVector(L2); GroupElementID B1_ID = BTAGS.AddLabFrameFourVector(B1); GroupElementID B2_ID = BTAGS.AddLabFrameFourVector(B2); INV.SetLabFrameThreeVector(MET); LAB->AnalyzeEvent(); // // Now we have two different sets of neutrino guesses in lab frame - define matching visible particles // TLorentzVector B1_top = B1; TLorentzVector B2_top = B2; TLorentzVector L1_top = L1; TLorentzVector L2_top = L2; TLorentzVector B1_W = B1; TLorentzVector B2_W = B2; TLorentzVector L1_W = L1; TLorentzVector L2_W = L2; // // We separate the objects into decay hemispheres // practice we will need to assign BL pairs according to // metric for 'reconstructed' events (see commented below) // TLorentzVector VISTOT_top = B1_top+L1_top+B2_top+L2_top; TVector3 boostTOT_top = VISTOT_top.BoostVector(); B1_top.Boost(-boostTOT_top); B2_top.Boost(-boostTOT_top); L1_top.Boost(-boostTOT_top); L2_top.Boost(-boostTOT_top); if( (B1_top+L2_top).P() > (B1_top+L1_top).P() ){ TLorentzVector temp = B1_top; B1_top = B2_top; B2_top = temp; } B1_top.Boost(boostTOT_top); B2_top.Boost(boostTOT_top); L1_top.Boost(boostTOT_top); L2_top.Boost(boostTOT_top); /* if( (B1_W+L1_W).M2()+(B2_W+L2_W).M2() > (B1_W+L2_W).M2()+(B2_W+L1_W).M2() ){ TLorentzVector temp = L1_W; L1_W = L2_W; L2_W = temp; } */ // // visible hemispheres of top decays // TLorentzVector H1 = L1+B1+NU1; TLorentzVector H2 = L2+B2+NU2; TLorentzVector H1_top = L1_top+B1_top+NU1_top; TLorentzVector H2_top = L2_top+B2_top+NU2_top; TLorentzVector H1_W = L1+B1+NU1_W; TLorentzVector H2_W = L2+B2+NU2_W; cout << "TT mass: " << (H1_top+H2_top).M() << " " << TT->GetMass() << endl; cout << "T1 mass: " << H1_top.M() << " " << T1->GetMass() << endl; cout << "T2 mass: " << H2_top.M() << " " << T2->GetMass() << endl; cout << "W1 mass: " << (L1_top+NU1_top).M() << " " << W1->GetMass() << endl; cout << "W2 mass: " << (L2_top+NU2_top).M() << " " << W2->GetMass() << endl; cout << "NU1 mass: " << NU1_top.M() << " " << Neu1->GetMass() << endl; cout << "NU2 mass: " << NU2_top.M() << " " << Neu2->GetMass() << endl; cout << "MET: " << (Neu1->GetFourVector(LAB)+Neu2->GetFourVector(LAB)).Pt() << " " << MET.Mag() << endl; /* cout << "TT mass: " << (H1_W+H2_W).M() << " " << TT->GetMass() << endl; cout << "T1 mass: " << H1_W.M() << " " << T1->GetMass() << endl; cout << "T2 mass: " << H2_W.M() << " " << T2->GetMass() << endl; cout << "W1 mass: " << (L1+NU1_W).M() << " " << W1->GetMass() << endl; cout << "W2 mass: " << (L2+NU2_W).M() << " " << W2->GetMass() << endl; cout << "NU1 mass: " << NU1_W.M() << " " << Neu1->GetMass() << endl; cout << "NU2 mass: " << NU2_W.M() << " " << Neu2->GetMass() << endl; */ // // In the lab frame - let's move now to the ttbar CM frame // boosts // TVector3 BltoCM = (H1+H2).BoostVector(); TVector3 BltoCM_top = (H1_top+H2_top).BoostVector(); TVector3 BltoCM_W = (H1_W+H2_W).BoostVector(); H1.Boost(-BltoCM); H2.Boost(-BltoCM); L1.Boost(-BltoCM); L2.Boost(-BltoCM); NU1.Boost(-BltoCM); NU2.Boost(-BltoCM); B1.Boost(-BltoCM); B2.Boost(-BltoCM); H1_top.Boost(-BltoCM_top); H2_top.Boost(-BltoCM_top); L1_top.Boost(-BltoCM_top); L2_top.Boost(-BltoCM_top); B1_top.Boost(-BltoCM_top); B2_top.Boost(-BltoCM_top); NU1_top.Boost(-BltoCM_top); NU2_top.Boost(-BltoCM_top); H1_W.Boost(-BltoCM_W); H2_W.Boost(-BltoCM_W); L1_W.Boost(-BltoCM_W); L2_W.Boost(-BltoCM_W); B1_W.Boost(-BltoCM_W); B2_W.Boost(-BltoCM_W); NU1_W.Boost(-BltoCM_W); NU2_W.Boost(-BltoCM_W); // // angles in the TT CM frames, approximate and true // double costhetaTT = H1.Vect().Unit().Dot( BltoCM.Unit() ); double dphiTT = fabs(H1.Vect().DeltaPhi( BltoCM )); double dphiM = fabs( (B1+B2+L1+L2).Vect().DeltaPhi( BltoCM )); double costhetaTT_top = fabs( H1_top.Vect().Unit().Dot( BltoCM_top.Unit() )); double dphiTT_top = fabs(H1_top.Vect().DeltaPhi( BltoCM_top )); double dphiM_top = fabs( (B1_top+B2_top+L1_top+L2_top).Vect().DeltaPhi( BltoCM_top )); double costhetaTT_W = fabs( H1_W.Vect().Unit().Dot( BltoCM_W.Unit() )); double dphiTT_W = fabs(H1_W.Vect().DeltaPhi( BltoCM_W )); double dphiM_W = fabs( (B1_W+B2_W+L1_W+L2_W).Vect().DeltaPhi( BltoCM_W )); //scale double MTT = (H1+H2).M(); double MTT_top = (H1_top+H2_top).M(); double MTT_W = (H1_W+H2_W).M(); // vector normal to decay plane of CM frame (for later azimuthal angles) TVector3 vNORM_CM_T1 = B1.Vect().Cross((L1+NU1).Vect()); TVector3 vNORM_CM_T2 = B2.Vect().Cross((L2+NU2).Vect()); double dphi_T1_T2 = vNORM_CM_T1.Angle(vNORM_CM_T2); double dot_dphi_T1_T2 = B1.Vect().Dot(vNORM_CM_T2); if(dot_dphi_T1_T2 < 0.0 && dphi_T1_T2 > 0.0){ dphi_T1_T2 = TMath::Pi()*2. - dphi_T1_T2; } TVector3 vNORM_CM_T1_top = B1_top.Vect().Cross((L1_top+NU1_top).Vect()); TVector3 vNORM_CM_T2_top = B2_top.Vect().Cross((L2_top+NU2_top).Vect()); double dphi_T1_T2_top = vNORM_CM_T1_top.Angle(vNORM_CM_T2_top); double dot_dphi_T1_T2_top = B1_top.Vect().Dot(vNORM_CM_T2_top); if(dot_dphi_T1_T2_top < 0.0 && dphi_T1_T2_top > 0.0){ dphi_T1_T2_top = TMath::Pi()*2. - dphi_T1_T2_top; } TVector3 vNORM_CM_T1_W = B1_W.Vect().Cross((L1_W+NU1_W).Vect()); TVector3 vNORM_CM_T2_W = B2_W.Vect().Cross((L2_W+NU2_W).Vect()); double dphi_T1_T2_W = vNORM_CM_T1_W.Angle(vNORM_CM_T2_W); double dot_dphi_T1_T2_W = B1.Vect().Dot(vNORM_CM_T2_W); if(dot_dphi_T1_T2_W < 0.0 && dphi_T1_T2_W > 0.0){ dphi_T1_T2_W = TMath::Pi()*2. - dphi_T1_T2_W; } double ddphi_T1_T2_top = sin(dphi_T1_T2_top-dphi_T1_T2); double ddphi_T1_T2_W = sin(dphi_T1_T2_W-dphi_T1_T2); // // To the next frames!!!! // now, to 'top' CM frame approxs and truth // TVector3 BCMtoT1 = H1.BoostVector(); TVector3 BCMtoT2 = H2.BoostVector(); TVector3 BCMtoT1_top = H1_top.BoostVector(); TVector3 BCMtoT2_top = H2_top.BoostVector(); TVector3 BCMtoT1_W = H1_W.BoostVector(); TVector3 BCMtoT2_W = H2_W.BoostVector(); B1.Boost(-BCMtoT1); B2.Boost(-BCMtoT2); L1.Boost(-BCMtoT1); L2.Boost(-BCMtoT2); NU1.Boost(-BCMtoT1); NU2.Boost(-BCMtoT2); B1_top.Boost(-BCMtoT1_top); B2_top.Boost(-BCMtoT2_top); L1_top.Boost(-BCMtoT1_top); L2_top.Boost(-BCMtoT2_top); NU1_top.Boost(-BCMtoT1_top); NU2_top.Boost(-BCMtoT2_top); B1_W.Boost(-BCMtoT1_W); B2_W.Boost(-BCMtoT2_W); L1_W.Boost(-BCMtoT1_W); L2_W.Boost(-BCMtoT2_W); NU1_W.Boost(-BCMtoT1_W); NU2_W.Boost(-BCMtoT2_W); cout << W1->GetFourVector(T1).E() << " " << (L1_top+NU1_top).E() << endl; cout << W2->GetFourVector(T2).E() << " " << (L2_top+NU2_top).E() << endl; // // decay angles in top frames // double costhetaT1 = B1.Vect().Unit().Dot(BCMtoT1.Unit()); double costhetaT2 = B2.Vect().Unit().Dot(BCMtoT2.Unit()); double costhetaT1_top = B1_top.Vect().Unit().Dot(BCMtoT1_top.Unit()); double costhetaT2_top = B2_top.Vect().Unit().Dot(BCMtoT2_top.Unit()); double costhetaT1_W = B1_W.Vect().Unit().Dot(BCMtoT1_W.Unit()); double costhetaT2_W = B2_W.Vect().Unit().Dot(BCMtoT2_W.Unit()); double dcosthetaT1_top = costhetaT1_top*sqrt(1.-costhetaT1*costhetaT1)-costhetaT1*sqrt(1.-costhetaT1_top*costhetaT1_top); double dcosthetaT2_top = costhetaT2_top*sqrt(1.-costhetaT2*costhetaT2)-costhetaT2*sqrt(1.-costhetaT2_top*costhetaT2_top); double dcosthetaT1_W = costhetaT1_W*sqrt(1.-costhetaT1*costhetaT1)-costhetaT1*sqrt(1.-costhetaT1_W*costhetaT1_W); double dcosthetaT2_W = costhetaT2_W*sqrt(1.-costhetaT2*costhetaT2)-costhetaT2*sqrt(1.-costhetaT2_W*costhetaT2_W); //vectors normal to decay planes of T frames TVector3 vNORM_T1_B = B1.Vect().Cross(BCMtoT1); TVector3 vNORM_T2_B = B2.Vect().Cross(BCMtoT2); TVector3 vNORM_T1_B_top = B1_top.Vect().Cross(BCMtoT1_top); TVector3 vNORM_T2_B_top = B2_top.Vect().Cross(BCMtoT2_top); TVector3 vNORM_T1_B_W = B1_W.Vect().Cross(BCMtoT1_W); TVector3 vNORM_T2_B_W = B2_W.Vect().Cross(BCMtoT2_W); //vectors normal to W decay planes in T frames TVector3 vNORM_T1_W = L1.Vect().Cross(NU1.Vect()); TVector3 vNORM_T2_W = L2.Vect().Cross(NU2.Vect()); TVector3 vNORM_T1_W_top = L1_top.Vect().Cross(NU1_top.Vect()); TVector3 vNORM_T2_W_top = L2_top.Vect().Cross(NU2_top.Vect()); TVector3 vNORM_T1_W_W = L1_W.Vect().Cross(NU1_W.Vect()); TVector3 vNORM_T2_W_W = L2_W.Vect().Cross(NU2_W.Vect()); double dphi_W_T1 = vNORM_T1_W.Angle(vNORM_T1_B); double dphi_W_T2 = vNORM_T2_W.Angle(vNORM_T2_B); double dot_dphi_W_T1 = L1.Vect().Dot(vNORM_T1_B); double dot_dphi_W_T2 = L2.Vect().Dot(vNORM_T2_B); if(dot_dphi_W_T1 < 0.0 && dphi_W_T1 > 0.0){ dphi_W_T1 = TMath::Pi()*2. - dphi_W_T1; } if(dot_dphi_W_T2 < 0.0 && dphi_W_T2 > 0.0){ dphi_W_T2 = TMath::Pi()*2. - dphi_W_T2; } double dphi_W_T1_top = vNORM_T1_W_top.Angle(vNORM_T1_B_top); double dphi_W_T2_top = vNORM_T2_W_top.Angle(vNORM_T2_B_top); double dot_dphi_W_T1_top = L1_top.Vect().Dot(vNORM_T1_B_top); double dot_dphi_W_T2_top = L2_top.Vect().Dot(vNORM_T2_B_top); if(dot_dphi_W_T1_top < 0.0 && dphi_W_T1_top > 0.0){ dphi_W_T1_top = TMath::Pi()*2. - dphi_W_T1_top; } if(dot_dphi_W_T2_top < 0.0 && dphi_W_T2_top > 0.0){ dphi_W_T2_top = TMath::Pi()*2. - dphi_W_T2_top; } double dphi_W_T1_W = vNORM_T1_W_W.Angle(vNORM_T1_B_W); double dphi_W_T2_W = vNORM_T2_W_W.Angle(vNORM_T2_B_W); double dot_dphi_W_T1_W = L1_W.Vect().Dot(vNORM_T1_B_W); double dot_dphi_W_T2_W = L2_W.Vect().Dot(vNORM_T2_B_W); if(dot_dphi_W_T1_W < 0.0 && dphi_W_T1_W > 0.0){ dphi_W_T1_W = TMath::Pi()*2. - dphi_W_T1_W; } if(dot_dphi_W_T2_W < 0.0 && dphi_W_T2_W > 0.0){ dphi_W_T2_W = TMath::Pi()*2. - dphi_W_T2_W; } // // differences between true and reco azimuthal angles // double ddphi_W_T1_top = sin(dphi_W_T1_top-dphi_W_T1); double ddphi_W_T2_top = sin(dphi_W_T2_top-dphi_W_T2); double ddphi_W_T1_W = sin(dphi_W_T1_W-dphi_W_T1); double ddphi_W_T2_W = sin(dphi_W_T2_W-dphi_W_T2); // // gamma for asymmetric boost // double gammaT = 1./pow( (1.-BCMtoT1.Mag2())*(1.-BCMtoT2.Mag2()),1./4. ); double gammaT_top = 1./sqrt(1.-BCMtoT1_top.Mag2()); double gammaT_W = 1./pow( (1.-BCMtoT1_W.Mag2())*(1.-BCMtoT2_W.Mag2()),1./4. ); // // scale variables // double MT1 = H1.M(); double MT2 = H2.M(); double MT_top = H1_top.M(); double MT1_W = H1_W.M(); double MT2_W = H2_W.M(); double Eb1 = B1.E(); double Eb2 = B2.E(); double Eb1_top = B1_top.E(); double Eb2_top = B2_top.E(); double Eb1_W = B1_W.E(); double Eb2_W = B2_W.E(); // // Heading to the last frames!!!!! // from the T rest frames to the W rest frames // TVector3 BTtoW1 = (L1+NU1).BoostVector(); TVector3 BTtoW2 = (L2+NU2).BoostVector(); TVector3 BTtoW1_top = (L1_top+NU1_top).BoostVector(); TVector3 BTtoW2_top = (L2_top+NU2_top).BoostVector(); TVector3 BTtoW1_W = (L1_W+NU1_W).BoostVector(); TVector3 BTtoW2_W = (L2_W+NU2_W).BoostVector(); L1.Boost(-BTtoW1); NU1.Boost(-BTtoW1); L2.Boost(-BTtoW2); NU2.Boost(-BTtoW2); L1_top.Boost(-BTtoW1_top); NU1_top.Boost(-BTtoW1_top); L2_top.Boost(-BTtoW2_top); NU2_top.Boost(-BTtoW2_top); L1_W.Boost(-BTtoW1_W); NU1_W.Boost(-BTtoW1_W); L2_W.Boost(-BTtoW2_W); NU2_W.Boost(-BTtoW2_W); // // scales in the W rest frame // double El1 = L1.E(); double El2 = L2.E(); double El1_top = L1_top.E(); double El2_top = L2_top.E(); double El1_W = L1_W.E(); double El2_W = L2_W.E(); //calculate some angles double costhetaW1 = L1.Vect().Unit().Dot(BTtoW1.Unit()); double costhetaW2 = L2.Vect().Unit().Dot(BTtoW2.Unit()); double costhetaW1_top = L1_top.Vect().Unit().Dot(BTtoW1_top.Unit()); double costhetaW2_top = L2_top.Vect().Unit().Dot(BTtoW2_top.Unit()); double costhetaW1_W = L1_W.Vect().Unit().Dot(BTtoW1_W.Unit()); double costhetaW2_W = L2_W.Vect().Unit().Dot(BTtoW2_W.Unit()); double dcosthetaW1_top = costhetaW1*sqrt(1.-costhetaW1_top*costhetaW1_top) - costhetaW1_top*sqrt(1.-costhetaW1*costhetaW1); double dcosthetaW2_top = costhetaW2*sqrt(1.-costhetaW2_top*costhetaW2_top) - costhetaW2_top*sqrt(1.-costhetaW2*costhetaW2); double dcosthetaW1_W = costhetaW1*sqrt(1.-costhetaW1_W*costhetaW1_W) - costhetaW1_W*sqrt(1.-costhetaW1*costhetaW1); double dcosthetaW2_W = costhetaW2*sqrt(1.-costhetaW2_W*costhetaW2_W) - costhetaW2_W*sqrt(1.-costhetaW2*costhetaW2); // define different scale sensitive ratios double El1Eb1_top = El1_top/(El1_top+Eb1_top); double El1Eb1_W = El1_W/(El1_W+Eb1_W); double El1Eb2_top = El1_top/(El1_top+Eb2_top); double El1Eb2_W = El1_W/(El1_W+Eb2_W); cout << "TT costheta: " << costhetaTT_top << " " << TT->GetCosDecayAngle() << endl; cout << "T1 costheta: " << costhetaT1_top << " " << T1->GetCosDecayAngle() << endl; cout << "T2 costheta: " << costhetaT2_top << " " << T2->GetCosDecayAngle() << endl; cout << "dphi_T1_T2_top: " << dphi_T1_T2_top << " " << T1->GetDeltaPhiDecayPlanes(T2) << endl; cout << "dphi_W_T1_top: " << dphi_W_T1_top << " " << T1->GetDeltaPhiDecayPlanes(W1) << endl; TLorentzVector newB1 = Bjet1->GetFourVector(T1); TLorentzVector newB2 = Bjet2->GetFourVector(T2); TLorentzVector newL1 = Lep1->GetFourVector(W1); TLorentzVector newL2 = Lep2->GetFourVector(W2); TLorentzVector newNU1 = Neu1->GetFourVector(W1); TLorentzVector newNU2 = Neu2->GetFourVector(W2); cout << "Eb1: " << Eb1_top << " " << newB1.E() << endl; cout << "Eb2: " << Eb2_top << " " << newB2.E() << endl; cout << "El1: " << El1_top << " " << newL1.E() << endl; cout << "El2: " << El2_top << " " << newL2.E() << endl; cout << "ENU1: " << NU1_top.E() << " " << newNU1.E() << endl; cout << "ENU2: " << NU2_top.E() << " " << newNU2.E() << endl; } }