#include #include "PndKinVtxFitter.h" #include "RhoBase/TCandListIterator.h" #include "RhoBase/TRho.h" #include "RhoBase/TFactory.h" #include "TDecompLU.h" #include "TMatrixD.h" #include "TMatrixDSym.h" #include "PndVtxPoca.h" using namespace std; ClassImp(PndKinVtxFitter) TBuffer &operator>>(TBuffer &buf, PndKinVtxFitter *&obj) { obj = (PndKinVtxFitter *) buf.ReadObject(PndKinVtxFitter::Class()); return buf; } //Include only those constraint which need vertex Info.... PndKinVtxFitter::PndKinVtxFitter( const TCandidate& b) : VAbsFitter( b ) { fMassConstraint =-1; fPointConstraint=-1; } PndKinVtxFitter::~PndKinVtxFitter() { } void PndKinVtxFitter::AddMassConstraint(double mass) { fMassConstraint = 1; fMass=mass; } void PndKinVtxFitter::AddPointingConstraint(TVector3 pVtx) { fPointConstraint = 1; fpVtx=pVtx; } void PndKinVtxFitter::Fit() { FitLeaf(fHeadOfTree); } void PndKinVtxFitter::FitLeaf(TCandidate *head) { TCandidate *tc; //if (head->decayVtx() == 0 ) { if ( head->NDaughters()>0 ) { TCandListIterator iter=head->DaughterIterator(); while ((tc=iter.Next())) { if (tc->IsComposite()) FitLeaf(tc); // else if( (!tc->decayVtx() && !tc->isAResonance() ) } } //} fDaughters.Cleanup(); //FindAndAddGenericDaughters(fHeadOfTree); FindAndAddGenericDaughters(head); //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] Compute(); SetOutput(); } void PndKinVtxFitter::FindAndAddGenericDaughters(TCandidate *head) { TCandidate *tc; TCandListIterator iter=head->DaughterIterator(); while ((tc=iter.Next())) { fDaughters.Add(*tc); // //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] // if (!tc->IsComposite()) fDaughters.Add(*tc); // else FindAndAddGenericDaughters(tc); } } void PndKinVtxFitter::SetMatrices(){ int nd=fDaughters.GetLength(); fNvar=7; fNpart=nd; fNpar =nd*fNvar; fNcon=NumCon; // if(fVerbose) cout << fNcon << "Num " << endl; fNc=0; fNiter=0; al0.ResizeTo(7*nd,1); V_al0.ResizeTo(fNpar,fNpar); al1.ResizeTo(7*nd,1); V_al1.ResizeTo(fNpar,fNpar); vtx_ex.ResizeTo(3,1); vtx_st.ResizeTo(3,1); mPull.ResizeTo(7*nd,1); covC.ResizeTo(7,7); } void PndKinVtxFitter::ResetMatrices(){ al0.Zero(); V_al0.Zero(); al1.Zero(); V_al1.Zero(); mPull.Zero(); vtx_ex.Zero(); vtx_st.Zero(); covC.Zero(); } void PndKinVtxFitter::Compute() { // int nd=fDaughters.GetLength(); int nd=fDaughters.GetLength(); NumCon=0; fdgf =0; if(fMassConstraint >0){ int nMass = 1; NumCon = NumCon + nMass; } NumCon = NumCon +2*nd; SetMatrices(); ResetMatrices(); ReadMatrix(); TMatrixD cov_al_x(7*nd,3); TVector3 startVtx; GetStartVtx(startVtx); vtx_st[0][0]=startVtx.X();vtx_st[1][0]=startVtx.Y();vtx_st[2][0]=startVtx.Z(); // vtx_st[0][0]=0.0;vtx_st[1][0]=0.0;vtx_st[2][0]=0.0; vtx_ex=vtx_st; if(fVerbose) cout<<"Initial vertex Position is"<0){ ReadMassKinMatrix();} //FIXME: here should be an else statement, right? ReadKinMatrix(); TMatrixD mD_t=mD; mD_t.T(); // mD_t=mD_t.Transpose(mD); // mD_t.Print(); TMatrixD Vd_inv = mD*V_al0*mD_t; if(Vd_inv==0)continue; TMatrixD Vd = Vd_inv.Invert(&ierr); // if( ierr != 0 ){ // if(fVerbose) cout << "Inversion of constraint-matrix failed! " << endl; // return 0;} // Vd.Print(); TMatrixD del_al = al0 - al1; // Lagrange multiplier //TMatrixD lam0=Vd*md; TMatrixD lam0 = Vd* ( mD*del_al + md); // if(fVerbose) cout << " lam0 calculated" << endl; // Position Derivative matrix ............... TMatrixD mE_t=mE; mE_t.T(); TMatrixD Vx_inv = mE_t*Vd*mE; TMatrixD Vx=Vx_inv.Invert(&ierr); // Vx.Print(); // New vertex and covariance ........ TMatrixD V_vtx_new(3,3); TMatrixD vtx_new(vtx_ex); vtx_new -= Vx*mE_t*lam0; // if(fVerbose) cout << " New vtx calculated" << endl; // vtx_new.Print(); V_vtx_new = Vx; // Final Lagarange multiplier ........ TMatrixD lam = lam0 + (Vd * mE) * (vtx_new - vtx_ex); // if(fVerbose) cout << " New lam calculated" << endl; // New track parameters............. TMatrixD al_new(al0); al_new -= V_al0*mD_t*lam; // if(fVerbose) cout << " New track param calculated" << endl; //chiSquared TMatrixD lam_t=lam; lam_t.T(); // TMatrixD chi2_new = lam_t* md; //TMatrixD chi2_new = lam_t*(mD*(al0 - al_new) ); TMatrixD chi2_new = lam_t*(mD*(al0 - al_new) + md); // TMatrixD chi2_new = lam_t*(mD*(al0 - al_new) + mE*(vtx_st-vtx_ex) + md); // New Covariance Matrix................ // TMatrixD V_al_new(V_al0); // V_al_new-=V_al0*mD_t*Vd*mD*V_al0_t; double deltaChi=chi2_new[0][0]-chi2[0][0]; // Check chi^2. If better yes update the values .............................. if (deltaChi>0.1*chi2[0][0]) {continue;} if( chi2_new[0][0] < chi2[0][0] ) { //if(true){ vtx_ex = vtx_new; al1 = al_new; // V_al0 = V_al_new; } // if (j1==0) {chi2=chi2_new;continue;} // If Chi^2 change is small then go out of iteration...................... if( fabs(chi2[0][0] - chi2_new[0][0]) < 0.01 ) j1 = j1Max - 1; chi2 = chi2_new; if( (j1+1) == j1Max ){ vtx_ex = vtx_new; al0 =al_new; // TMatrixD Vd_new(Vd); Vd_new -= Vd*(mE*Vx*mE_t)*Vd.T(); TMatrixD V_al_new(V_al0); V_al_new -= V_al0*(mD_t*Vd_new*mD)*V_al0.T(); cov_al_x -= V_al0*mD_t*Vd*mE*Vx; // Vertex-track Correlation //double covdif=(V_al0[6][6]-V_al_new[6][6]); // if (covdif > 0 ) {mPull[0][0] =(al0[6][0]-al_new[6][0])/sqrt(covdif);} mPull[0][0] =(al0[6][0]-al_new[6][0]); fPull=mPull[0][0]; V_al0 = V_al_new; V_vtx = V_vtx_new; } if(fVerbose) cout << "iteration Number " << " " << j1 << endl; if(fVerbose) cout << " chi2 in iterartion" << " " << chi2[0][0] << endl; } // end of iteration-loop TMatrixD al_new_vtx(7*nd,1); TMatrixD Va_new_vtx(7*nd,7*nd); // Trivial way for covariance matrix of composite // covC= // for(Int_t k=0;kSetP7(vtx,sum); head->SetP7(vtx,sum); //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] if(fVerbose) cout<<"Final vertex Position is"<SetCov7(covC); //New covariance matrix head->SetCov7(covC); //New covariance matrix //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] } //Read the input vector void PndKinVtxFitter::ReadMatrix() { int nd =fDaughters.GetLength(); TMatrixD m(nd,1); for (int k=0;k=3){ if(j>=3) p4Cov[i-3][j-3] = p2Cov[i][j];else p4Cov[i-3][j+3] = p2Cov[i][j]; }else {if(j>=3) p4Cov[i+4][j-3] = p2Cov[i][j];else p4Cov[i+4][j+4] = p2Cov[i][j];}}} for(int i=0;i<7;i++){ for (int j=0;j<7;j++){ V_al0[k*7+i][k*7+j] = p4Cov[i][j]; } } } } //Read Constraint Matrices ... D, E and d //unsigned PndKinVtxFitter:: ReadKinMatrix( TMatrixD & mD, TMatrixD & mE, TMatrixD & md) void PndKinVtxFitter::ReadKinMatrix() { int nd=fDaughters.GetLength(); fNc=0; mD.ResizeTo(fNcon,fNpar); mE.ResizeTo(fNcon,3); md.ResizeTo(fNcon,1); for (int k=0;kGetMagnetField(); //unused, why? double a = -0.0029979246*ch*2.0; //TODO: is bfield put here manually? double pT_2 = px*px + py*py; double J = a*(delX*px + delY*py)/pT_2; double Rx = delX - 2.*px*(delX*px + delY*py)/pT_2; double Ry = delY - 2.*py*(delX*px + delY*py)/pT_2; // if(fabs(J) > 1) {return 0;} if (J>=1.0 || J<= -1.0) { J = (J>=1.0 ? 0.99 : -0.99);} double S = 1./(pT_2*sqrt(1-(J*J))); // if(fVerbose) cout << ch << "ch" << S << "pt2" << J << "bField" << bField <GetCharge(); //unused //TLorentzVector p1=fHeadOfTree->P4(); //TVector3 p2=fHeadOfTree->Pos(); TLorentzVector p1=head->P4(); //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] TVector3 p2=head->Pos(); //[ralfk:01.12.11 Try to make it a leaf-by-leaf fit] double delX = p2.X() - fpVtx.X(); double delY = p2.Y() - fpVtx.Y(); double delZ = p2.Z() - fpVtx.Z(); double px = p1.X(); double py = p1.Y(); double pz = p1.Z(); //double bField = TRho::Instance()->GetMagnetField(); //unused, why? //double a = -0.0029979246*ch*2.0; //TODO: bfield put manually here? double pT = sqrt(px*px + py*py); double delT= sqrt(delX*delX + delY*delY); double p = sqrt(px*px + py*py + pz*pz); double T = sqrt(delX*delX + delY*delY + delZ*delZ); md[fNc+0][0] = (1-delX/delT)/(delY/delT) - (1-px/pT)/(py/pT); md[fNc+1][0]= (1-delT/T)/(delZ/T) - (1-(pT/p))/(pz/p); mD[fNc+0][0] = -(px/(py*pT) - 1/py); mD[fNc+0][1] = -(1/pT - pT/(py*py)+ px/(py*py)); mD[fNc+0][2] = 0; mD[fNc+0][3] = 0; mD[fNc+0][4] = delX/(delY*delT) - 1/delY; mD[fNc+0][5] = 1/delT - delT/delY*delY+ delX/(delY*delY); mD[fNc+0][6] = 0; //half angle solution mD[fNc+1][0] = -(px/pz)*(1/p - 1/pT); mD[fNc+1][1] = -(py/pz)*(1/p - 1/pT); mD[fNc+1][2] = -((1/(pz*pz))*(pT - p) + 1/p); mD[fNc+1][3] = 0; mD[fNc+1][4] = (delX/delZ)*(1/T - 1/delT); mD[fNc+1][5] = (delY/delZ)*(1/T - 1/delT); mD[fNc+1][6] = (1/(delZ*delZ))*(delT - T) + 1/T; } /* // better alternate way ......... md[fNc+0][0] = py/p*delX/delT-px/pT*delY/delT; md[fNc+1][0]= pz/p*pT/T-pT/p*delZ/T; mD[fNc+0][0] = -((py*(dx*px + dy*py))/(delT*pT*pT*PT)); mD[fNc+0][1] = -((py*(dx*px + dy*py))/(delT*pT*pT*PT)); mD[fNc+0][2] = 0; mD[fNc+0][3] = 0; mD[fNc+0][4] = (delY*(delX*px + delY*py))/(delT*delT*delT*pT) ; mD[fNc+0][5] = -((delX*(delX*px + delY*py))/(delT*delT*delT*pT)) ; mD[fNc+0][6] = 0; //2nd equation mD[fNc+1][0] = -((px*pz*(delT*pT + dz*pz))/(T*pT*(p*p*p)); //correct mD[fNc+1][1] = -((py*pz*(delT*pT + dz*pz))/(T*pT*(p*p*p)); mD[fNc+1][2] = (delT*pT*pT + dz*pT*pz)/(delT*p*p*p) ; mD[fNc+1][3] = 0; mD[fNc+1][4] = (dx*dz*(delT*pT + dz*pz))/(delT*T*T*T*p); mD[fNc+1][5] = (dy*dz*(delT*pT + dz*pz))/(delT*T*T*T*p); mD[fNc+1][6] = (-(delT*delT*pT) - delT*dz*pz)/(delT*delT*delT*p); } */ void PndKinVtxFitter::GetStartVtx(TVector3 &vertex) { vertex.SetXYZ(0.,0.,0.); int nd=fDaughters.GetLength(); if ( nd < 2 ) vertex.SetXYZ(0.,0.,0.); if ( nd == 2 ) GetPocaVtx(vertex,&fDaughters[0],&fDaughters[1]); std::vector distances; std::vector results; // loop over daughters, take the mean value of all "best" positions // TODO do this smarter by using already found vertices ? TVector3 theVertex(0.,0.,0.); Double_t actualDoca=0.; for(Int_t daug1 =0;daug1 Mean = Sum(x/(sigmax^2)) / Sum(Sigmax^2) // Averaging vertex results from each track pair how to do that? "geometric" or arithmetic mean? std::vector::iterator iterDoca; std::vector::iterator iterVtx; Double_t docaweight=0,sumdocaweigts=0; TVector3 vertexK; for(iterVtx=results.begin(), iterDoca=distances.begin();iterVtx!=results.end()&&iterDoca!=distances.end();++iterVtx,++iterDoca) { docaweight=1/(*iterDoca); //docaweight *= docaweight; vertexK=*iterVtx; if (docaweight == 0) docaweight = 1; // right so? vertexK *= docaweight; vertex+=vertexK; sumdocaweigts+=docaweight; } if (sumdocaweigts == 0) sumdocaweigts=1; vertex*=1./sumdocaweigts; //sumdocaweigts = sqrt(sumdocaweigts); // return fHeadOfTree->NDaughters()/sumdocaweigts; } Float_t PndKinVtxFitter::GetPocaVtx(TVector3 &vertex, TCandidate *a, TCandidate *b) { //Double_t d=1.0, Double_t a=3.14159265358979323846, Double_t r1=0.0, Double_t r2=1.E8 //Taken from the TVertexSelector . // if ( fDaughters.GetLength() != 2 ) SVtx->SetXYZ(0.,0.,0.); // TCandidate a=fDaughters[0]; // TCandidate b=fDaughters[1]; // SVtx->SetXYZ( 0.5, 0.5, 1.0 ); // SVtx->SetXYZ( 0.0, 0.0, 0.0 ); //Float_t bField = TRho::Instance()->GetMagnetField(); Double_t bField=2.0; // Position vectors TVector3 position1 = a->GetPosition(); TVector3 position2 = b->GetPosition(); // Momentum vectors TVector3 ap3 = a->P3(); Double_t pPerp1 = ap3.Perp(); TVector3 d1 = ap3; d1.SetZ(0); d1*=1.0/pPerp1; TVector3 bp3 = b->P3(); Double_t pPerp2 = bp3.Perp(); TVector3 d2 = bp3; d2.SetZ(0); d2*=1.0/pPerp2; TVector3 dB(0,0,1.0); // Radius and center Double_t rho1 = pPerp1/(0.0029979246*bField); // Radius in cm TVector3 r1=d1.Cross(dB); r1 *= -a->Charge()*rho1; TVector3 center1 = position1 - r1; center1.SetZ(0); Double_t rho2 = pPerp2/(0.0029979246*bField); // Radius in cm TVector3 r2=d2.Cross(dB); r2 *= -b->Charge()*rho2; TVector3 center2 = position2 - r2; center2.SetZ(0); // distance and angle of the axis between the two centers TVector3 ab = center2 - center1; Double_t dab = ab.Perp(); Double_t cosTheAB = ab.X()/dab; Double_t sinTheAB = ab.Y()/dab; // x value of intersect at reduced system Double_t x = dab/2 + ( rho1*rho1 - rho2*rho2 )/(2*dab); // y*y value of intersect at reduced system for helix A Double_t y2 = (rho1+x)*(rho1-x); // both circles do not intersect (only one solution) Int_t nSolMax=1; Double_t y=0; if (y2 > 0) { nSolMax=2; y = sqrt(y2); } // now we compute the solution(s) TVector3 newapos[2]; TVector3 newbpos[2]; Int_t best=0; double fActualDoca=1.E8; // fActualDoca=0.99999999; for (Int_t ns=0; ns0 ? 1.0 : -1.0; Double_t aangle=adir * r1.Angle(rs1); // intersection point Double_t newaz=position1.Z() + rho1*aangle/pPerp1 * ap3.Z(); newapos[ns].SetX( center1.X() + rs1.X() ); newapos[ns].SetY( center1.Y() + rs1.Y() ); newapos[ns].SetZ( newaz ); // same for b Double_t bdir=(rs2-r2).Dot(bp3)>0 ? 1.0 : -1.0; Double_t bangle=bdir * r2.Angle(rs2); Double_t newbz=position2.Z() + rho2*bangle/pPerp2 * bp3.Z(); newbpos[ns].SetX( center2.X() + rs2.X()); // ==newapos[ns].X() newbpos[ns].SetY( center2.Y() + rs2.Y()); // ==newapos[ns].Y() newbpos[ns].SetZ( newbz ); Double_t delta = (newapos[ns]-newbpos[ns]).Mag(); // take the solution of minimal deltaZ if ( delta < fActualDoca ) { best=ns; fActualDoca = delta; } } // TVector3 fVertex=0.5*(newapos[best]+newbpos[best]); // SVtx->SetXYZ( fVertex.X(), fVertex.Y(), fVertex.Z()); vertex=0.5*(newapos[best]+newbpos[best]); return fActualDoca; } void PndKinVtxFitter::TransportToVertex(TMatrixD &a_in, TMatrixD &a_cov_in, TMatrixD &a_out, TMatrixD &a_cov_out, TMatrixD &xref) { int fNDau=fDaughters.GetLength(); int nd=fNDau; TMatrixD U(7*nd,7*nd); int kN=0; for(int k=0; k