+ //__________________________________________________________________________
+Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation)
+{
+ /// Follow trackCandidate in station(0..) nextStation and search for compatible cluster(s)
+ /// Keep all possibilities or only the best one(s) according to the flag fgkTrackAllTracks:
+ /// kTRUE: duplicate "trackCandidate" if there are several possibilities and add the new tracks at the end of
+ /// fRecTracksPtr to avoid conficts with other track candidates at this current stage of the tracking procedure.
+ /// Remove the obsolete "trackCandidate" at the end.
+ /// kFALSE: add only the best cluster(s) to the "trackCandidate". Try to add a couple of clusters in priority.
+ /// return kTRUE if new cluster(s) have been found (otherwise return kFALSE)
+ AliDebug(1,Form("Enter FollowTrackInStation(1..) %d", nextStation+1));
+
+ // Order the chamber according to the propagation direction (tracking starts with chamber 2):
+ // - nextStation == station(1...) 5 => forward propagation
+ // - nextStation < station(1...) 5 => backward propagation
+ Int_t ch1, ch2;
+ if (nextStation==4) {
+ ch1 = 2*nextStation+1;
+ ch2 = 2*nextStation;
+ } else {
+ ch1 = 2*nextStation;
+ ch2 = 2*nextStation+1;
+ }
+
+ Double_t chi2OfCluster;
+ Double_t maxChi2OfCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
+ GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+ Double_t addChi2TrackAtCluster1;
+ Double_t addChi2TrackAtCluster2;
+ Double_t bestAddChi2TrackAtCluster1 = 1.e10;
+ Double_t bestAddChi2TrackAtCluster2 = 1.e10;
+ Bool_t foundOneCluster = kFALSE;
+ Bool_t foundTwoClusters = kFALSE;
+ AliMUONTrack *newTrack = 0x0;
+ AliMUONVCluster *clusterCh1, *clusterCh2;
+ AliMUONTrackParam extrapTrackParam;
+ AliMUONTrackParam extrapTrackParamAtCh;
+ AliMUONTrackParam extrapTrackParamAtCluster1;
+ AliMUONTrackParam extrapTrackParamAtCluster2;
+ AliMUONTrackParam bestTrackParamAtCluster1;
+ AliMUONTrackParam bestTrackParamAtCluster2;
+
+ Int_t nClusters = clusterStore.GetSize();
+ Bool_t *clusterCh1Used = new Bool_t[nClusters];
+ for (Int_t i = 0; i < nClusters; i++) clusterCh1Used[i] = kFALSE;
+ Int_t iCluster1;
+
+ // Get track parameters according to the propagation direction
+
+ if (nextStation==4) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
+ else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+ cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+ extrapTrackParamAtCh.GetParameters().Print();
+ extrapTrackParamAtCh.GetCovariances().Print();
+ }
+
+ // Add MCS effect
+ AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+
+ // reset propagator for smoother
+ if (GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator();
+
+ // Add MCS in the missing chamber(s) if any
+ Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
+ while (ch1 < ch2 && currentChamber > ch2 + 1) {
+ // extrapolation to the missing chamber
+ currentChamber--;
+ AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber),
+ GetRecoParam()->UseSmoother());
+ // add MCS effect
+ AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+ }
+
+ //Extrapolate trackCandidate to chamber "ch2"
+ AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch2),
+ GetRecoParam()->UseSmoother());
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+ cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
+ extrapTrackParamAtCh.GetParameters().Print();
+ extrapTrackParamAtCh.GetCovariances().Print();
+ }
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowTrackInStation: look for clusters in chamber(1..): " << ch2+1 << endl;
+ }
+
+ // Ask the clustering to reconstruct new clusters around the track position in the current station
+ // except for station 4 and 5 that are already entirely clusterized
+ if (GetRecoParam()->CombineClusterTrackReco()) {
+ if (nextStation < 3) AskForNewClustersInStation(extrapTrackParamAtCh, clusterStore, nextStation);
+ }
+
+ // Create iterators to loop over clusters in both chambers
+ TIter nextInCh1(clusterStore.CreateChamberIterator(ch1,ch1));
+ TIter nextInCh2(clusterStore.CreateChamberIterator(ch2,ch2));
+
+ // look for candidates in chamber 2
+ while ( ( clusterCh2 = static_cast<AliMUONVCluster*>(nextInCh2()) ) ) {
+
+ // try to add the current cluster fast
+ if (!TryOneClusterFast(extrapTrackParamAtCh, clusterCh2)) continue;
+
+ // try to add the current cluster accuratly
+ chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh2, extrapTrackParamAtCluster2,
+ GetRecoParam()->UseSmoother());
+
+ // if good chi2 then try to attach a cluster in the other chamber too
+ if (chi2OfCluster < maxChi2OfCluster) {
+
+ if (GetRecoParam()->UseSmoother()) {
+ // save extrapolated parameters for smoother
+ extrapTrackParamAtCluster2.SetExtrapParameters(extrapTrackParamAtCluster2.GetParameters());
+
+ // save extrapolated covariance matrix for smoother
+ extrapTrackParamAtCluster2.SetExtrapCovariances(extrapTrackParamAtCluster2.GetCovariances());
+ }
+
+ // Compute new track parameters including "clusterCh2" using kalman filter
+ addChi2TrackAtCluster2 = RunKalmanFilter(extrapTrackParamAtCluster2);
+
+ // skip track out of limits
+ if (!IsAcceptable(extrapTrackParamAtCluster2)) continue;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch2+1
+ << " (Chi2 = " << chi2OfCluster << ")" << endl;
+ clusterCh2->Print();
+ cout << " look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
+ }
+
+ // copy new track parameters for next step
+ extrapTrackParam = extrapTrackParamAtCluster2;
+
+ // add MCS effect
+ AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
+
+ // reset propagator for smoother
+ if (GetRecoParam()->UseSmoother()) extrapTrackParam.ResetPropagator();
+
+ //Extrapolate track parameters to chamber "ch1"
+ AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(ch1),
+ GetRecoParam()->UseSmoother());
+
+ // reset cluster iterator of chamber 1
+ nextInCh1.Reset();
+ iCluster1 = -1;
+
+ // look for second candidates in chamber 1
+ Bool_t foundSecondCluster = kFALSE;
+ while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) {
+ iCluster1++;
+
+ // try to add the current cluster fast
+ if (!TryOneClusterFast(extrapTrackParam, clusterCh1)) continue;
+
+ // try to add the current cluster accuratly
+ chi2OfCluster = TryOneCluster(extrapTrackParam, clusterCh1, extrapTrackParamAtCluster1,
+ GetRecoParam()->UseSmoother());
+
+ // if good chi2 then consider to add the 2 clusters to the "trackCandidate"
+ if (chi2OfCluster < maxChi2OfCluster) {
+
+ if (GetRecoParam()->UseSmoother()) {
+ // save extrapolated parameters for smoother
+ extrapTrackParamAtCluster1.SetExtrapParameters(extrapTrackParamAtCluster1.GetParameters());
+
+ // save extrapolated covariance matrix for smoother
+ extrapTrackParamAtCluster1.SetExtrapCovariances(extrapTrackParamAtCluster1.GetCovariances());
+ }
+
+ // Compute new track parameters including "clusterCh1" using kalman filter
+ addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1);
+
+ // skip track out of limits
+ if (!IsAcceptable(extrapTrackParamAtCluster1)) continue;
+
+ // remember a second cluster was found
+ foundSecondCluster = kTRUE;
+ foundTwoClusters = kTRUE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
+ << " (Chi2 = " << chi2OfCluster << ")" << endl;
+ clusterCh1->Print();
+ }
+
+ if (GetRecoParam()->TrackAllTracks()) {
+ // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new clusters
+ newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
+ UpdateTrack(*newTrack,extrapTrackParamAtCluster1,extrapTrackParamAtCluster2,addChi2TrackAtCluster1,addChi2TrackAtCluster2);
+ fNRecTracks++;
+
+ // Tag clusterCh1 as used
+ clusterCh1Used[iCluster1] = kTRUE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowTrackInStation: added two clusters in station(1..): " << nextStation+1 << endl;
+ if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+ }
+
+ } else if (addChi2TrackAtCluster1+addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1+bestAddChi2TrackAtCluster2) {
+ // keep track of the best couple of clusters
+ bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster1;
+ bestAddChi2TrackAtCluster2 = addChi2TrackAtCluster2;
+ bestTrackParamAtCluster1 = extrapTrackParamAtCluster1;
+ bestTrackParamAtCluster2 = extrapTrackParamAtCluster2;
+ }
+
+ }
+
+ }
+
+ // if no clusterCh1 found then consider to add clusterCh2 only
+ if (!foundSecondCluster) {
+
+ // remember a cluster was found
+ foundOneCluster = kTRUE;
+
+ if (GetRecoParam()->TrackAllTracks()) {
+ // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
+ newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
+ UpdateTrack(*newTrack,extrapTrackParamAtCluster2,addChi2TrackAtCluster2);
+ fNRecTracks++;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowTrackInStation: added one cluster in chamber(1..): " << ch2+1 << endl;
+ if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+ }
+
+ } else if (!foundTwoClusters && addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1) {
+ // keep track of the best single cluster except if a couple of clusters has already been found
+ bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster2;
+ bestTrackParamAtCluster1 = extrapTrackParamAtCluster2;
+ }
+
+ }
+