/* * PndSttSkewStrawPzFinder.cxx * * Created on: Mar 17, 2016 * Author: walan603 */ #include "PndSttSkewStrawPzFinder.h" //ROOT includes REMOVE WHEN DONE DEVELOPING #include "TCanvas.h" #include "TH2D.h" //For sorting skew straws according to layer struct sort_pred { bool operator()(const std::pair &left, const std::pair &right) { return left.second < right.second; } }; /* * Public member functions */ PndSttSkewStrawPzFinder::PndSttSkewStrawPzFinder(TClonesArray* sttTubeArray, TClonesArray* sttHitArray) : fVerbose(0), fTubeArray(sttTubeArray), fSTTHits(sttHitArray), LineCombiAngleThreshold(90.), fSteps(180.) { if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder initialized" << endl; } fStrawMap = new PndSttStrawMap(sttTubeArray); fHoughHisto = new TH2D("HoughSpace","HoughSpace", 180, 0, 180, 200, -100, 200); } void PndSttSkewStrawPzFinder::AddPndRiemannTracks(vector AllRiemannTracks) { fVectorPndRiemannTrack = AllRiemannTracks; if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder::AddPndRiemannTracks() added " < AllTracks) { fVectorPndTrack = AllTracks; if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder::AddPndTracks() added " < AllTrackCands) { fVectorPndTrackCand = AllTrackCands; if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder::AddPndTrackCands() added " < > AllSkewedHits) { fVectorSkewedSttHits = AllSkewedHits; if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder::AddPndSttHits() added " < 0) { cout << "PndSttSkewStrawPzFinder::ExtractPz()" << endl; } //Fill fVectorSkewedSttHits with only SkewedSttHits InitSkewed(); vector< vector > output; /* * Index i runs over all Track candidates. Following input TCloneArray's * are assumed to have the same index i: * * fVectorPndTrackCand * fVectorPndTrack * fVectorPndRiemannTrack */ for (int i = 0; i < fVectorPndTrackCand.size(); ++i) { Double_t riemannR = fVectorPndRiemannTrack.at(i).r(); TVector2 riemanncircle(fVectorPndRiemannTrack.at(i).orig()[0],fVectorPndRiemannTrack.at(i).orig()[1]); Int_t charge = fVectorPndTrack.at(i).GetParamFirst().GetQ(); //q=1 => clockwise, q=-q 0> anti-clockwise if (fVerbose > 0) cout<<"ExtractSkewedHits - Correcting hits for track: "< 0 ) cout<<"ExtractSkewedHits - No hits in track: "< 1) { TVector2 FirstHit1(output.at(0).at(0).GetX() - riemanncircle.X(),output.at(0).at(0).GetY() - riemanncircle.Y()); TVector2 FirstHit2(output.at(0).at(1).GetX() - riemanncircle.X(),output.at(0).at(1).GetY() - riemanncircle.Y()); Double_t FirstHitPhi1 = FirstHit1.Phi(); Double_t FirstHitPhi2 = FirstHit2.Phi(); if (charge < 0 && (FirstHitPhi1 < FirstHitPhi2)) { Phi0 = FirstHitPhi1; } else if (charge < 0 && (FirstHitPhi1 > FirstHitPhi2)) { Phi0 = FirstHitPhi2; } else if (charge > 0 && (FirstHitPhi1 > FirstHitPhi2)) { Phi0 = FirstHitPhi1; } else if (charge > 0 && (FirstHitPhi1 < FirstHitPhi2)) { Phi0 = FirstHitPhi2; } } else { TVector2 FirstHit(output.at(0).at(0).GetX() - riemanncircle.X(),output.at(0).at(0).GetY() - riemanncircle.Y()); Phi0 = FirstHit.Phi(); } Double_t S0 = Phi0*riemannR; //Currently unused todo:Fix the phi angle such that the z-phi points spans a continuous line and not a triangle function vector< vector > ZPhiPairVector; for (int j = 0; j < output.size(); ++j)//Loop over all stt hits { vector ZPhiPair; if (output.at(j).empty()) { cout<<"ExtractSkewedHits - Hit: "< 1 ) cout<<"ExtractSkewedHits - SkewHit Z: "< 0) cout<<"<=2 skewed straw hits, Cannot continue!"< 9) { if (fVerbose > 0) cout<<"Too many skewed straws, exploding combi"< TrueZPhi = LineCombiIsoFinder(ZPhiPairVector); */ /* * End line combi code */ //TVector2 TheilSenLinePar = TheilSen(ZPhiPairVector); //TVector2 Linreg = PzLineFitExtract2(ZPhiPairVector); //cout<<"All points lin reg slope: "< Zmax) { Zmax = ZPhiPairVector.at(k).at(j).X(); }; if (ZPhiPairVector.at(k).at(j).Y() < Phimin) { Phimin = ZPhiPairVector.at(k).at(j).Y(); }; if (ZPhiPairVector.at(k).at(j).Y() > Phimax) { Phimax = ZPhiPairVector.at(k).at(j).Y(); }; } } Double_t maxDist; if (TMath::Abs(Zmax - Zmin)>TMath::Abs(Phimax-Phimin)) { maxDist = (sqrt(2)*TMath::Abs(Zmax - Zmin)); } else { maxDist = (sqrt(2)*TMath::Abs(Phimax - Phimin)); } TH2D *HoughSpace = new TH2D("HoughSpace","HoughSpace", 180, 0, 180, 100, -maxDist, maxDist); TVector2 resultparams; vector< vector > translate_ZPhi = TranslateZPhi(ZPhiPairVector); ZPhiPairVector = translate_ZPhi; vector TrueZPhi = HoughTrueIsoFinder(ZPhiPairVector, HoughSpace, resultparams); //REMOVE WHEN DONE DEVELOPING TCanvas *HoughCanvas = new TCanvas(); HoughSpace->Draw("COLZ"); HoughCanvas->Update(); //HoughSpace->Delete(); /* TVector2 resultparams; vector TrueZPhi = HoughTrueIsoFinder(ZPhiPairVector, fHoughHisto, resultparams); fHoughHisto->Clear(); if (fHoughHisto != 0) { TCanvas * tempCanvas = new TCanvas("canvasHough","canvasHough Track: "+TString::Itoa(i,10),0, 0, 1000, 800); fHoughHisto->Draw("COLZ"); tempCanvas->Update(); } */ /* * End Hough transform code */ if (TrueZPhi.empty()) { cout<<"No true Zphi was selected"< 0) { pz = (-1.)*pz/(lineparams.Y()); } else (pz = pz/(lineparams.Y())); //Generate new set of track parameters with the z-information FairTrackParP trackParamFirst = GetTrackParam(fVectorPndTrack.at(i).GetParamFirst(), fVectorPndRiemannTrack.at(i), lineparams, pz); FairTrackParP trackParamLast = GetTrackParam(fVectorPndTrack.at(i).GetParamLast(), fVectorPndRiemannTrack.at(i), lineparams, pz); //Generate new PndTrack PndTrackCand newCand = fVectorPndTrackCand.at(i); PndTrack newTrack(trackParamFirst,trackParamLast,newCand); //Store track info fResultPndRiemannTrack.push_back(fVectorPndRiemannTrack.at(i)); fResultPndTrackCand.push_back(newCand); fResultPndTrack.push_back(newTrack); //Store additional PzFinder information PndSttSkewStrawPzFinderData resultData; resultData.setLineSlope(lineparams.Y()); resultData.setLineIntercept(lineparams.X()); resultData.setPhiPairVector(ZPhiPairVector); resultData.setTrueZPhi(TrueZPhi); fResultPzData.push_back(resultData); } } /* * Private member functions */ //todo:Implement me! bool PndSttSkewStrawPzFinder::Clockwise(vector > ZPhiPairVector, TVector2 center){ return false; } void PndSttSkewStrawPzFinder::InitSkewed() { if (fVerbose > 0) { cout << "PndSttSkewStrawPzFinder::InitSkewed()" << endl; } vector tracklist; PndSttTube myTube; PndSttHit hit; for (int i = 0; i < fVectorPndTrackCand.size(); ++i) { tracklist = fVectorPndTrackCand.at(i).GetSortedHits(); vector > hitPairs; for (int j = 0; j < tracklist.size(); ++j) { hit = *(PndSttHit*) fSTTHits->At(tracklist.at(j).GetHitId()); myTube = *(PndSttTube*) fTubeArray->At(hit.GetTubeID()); if (myTube.IsSkew()) { hitPairs.push_back(pair (hit,hit.GetTubeID())); } //Sorting the skewed hits based on their layer ID std::sort(hitPairs.begin(), hitPairs.end(), sort_pred()); } vector skewHits; for (int j = 0; j < hitPairs.size(); j++){ skewHits.push_back(hitPairs.at(j).first); } fVectorSkewedSttHits.push_back(skewHits); } } vector > PndSttSkewStrawPzFinder::MoveSkewedHitsToCircle(TVector2 circle, Double_t circlerad, vector skewhits){ vector > result; for (Int_t i = 0; i < skewhits.size(); i++){ if (fVerbose > 1 ) cout<<"MoveSkewedHitsToCircle() Hit: "< tempResult; PndSttHit myHit = skewhits.at(i); PndSttTube myTube = *(PndSttTube*) fTubeArray->At(myHit.GetTubeID()); Double_t tubeLengthHalf = myTube.GetHalfLength(); TVector3 wireDirection = myTube.GetWireDirection(); TVector3 tubePosition = myTube.GetPosition(); TVector3 startPoint = tubePosition - (tubeLengthHalf * wireDirection); TVector3 endPoint = tubePosition + (tubeLengthHalf * wireDirection); TVector2 intersection1, intersection2; Int_t nofint = ComputeSegmentCircleIntersection(TVector2(endPoint.X(), endPoint.Y()), TVector2(startPoint.X(), startPoint.Y()), circle.X(), circle.Y(), circlerad, intersection1, intersection2); if (nofint == 0) continue; PndSttHit fixhit = myHit; if (fVerbose > 1 ) cout<<"MoveSkewedHitsToCircle() Intersection1 X: "< 1 ) cout<<"MoveSkewedHitsToCircle() Intersection2 X: "< PndSttSkewStrawPzFinder::LineCombiIsoFinder(vector > ZPhiPairVector){ vector,double> > > matrix2; vector,double> > tmp2; vector tmpIndices; TVector2 first, second; TVector2 v1, v2; double CosAngle, Angle; vector nPairArray; for (int i = 1; i < ZPhiPairVector.size()-1; i++){//Loop over straws if (fVerbose > 1 ) cout<<"LineCombiIsoFinder - New segment centered around straw: "< 180 - LineCombiAngleThreshold){//exclude paths tmpIndices.push_back(j); tmpIndices.push_back(k); tmpIndices.push_back(l); tmp2.push_back(pair,double> (tmpIndices,Angle)); tmpIndices.clear(); if (fVerbose > 4 ) cout<<"LineCombiIsoFinder - Indices j: " < current; current.assign(matrix2.size(),0); pair,double> bestIndices; bestIndices.first.assign(matrix2.size(),0); bestIndices.second=0.; NestedFor(nPairArray,current,bestIndices,0.,matrix2,0); if (bestIndices.second == 0. && ZPhiPairVector.size() < 10) { Double_t temp=LineCombiAngleThreshold; LineCombiAngleThreshold = 180.; NestedFor(nPairArray,current,bestIndices,0.,matrix2,0); LineCombiAngleThreshold=temp; } if (fVerbose > 1 ) cout<<"Final answer: "< 1 ) { for (int i = 0; i < bestIndices.first.size();i++){ cout< 0 ) cout<<"sum: "< result; if (bestIndices.second > 0.) { for (int i = 0; i 2 ) cout<<"LineCombiIsoFinder - R*phi: "< ×, vector ¤t, pair,double> &best, double sum, vector,double> > > matrix, int depth) { double tmp; bool possible = true; if (depth == times.size()) { if (sum > best.second) { for (int i = 0; i 1 ) cout<<"NestedFor - Weight: "<0) { //Check if lines are connected if (matrix.at(depth).at(i).first.at(1) != matrix.at(depth-1).at(current.at(depth-1)).first.at(2)) continue; if (matrix.at(depth).at(i).first.at(0) != matrix.at(depth-1).at(current.at(depth-1)).first.at(1)) continue; //Check if angle is too small if (matrix.at(depth).at(i).second < 180. - LineCombiAngleThreshold) continue; } tmp = sum; current[depth]=i; sum+= matrix.at(depth).at(i).second; NestedFor(times, current, best, sum, matrix, depth + 1); sum = tmp; } } /* * Functions for linear Hough transform */ vector PndSttSkewStrawPzFinder::HoughTrueIsoFinder(vector > ZPhiPairVector, TH2D *HoughSpace, TVector2 &lineparams){ //Generate lines for each Z-phi point, fill Houghspace with generated line parameters for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ pair AngleRange(0.,180.); Double_t theta = AngleRange.first; Double_t StepSize = ( AngleRange.second-AngleRange.first)/fSteps; Double_t Z = ZPhiPairVector.at(i).at(j).X(); Double_t Phi = ZPhiPairVector.at(i).at(j).Y(); for (int k = 0; k < fSteps; k++) { Double_t dist = Z*TMath::Cos(theta*TMath::DegToRad()) + Phi*TMath::Sin(theta*TMath::DegToRad()); HoughSpace->Fill(theta,dist); theta += StepSize; } } } //Find maximum in Hough space Int_t MaxDist, MaxTheta, MaxBin, BinID; HoughSpace->GetMaximumBin(MaxDist,MaxTheta,MaxBin); Double_t MaxdDist = HoughSpace->GetXaxis()->GetBinCenter(MaxDist); Double_t MaxdTheta = HoughSpace->GetYaxis()->GetBinCenter(MaxTheta); Double_t MaxdBin = HoughSpace->GetBinContent(MaxDist,MaxTheta); BinID = HoughSpace->GetBin(MaxDist,MaxTheta,MaxBin); cout<<"bin max: "<GetMaximumBin(MaxTheta,MaxDist,MaxBin)<<" "< 0 ) cout<<"HoughTrueIsoFinder - HoughSpaceMaxima x: "< 0 ) cout<<"HoughTrueIsoFinder - Z-Phi line Slope: "< result; for (int i = 0; i < ZPhiPairVector.size(); i++){ Double_t poca = 999999.; Int_t index = 0; for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ Double_t temppoca = TMath::Abs(slope*ZPhiPairVector.at(i).at(j).X() - 1*ZPhiPairVector.at(i).at(j).Y() + m)/TMath::Sqrt(pow(slope,2) + pow(-1.,2)); if (temppoca < poca) { poca = temppoca; index = j; } } result.push_back(ZPhiPairVector.at(i).at(index)); } return result; } /* * Second function for linear Hough transform * only generates alla lines between all pairs of z-phi points */ vector PndSttSkewStrawPzFinder::HoughTrueIsoFinder2(vector > ZPhiPairVector, TH2D *HoughSpace, TVector2 &lineparams){ //Generate only lines between all z-phi candidates, fill Hough space for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ double z1 = ZPhiPairVector.at(i).at(j).X(); double phi1 = ZPhiPairVector.at(i).at(j).Y(); for (int k = i+1; k < ZPhiPairVector.size(); k++){ for (int l = 0; l < ZPhiPairVector.at(k).size(); l++){ double z2 = ZPhiPairVector.at(k).at(l).X(); double phi2 = ZPhiPairVector.at(k).at(l).Y(); double theta = TMath::ATan(-(phi2-phi1)/(z2-z1)); double dist = z1*TMath::Cos(theta) + phi1*TMath::Sin(theta); if (fVerbose > 0 ) cout<<"HoughTrueIsoFinder2 - theta: "<Fill(theta*TMath::RadToDeg(),dist); } } } } //Find maximum in Hough space Int_t MaxDist, MaxTheta, MaxBin, BinID; HoughSpace->GetMaximumBin(MaxTheta,MaxDist,MaxBin); Double_t MaxdTheta = HoughSpace->GetXaxis()->GetBinCenter(MaxTheta); Double_t MaxdDist = HoughSpace->GetYaxis()->GetBinCenter(MaxDist); Double_t MaxdBin = HoughSpace->GetBinContent(MaxTheta,MaxDist); if (fVerbose > 0 ) cout<<"HoughTrueIsoFinder2 - HoughSpaceMaxima x: "< 0 ) cout<<"HoughTrueIsoFinder2 - Z-Phi line Slope: "< result; for (int i = 0; i < ZPhiPairVector.size(); i++){ Double_t poca = 999999.; Int_t index = 0; for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ Double_t temppoca = TMath::Abs(slope*ZPhiPairVector.at(i).at(j).X() - 1*ZPhiPairVector.at(i).at(j).Y() + m)/TMath::Sqrt(pow(slope,2) + pow(-1.,2)); if (temppoca < poca) { poca = temppoca; index = j; } } result.push_back(ZPhiPairVector.at(i).at(index)); } return result; } vector > PndSttSkewStrawPzFinder::TranslateZPhi(vector > ZPhiPairVector){ Double_t Zmin = 99999., Zmax = -1., Phimin = 99999., Phimax = -1.; for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ if (ZPhiPairVector.at(i).at(j).X() < Zmin) { Zmin = ZPhiPairVector.at(i).at(j).X(); }; if (ZPhiPairVector.at(i).at(j).X() > Zmax) { Zmax = ZPhiPairVector.at(i).at(j).X(); }; if (ZPhiPairVector.at(i).at(j).Y() < Phimin) { Phimin = ZPhiPairVector.at(i).at(j).Y(); }; if (ZPhiPairVector.at(i).at(j).Y() > Phimax) { Phimax = ZPhiPairVector.at(i).at(j).Y(); }; } } cout<<"zmin zmax phimin phimax: "< > result = ZPhiPairVector; for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ result.at(i).at(j).Set(ZPhiPairVector.at(i).at(j).X()-Zmin,ZPhiPairVector.at(i).at(j).Y()-Phimin); } } return result; } /* * FUnctions for linear regression */ TVector2 PndSttSkewStrawPzFinder::TheilSen(vector > ZPhiPairVector){ TVector2 result; vector SlopeVector; for (int i = 0; i < ZPhiPairVector.size()-1; i++){//Loop over all straws minus last one for (int j = i+1; j < ZPhiPairVector.size(); j++){//Loop over straws from i+1 to and including last one for (int k = 0; k < ZPhiPairVector.at(i).size(); k++){//Loop over all Z-phi in straw i for (int l = 0; l < ZPhiPairVector.at(j).size(); l++){//Loop over all Z-phi in straw j Double_t slope = (ZPhiPairVector.at(j).at(l).Y() - ZPhiPairVector.at(i).at(k).Y())/(ZPhiPairVector.at(j).at(l).X() - ZPhiPairVector.at(i).at(k).X()); SlopeVector.push_back(slope); } } } } sort(SlopeVector.begin(),SlopeVector.end()); cout<<"Slopes ordered: "< ZPhi){ //Simple linear regression, Z on X-axis Phi on Y-axis //Errors not taken into account Double_t meanZ = 0.; Double_t meanPhi = 0.; for (int i = 0; i < ZPhi.size(); i++){ if (fVerbose > 0 ) cout<<"PzLineFitExtract - True hit Z: "< 0 ) cout<<"PzLineFitExtract - Slope: "< > ZPhiPairVector){ //Simple linear regression, Z on X-axis Phi on Y-axis //Errors not taken into account Double_t meanZ = 0.; Double_t meanPhi = 0.; Int_t N = 0; for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ meanZ += ZPhiPairVector.at(i).at(j).X(); meanPhi += ZPhiPairVector.at(i).at(j).Y(); N++; } } meanZ /= N; meanPhi /= N; Double_t betanume = 0.; Double_t betadeno = 0.; for (int i = 0; i < ZPhiPairVector.size(); i++){ for (int j = 0; j < ZPhiPairVector.at(i).size(); j++){ betanume += (ZPhiPairVector.at(i).at(j).X() - meanZ)*(ZPhiPairVector.at(i).at(j).Y() - meanPhi); betadeno += pow(ZPhiPairVector.at(i).at(j).X() - meanZ,2); } } Double_t beta = betanume/betadeno; Double_t alpha = meanPhi - beta*meanZ; if (fVerbose > 0 ) cout<<"PzLineFitExtract - Slope: "< 0) cout<<"Hit Phi*R: "< 0) cout<<"New position: "< 0) cout<<"New momentum vector: "<