//----------------------------------------------------------- // File and Version Information: // $Id$ // // Description: // Implementation of class PndTpcRiemannTrack // see PndTpcRiemannTrack.hh for details // // Environment: // Software developed for the PANDA Detector at FAIR. // // Author List: // Sebastian Neubert TUM (original author) // // //----------------------------------------------------------- // Panda Headers ---------------------- // This Class' Header ------------------ #include "PndTpcRiemannTrack.h" // C/C++ Headers ---------------------- #include #include #include #include // Collaborating Class Headers -------- #include "PndTpcRiemannHit.h" #include "PndTpcCluster.h" #include "TMatrixD.h" #include "TVectorD.h" #include "TVector3.h" #include "TGraph.h" #include "TF1.h" #include "TMath.h" #include "TPolyMarker3D.h" #include "TCanvas.h" #include "TApplication.h" #include "TPolyLine3D.h" #include "TSystem.h" // Class Member definitions ----------- ClassImp(PndTpcRiemannTrack) PndTpcRiemannTrack::PndTpcRiemannTrack() : _n(3),_av(3), _sumOfWeights(0), _c(0),_m(0), _t(0), _isFitted(false), _isFittedPlane(false), _nit(0), _doSort(true) {} void PndTpcRiemannTrack::init(double x0_, double y0_, double R_, double Dip, double z0){ double x0=x0_/100; double y0=y0_/100; double R=R_/100; double R2=R*R; double lambda=R2-x0*x0-y0*y0; if(lambda==0)lambda=0.0001; double D=lambda/sqrt(4*R2+(1-lambda)*(1-lambda)); double DC=-D/lambda; double C=DC-D; double A=-2*x0*DC; double B=-2*y0*DC; _n[0]=A; _n[1]=B; _n[2]=C; _c=D; _m=Dip; _t=z0; } PndTpcRiemannHit* PndTpcRiemannTrack::getHit(unsigned int i) const { std::list::const_iterator it=_hits.begin(); std::advance(it, i); return *it; } PndTpcRiemannHit* PndTpcRiemannTrack::getLastHit() const { return _hits.back(); } //########################################################################## // Todo: can this be optimized? hitIt PndTpcRiemannTrack::getClosestHit(PndTpcRiemannHit* hit, double& Dist) { // check if we start at end or at beginning: TVector3 posX=hit->cluster()->pos(); TVector3 posend=_hits.back()->cluster()->pos(); TVector3 posstart=_hits.front()->cluster()->pos(); double s1x=(posX-posstart).Mag(); double s2x=(posX-posend).Mag(); int dir=0; if(s1x>=s2x){// hit closer to end of list dir=-1;// direction -1 --> start backwards search } else { // hit closer to start of list dir=+1; // direction 1 --> search from front to end } // prepare iterators through list hitIt it2; if(dir>0){ it2=_hits.begin(); } else { it2=_hits.end(); --it2; } TVector3 pos2=(*it2)->cluster()->pos(); //next point // find closest point to my hit int found=0; double dis=(pos2-posX).Mag(); double mindis=dis; //std::cout<<"dir="<cluster()->pos(); //next point dis=(pos2-posX).Mag(); //std::cout << dis << " "; if(dis0 ? ++it2 : --it2; } //if(it2==_hits.end()&& dir>0){std::cout<< "dropping out at end";} //std::cout << std::endl << "mindis="<cluster()->pos(); //next point TVector3 pos3=(*it3)->cluster()->pos(); // construct general direction of track from these three outdir=(pos3-pos1); outdir.SetMag(1); } else { TVector3 pos=hit->cluster()->pos(); //next point TVector3 pos2=(*it2)->cluster()->pos(); outdir=(pos2-pos); outdir.SetMag(1); } return it2; } //########################################################################## void PndTpcRiemannTrack::addHit(PndTpcRiemannHit* hit){ int nbefore=_hits.size(); _mcid.AddIDCollection(hit->cluster()->mcId(),1.); // update average double weightFactor = 1./(hit->cluster()->sig().Perp()); _av*=_sumOfWeights; _av[0]+=hit->x().X() * weightFactor; _av[1]+=hit->x().Y() * weightFactor; _av[2]+=hit->x().Z() * weightFactor; _sumOfWeights += weightFactor; _av*=1./_sumOfWeights; if(nbefore<2 || !_doSort){// first two hits hit _hits.push_back(hit); return; } // check if we start at end or at beginning: TVector3 posX=hit->cluster()->pos(); std::list::iterator it2=_hits.end(); --it2; TVector3 posend=(*it2)->cluster()->pos(); std::list::iterator it1=_hits.begin(); TVector3 posstart=(*it1)->cluster()->pos(); double s1x=(posX-posstart).Mag(); double s2x=(posX-posend).Mag(); _nit=0; // reset iteration counter if(s1x>=s2x){// hit closer to end of list _hits.insert(this->sortHit(hit,_hits,-1),hit); // direction -1 --> start backwards search } else { // hit closer to start of list _hits.insert(this->sortHit(hit,_hits,1),hit); // direction 1 --> search from front to end } } // returns iterator BEFORE which to insert hitX!!! // dir = 1 means start from beginning // dir = -1 means start from end hitIt PndTpcRiemannTrack::sortHit(PndTpcRiemannHit* hitX, hitList& hL, int dir){ // prepare iterators through list hitIt it2; if(dir>0){ it2=hL.begin(); } else { it2=hL.end(); --it2; } TVector3 posX=hitX->cluster()->pos(); TVector3 pos2=(*it2)->cluster()->pos(); //next point // find closest point to my hit int found=0; double dis=(pos2-posX).Mag(); double mindis=dis; //std::cout<<"dir="<cluster()->pos(); //next point dis=(pos2-posX).Mag(); //std::cout << dis << " "; if(dis0 ? ++it2 : --it2; } //if(it2==hL.end()&& dir>0){std::cout<< "dropping out at end";} //std::cout << std::endl << "mindis="<cluster()->pos(); //previous point (same if @ begin) TVector3 pos3=(*it3)->cluster()->pos(); //next point (same if @ end) // new simple approach by Johannes TVector3 d1 = posX-pos1; TVector3 d3 = posX-pos3; if(d1.Mag()>d3.Mag()){ // hit is nearer to next hit if(it3==it2) // we are at the end return ++it3; else return it3; } else // hit is nearer to previous hit return it2; /* // construct general direction of track from these three TVector3 d1=(pos3-pos1); TVector3 d2=(pos2-pos1); TVector3 dx=(posX-pos1); //d1.SetMag(1); //d2.SetMag(1); //dx.SetMag(1); TVector3 d=d1+d2+dx; if(d.Mag()==0){ std::cout<<"d=0"<0 && d31>dx1){ // different signs -> inside! //std::cout<<"X is inside 13!"<setPosOnTrk(0); hitIt itlast=--_hits.end(); while(it!=itlast){ double s1=(*it)->s(); TVector3 pos1=(*it)->cluster()->pos(); ++it; // next hit TVector3 pos2=(*it)->cluster()->pos(); (*it)->setPosOnTrk(s1+(pos2-pos1).Mag()); } } // returns winding sense along z-axis int PndTpcRiemannTrack::winding(){ hitIt it=_hits.begin(); TVector3 pos1=(*it)->cluster()->pos(); ++it;++it; TVector3 pos2=(*it)->cluster()->pos(); it=--_hits.end(); TVector3 pos3=(*it)->cluster()->pos(); int dir= pos1.Mag() last one is smallest _n=TMatrixDColumn(eigenVec,2); double norm=1./TMath::Sqrt(_n.Norm2Sqr()); _n*=norm; _c=-1.*_n*_av; _isFittedPlane = true; } double PndTpcRiemannTrack::planeRMS(){ if(!_isFittedPlane) return 0.; // get plane parameters TVector3 n3; n3.SetXYZ(_n[0], _n[1], _n[2]); // loop over hits and calculate RMS double rms = 0.; std::list::iterator it=_hits.begin(); while(it!=_hits.end()){ TVector3 pos = (*it)->x(); double distance = pos*n3 + _c; rms += distance*distance; ++it; } rms /= _hits.size(); rms = TMath::Sqrt(rms); return rms; } TVectorD PndTpcRiemannTrack::orig() const { TVectorD o(2); double den=0.5/(_c+_n[2]); o[0]=-_n[0]*den; o[1]=-_n[1]*den; return o; } double PndTpcRiemannTrack::r() const { if(_c==0)return 0; if(fabs(_c)>1000)return 0; double a=2.*(_c+_n[2]); //if(a==0){ // std::cout<<"PndTpcRiemannTrack:: a==0 cannot calc r! set r=1E4"<::iterator it=_hits.begin(); std::list::iterator lastit=it; if(!_isFitted){ TGraph g(4); for(unsigned int i=0;i<4;++i){ //(*it)->calcPosOnTrk((*lastit),false); g.SetPoint(i,(*it)->s(),(*it)->z()); //std::cout<<_hits[i]->z()<<"|"<<_hits[i]->s()<calcPosOnTrk((*lastit),false); g.SetPoint(i,(*it)->s(),(*it)->z()); lastit=it; ++it; } int errorcode; g.LeastSquareLinearFit(nn,_t,_m,errorcode,-999,999); //std::cout<<"szFit Error Code:"<SetReturnFromRun(kTRUE); gSystem->Run(); } return; } double PndTpcRiemannTrack::szDist(PndTpcRiemannHit* hit, bool calcPos){ if(!_isFitted)szFit(); double hits=hit->s(); //std::cout<<"raw s="<cluster()->pos(); std::list::iterator it2=_hits.end(); --it2; TVector3 posend=(*it2)->cluster()->pos(); std::list::iterator it1=_hits.begin(); TVector3 posstart=(*it1)->cluster()->pos(); double s1x=(posX-posstart).Mag(); double s2x=(posX-posend).Mag(); _nit=0; // reset iteration counter hitIt ahit; if(s1x>=s2x){// hit closer to end of list ahit=this->sortHit(hit,_hits,-1); // direction -1 --> start backwards search } else { // hit closer to start of list ahit=this->sortHit(hit,_hits,1); // direction 1 --> search from front to end } // ahit is the hit AFTER our hit ... bool first=(ahit==_hits.begin()); for(int i=0;i<2;++i){ // TODO: Why do I have to increment twice???? if(!first)--ahit; first=(ahit==_hits.begin()); } TVector3 pos1=(*ahit)->cluster()->pos(); if(first){ hits=-((posX-pos1).Mag()); } else { double s1=(*ahit)->s(); hits=s1+(posX-pos1).Mag(); } //std::cout<<"recalc s="<z(); } // only after szFit! double PndTpcRiemannTrack::dip() const { std::cout << _m << std::endl; if(_m>=1. || _m<=-1.)return 0; return TMath::PiOver2()-(asin(_m)); } // Todo: check for backward going tracks!!! double PndTpcRiemannTrack::sign() const { double s=getHit(3)->s(); return s<0 ? -1. : 1; } void PndTpcRiemannTrack::Plot(bool standalone){ TCanvas* cc=NULL; if(standalone)cc=new TCanvas("c"); TPolyMarker3D* maker=new TPolyMarker3D(_hits.size()); TPolyLine3D* line=new TPolyLine3D(_hits.size()); std::list::iterator it=_hits.begin(); int count=0; while(it!=_hits.end()){ TVector3 pos=(*it)->cluster()->pos(); //pos.Print(); maker->SetPoint(count,pos.X(),pos.Y(),pos.Z()); line->SetPoint(count,pos.X(),pos.Y(),pos.Z()); ++it; ++count; } maker->SetMarkerStyle(23); maker->Draw(); line->Draw(); if(standalone){ gApplication->SetReturnFromRun(kTRUE); gSystem->Run(); delete maker; delete line; delete cc; } }