#include #include "PndVtxPRG.h" #include "RhoBase/RhoCandListIterator.h" #include "RhoBase/RhoFactory.h" #include "TMatrixT.h" #include "PndAnalysisCalcTools.h" ClassImp(PndVtxPRG) TBuffer& operator>>(TBuffer& buf, PndVtxPRG *&obj) { obj = (PndVtxPRG*) buf.ReadObject(PndVtxPRG::Class()); return buf; } PndVtxPRG::PndVtxPRG( RhoCandidate* b) : RhoFitterBase(b), fDebug(false), fNIterations(2), fExpansionPoint(0.,0.,0.), // Assume Zero origin as default fPrgCov(5,5), fJacobian(5,7) { fVerbose=false; fCurrentHead=fHeadOfTree; } PndVtxPRG::~PndVtxPRG() { } Bool_t PndVtxPRG::CalcPrgParams(RhoCandidate* tcand, TVector3 expansionpoint) { // calculate helix and its covariance in the preigee representation TLorentzVector mom = tcand->P4(); TVector3 pos= tcand->GetPosition(); Double_t charge = tcand->GetCharge(); TMatrixD cov77 = tcand->Cov7(); Bool_t test = PndAnalysisCalcTools::P7toPRG(pos, mom, charge, cov77, expansionpoint, fPrgParams, fPrgCov, fJacobian, false); return test; } Bool_t PndVtxPRG::FitNode(RhoCandidate* b) { fCurrentHead=b; Bool_t check = Calculate(); if(check == kFALSE) { fChiSquare=-22222; Error("PndVtxPRG::FitNode()","Fit failed for composite %p. Set chisquare to %i.",b,fChiSquare); } return check; } // Double_t PndVtxPRG::FitVertexFull(TVector3& vtx, TMatrixD& cov) // { // // Calculate the Vertex in the full scheme and pass vertexing information directly // FitNode(fCurrentHead); // RhoCandidate* tcand = fCurrentHead->Daughter(0); // vtx = tcand->Pos(); // TMatrixD cov7 = tcand->Cov7(); // for(int i=0; i<3; i++)for(int j=0; j<3; j++) { // cov[i][j]=cov7[i][j]; // } // return fChiSquare; // } Double_t PndVtxPRG::FitVertexFast(TVector3& vtx, TMatrixD& cov, bool skipcov, int niter) { // Calculate a vertex of n tracks without considering the changes in momentum vector // the variables vtx & cov (3x3) are written and the Chi^2 is returned. // the current head candidate is set by FitNode during tree navigation or is the composite // which the fitter was initialized with. int nTrk = fCurrentHead->NDaughters(); fNDegreesOfFreedom=2*nTrk-3; for (int iterate=0;iterate w; std::vector xp; TMatrixD sumw(3,3); TMatrixD sumwx(3,1); Double_t determinant = 0.; for(int i=0; iDaughter(i); // get Helix in PRG notation from Billoir paper // (epsilon,z0,theta,phi0,rho) Bool_t testprg = CalcPrgParams(tcand,fExpansionPoint); if(!testprg) { return -2; } if (fVerbose) { printf("#$# Fast #$# Helix params:\n\t epsilon\t = %.4g cm\n\t Z0\t = %.4g cm\n\t theta\t = %.4g\n\t phi0\t = %.4g\n\t rho\t = %.4g\n",fPrgParams[0],fPrgParams[1],fPrgParams[2],fPrgParams[3],fPrgParams[4]); std::cout<<" #$# Fast #$# Helix cov: "; fPrgCov.Print(); } Double_t s = sin(fPrgParams[3]); Double_t c = cos(fPrgParams[3]); Double_t t = TMath::Tan(fPrgParams[2]); if(t!=0.) { t = 1/t; } else { return -3; } // t = cot(theta) TMatrixD COVi(2,2); // track parameter cov for (epsilon,z0) COVi[0][0]=fPrgCov[0][0]; COVi[0][1]=fPrgCov[0][1]; COVi[1][0]=fPrgCov[1][0]; COVi[1][1]=fPrgCov[1][1]; if(fVerbose) {std::cout<<" #$# Fast #$# COVi "; COVi.Print();} TMatrixD Di(2,3); // Derivative in V, 2x3 Di[0][0]=fJacobian[0][0]; // dEpsilon / dvx Di[0][1]=fJacobian[0][1]; // dEpsilon /dvy Di[0][2]=fJacobian[0][2]; // dEpsilon /dvz Di[1][0]=fJacobian[1][0]; // dZ0 /dvx Di[1][1]=fJacobian[1][1]; // dZ0 /dvy Di[1][2]=fJacobian[1][2]; // dZ0 /dvz if(fDebug) {std::cout<<" #$# Fast #$# Di "; Di.Print();} TMatrixD xpi(1,3); xpi[0][0]=s*fPrgParams[0]; xpi[0][1]=-c*fPrgParams[0]; xpi[0][2]=fPrgParams[1]; xp.push_back(xpi); // save for later use if(fVerbose) {std::cout<<" #$# Fast #$# xpi "; xpi.Print();} //propagate to Vertex TMatrixD Wi(COVi); Wi.InvertFast(&determinant); if (determinant == 0.) { std::cout<<"PndVtxPRG: COVi Inversion failed, abort fit -888"< No check possible if(fDebug) {std::cout<<" #$# Fast #$# Wi"< No check possible if(fVerbose) {std::cout<<" #$# Fast #$# cV "; cV.Print();} TMatrixD V(cV,TMatrixD::kMult,sumwx);// result vertex V.T(); // make it a row vector if(fVerbose) {std::cout<<" #$# Fast #$# V "; V.Print();} vtx.SetXYZ(V[0][0],V[0][1],V[0][2]); vtx += fExpansionPoint; // move back to origin if(fVerbose) {std::cout<<" #$# Fast #$# Vtx: "; vtx.Print();} if (skipcov) { fChiSquare = -111.;// skip chisqare calculation } else { Double_t chisq=0.; // calculate chisquare for(int i=0; iDaughter(i); const Double_t charge = tcand->GetCharge(); if(iteration==0) { //On the first run fetch the starting values (being updated) //Bool_t testprg = CalcPrgParams(tcand,fExpansionPoint); Bool_t testprg = CalcPrgParams(tcand,vtx); if(!testprg) {printf("#$# Fit #$# CANNOT CALCULATE TRACK PARAMETERS (momenta at origin)"); return kFALSE;} qip[0][i]=0.;//fPrgParams[0];// the initial guess is AT the guess vertex. No epsilon_0 qip[1][i]=0.;//fPrgParams[1];// the initial guess is AT the guess vertex. No z_0 qip[2][i]=fPrgParams[2];// qip[3][i]=fPrgParams[3];//phi0 qip[4][i]=fPrgParams[4]; if(fDebug) {printf(" ##$# Fit #$# Measurement p: "); tcand->GetMomentum().Print();} if(fDebug) {printf(" ##$# Fit #$# Measurement x: "); tcand->GetPosition().Print();} momenta.push_back(tcand->GetMomentum()); momenta[i].SetPhi(fPrgParams[3]); // set phi while keeping magnitude and theta constant if(fDebug) {printf(" ##$# Fit #$# Momentum at Expansionpoint (phi=%g): ",fPrgParams[3]); momenta[i].Print();} } // get parameters closest to current vertex estimate Bool_t testvtx = CalcPrgParams(tcand,vtx); if(!testvtx) { return kFALSE; } if (fVerbose) { printf("#$# Fit #$# Helix params:\n\t epsilon = %.4g cm\n\t Z0\t = %.4g cm\n\t theta\t = %.4g\n\t phi0\t = %.4g\n\t rho\t = %.4g 1/cm\n\t charge\t = %g e\n",fPrgParams[0],fPrgParams[1],fPrgParams[2],fPrgParams[3],fPrgParams[4],charge); std::cout<<" #$# Fit #$# Helix cov: "; fPrgCov.Print(); } TMatrixD qiv(5,1); // parameters describing relative to expansion point the vertex seed qiv[0][0]=fPrgParams[0];//epsilon AT vertex zero qiv[1][0]=fPrgParams[1];//z0 AT vertex zero qiv[2][0]=fPrgParams[2];// qiv[3][0]=fPrgParams[3];//phi0 qiv[4][0]=fPrgParams[4];// //dqi = q_measured - F_0 == div-qip; TMatrixD qipi(5,1); for (int kk=0; kk<5; kk++) { qipi[kk][0]=qip[kk][i]; } TMatrixD dqi(qiv,TMatrixD::kMinus,qipi); dq.push_back(dqi); if(fDebug) {std::cout<<" #$# Fit #$# dqi "; dqi.Print();} TMatrixD COVi(5,5); // track parameter cov for (epsilon,z_p,Phi_p) //Double_t r=pocai.Perp(); COVi=fPrgCov; if(fVerbose) {std::cout<<" #$# Fit #$# COVi "; COVi.Print();} //Take the derivatives at the current vertex estimate (seed) (cf. Avery1 p.4) TMatrixD Di(5,3); // Derivative in V Di[0][0]=fJacobian[0][0]; // dEpsilon / dvx Di[0][1]=fJacobian[0][1]; // dEpsilon /dvy Di[0][2]=fJacobian[0][2]; // dEpsilon /dvz Di[1][0]=fJacobian[1][0]; // dZ0 /dvx Di[1][1]=fJacobian[1][1]; // dZ0 /dvy Di[1][2]=fJacobian[1][2]; // dZ0 /dvz Di[2][0]=fJacobian[2][0]; // Di[2][1]=fJacobian[2][1]; // Di[2][2]=fJacobian[2][2]; // Di[3][0]=fJacobian[3][0]; // dPhi0 /dvx Di[3][1]=fJacobian[3][1]; // dPhi0 /dvy Di[3][2]=fJacobian[3][2]; // dPhi0 /dvz Di[4][0]=fJacobian[4][0]; // Di[4][1]=fJacobian[4][1]; // Di[4][2]=fJacobian[4][2]; // //Di.T(); D.push_back(Di); if(fDebug) {std::cout<<" #$# Fit #$# Di "; Di.Print();} TMatrixD Ei(5,3); // Derivative in p Ei[0][0]=fJacobian[0][3]; // dEpsilon /dpx Ei[0][1]=fJacobian[0][4]; // dEpsilon /dpy Ei[0][2]=fJacobian[0][5]; // dEpsilon /dpz Ei[1][0]=fJacobian[1][3]; // dZ0 /dpx Ei[1][1]=fJacobian[1][4]; // dZ0 /dpy Ei[1][2]=fJacobian[1][5]; // dZ0 /dpz Ei[2][0]=fJacobian[2][3]; // Ei[2][1]=fJacobian[2][4]; // Ei[2][2]=fJacobian[2][5]; // Ei[3][0]=fJacobian[3][3]; // dPhi0 /dpx Ei[3][1]=fJacobian[3][4]; // dPhi0 /dpy Ei[3][2]=fJacobian[3][5]; // dPhi0 /dpz Ei[4][0]=fJacobian[4][3]; // Ei[4][1]=fJacobian[4][4]; // Ei[4][2]=fJacobian[4][5]; // //Ei.T(); E.push_back(Ei); if(fDebug) {std::cout<<" #$# Fit #$# Ei "; Ei.Print();} //det(aA) = a^n det(A) TMatrixD Wi(COVi); determinant=0.; Wi.InvertFast(&determinant); if (determinant==0) { std::cout<<"PndVtxPRG: COVi Inversion failed, abort fit."< uq; //dV.T(); double chiq=0; for(int i=0; iDaughter(i),chisquare); } if(chiq>0 && chiq<10000) { chisquare=chiq; } else { chisquare = -20; } // TODO: end iteration loop at satisfying chisq? }// end of iteratoin loop fChiSquare=chisquare; // calculating other cov matrices // POS COV for(int k=0; k<3; k++) for(int l=0; l<3; l++) { CovFitFull[k][l]=CovVV[k][l]; } // MOM-POS COV for(int i=0; iDaughter(i); // set fitted values tcand->SetPos(vtx); if(fDebug) {std::cout<<" #$# Fit #$# Final Momentum :("<SetP3(momenta[i]); for(int k=0; k<3; k++) for(int l=0; l<3; l++) { CovP7[k+3][l+3]=CovFitFull[3*(i+1)+k][3*(i+1)+l]; // momentum cov CovP7[k+3][l]=CovFitFull[3*(i+1)+k][l]; // momentum-position cov CovP7[l][k+3]=CovFitFull[l][3*(i+1)+k]; // momentum-position cov } // Calculate energy covariances: double invE = 1./tcand->E(); CovP7[3][6] = CovP7[6][3] = (momenta[i].X()*CovP7[3][3]+momenta[i].Y()*CovP7[3][4]+momenta[i].Z()*CovP7[3][5])*invE; CovP7[4][6] = CovP7[6][4] = (momenta[i].X()*CovP7[4][3]+momenta[i].Y()*CovP7[4][4]+momenta[i].Z()*CovP7[4][5])*invE; CovP7[5][6] = CovP7[6][5] = (momenta[i].X()*CovP7[5][3]+momenta[i].Y()*CovP7[5][4]+momenta[i].Z()*CovP7[5][5])*invE; CovP7[6][6] = (momenta[i].X()*momenta[i].X()*CovP7[3][3]+momenta[i].Y()*momenta[i].Y()*CovP7[4][4]+momenta[i].Z()*momenta[i].Z()*CovP7[5][5] +2.0*momenta[i].X()*momenta[i].Y()*CovP7[3][4] +2.0*momenta[i].X()*momenta[i].Z()*CovP7[3][5] +2.0*momenta[i].Y()*momenta[i].Z()*CovP7[4][5])*invE*invE; CovP7[6][0] = CovP7[0][6] = (momenta[i].X()*CovP7[3][0]+momenta[i].Y()*CovP7[4][0]+momenta[i].Z()*CovP7[5][0])*invE; CovP7[6][1] = CovP7[1][6] = (momenta[i].X()*CovP7[3][1]+momenta[i].Y()*CovP7[4][1]+momenta[i].Z()*CovP7[5][1])*invE; CovP7[6][2] = CovP7[2][6] = (momenta[i].X()*CovP7[3][2]+momenta[i].Y()*CovP7[4][2]+momenta[i].Z()*CovP7[5][2])*invE; tcand->SetCov7(CovP7); //tcand->Lock(); //?? autolocking //if(fDebug) {std::cout<<" #$# Fit #$# CovP7 with mom for traj "<SetPos(vtx); // that's where the P4 is defined SetFourMomentumByDaughters(fCurrentHead);//Cov7 updated by daughters, too! SetDecayVertex(fCurrentHead,vtx,CovVV); return kTRUE; // all good now! }