- AliMUONHitForRec *hit1Ptr, *hit2Ptr;
- AliMUONObjectPair *segment;
- Double_t bendingSlope, distBend, distNonBend, extBendCoor, extNonBendCoor, extrapFact;
- Double_t impactParam = 0., bendingMomentum = 0.; // to avoid compilation warning
- // first and second chambers (0...) in the station
- Int_t ch1 = 2 * station;
- Int_t ch2 = ch1 + 1;
- // list of segments
- TClonesArray *segments = new TClonesArray("AliMUONObjectPair", fNHitsForRecPerChamber[ch2]);
- // Loop over HitForRec's in the first chamber of the station
- for (Int_t hit1 = fIndexOfFirstHitForRecPerChamber[ch1];
- hit1 < fIndexOfFirstHitForRecPerChamber[ch1] + fNHitsForRecPerChamber[ch1];
- hit1++) {
- // pointer to the HitForRec
- hit1Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit1]);
- // extrapolation, on the straight line joining the HitForRec to the vertex (0,0,0),
- // to the Z of the HitForRec in the second chamber of the station
- // Loop over HitsForRec's in the second chamber of the station
- for (Int_t hit2 = fIndexOfFirstHitForRecPerChamber[ch2];
- hit2 < fIndexOfFirstHitForRecPerChamber[ch2] + fNHitsForRecPerChamber[ch2];
- hit2++) {
- // pointer to the HitForRec
- hit2Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit2]);
- // absolute values of distances, in bending and non bending planes,
- // between the HitForRec in the second chamber
- // and the previous extrapolation
- extrapFact = hit2Ptr->GetZ()/ hit1Ptr->GetZ();
- extBendCoor = extrapFact * hit1Ptr->GetBendingCoor();
- extNonBendCoor = extrapFact * hit1Ptr->GetNonBendingCoor();
- distBend = TMath::Abs(hit2Ptr->GetBendingCoor() - extBendCoor);
- distNonBend = TMath::Abs(hit2Ptr->GetNonBendingCoor() - extNonBendCoor);
- // bending slope
- if ( hit1Ptr->GetZ() - hit2Ptr->GetZ() != 0. ) {
- bendingSlope = (hit1Ptr->GetBendingCoor() - hit2Ptr->GetBendingCoor()) / (hit1Ptr->GetZ() - hit2Ptr->GetZ());
- // impact parameter
- impactParam = hit1Ptr->GetBendingCoor() - hit1Ptr->GetZ() * bendingSlope;
- // absolute value of bending momentum
- bendingMomentum = TMath::Abs(AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(impactParam));
- } else {
- AliWarning("hit1Ptr->GetZ() = hit2Ptr->GetZ(): no segment created");
- continue;
- }
- // check for distances not too large,
- // and impact parameter not too big if stations downstream of the dipole.
- // Conditions "distBend" and "impactParam" correlated for these stations ????
- if ((distBend < fSegmentMaxDistBending[station]) && (distNonBend < fSegmentMaxDistNonBending[station]) &&
- (bendingMomentum < fMaxBendingMomentum) && (bendingMomentum > fMinBendingMomentum)) {
- // make new segment
- segment = new ((*segments)[segments->GetLast()+1]) AliMUONObjectPair(hit1Ptr, hit2Ptr, kFALSE, kFALSE);
- if (AliLog::GetGlobalDebugLevel() > 1) {
- cout << "segmentIndex(0...): " << segments->GetLast()
- << " distBend: " << distBend
- << " distNonBend: " << distNonBend
- << endl;
- segment->Dump();
- cout << "HitForRec in first chamber" << endl;
- hit1Ptr->Dump();
- cout << "HitForRec in second chamber" << endl;
- hit2Ptr->Dump();
+ // 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 chi2WithOneCluster = 1.e10;
+ Double_t chi2WithTwoClusters = 1.e10;
+ Double_t maxChi2WithOneCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+ AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+ Double_t maxChi2WithTwoClusters = 4. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+ AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 4 because 4 quantities in chi2
+ Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
+ Double_t bestChi2WithTwoClusters = maxChi2WithTwoClusters;
+ Bool_t foundOneCluster = kFALSE;
+ Bool_t foundTwoClusters = kFALSE;
+ AliMUONTrack *newTrack = 0x0;
+ AliMUONVCluster *clusterCh1, *clusterCh2;
+ AliMUONTrackParam trackParam;
+ 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) trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
+ else trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+ cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+ trackParam.GetParameters().Print();
+ trackParam.GetCovariances().Print();
+ }
+
+ // Add MCS effect
+ AliMUONTrackExtrap::AddMCSEffect(&trackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInStation: look for clusters in chamber(1..): " << ch2+1 << endl;
+ }
+
+ // 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(trackParam, clusterCh2)) continue;
+
+ // try to add the current cluster accuratly
+ extrapTrackParamAtCluster2 = trackParam;
+ AliMUONTrackExtrap::LinearExtrapToZ(&extrapTrackParamAtCluster2, clusterCh2->GetZ());
+ chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCluster2, clusterCh2, extrapTrackParamAtCluster2);
+
+ // if good chi2 then try to attach a cluster in the other chamber too
+ if (chi2WithOneCluster < maxChi2WithOneCluster) {
+ Bool_t foundSecondCluster = kFALSE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInStation: found one cluster in chamber(1..): " << ch2+1
+ << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+ clusterCh2->Print();
+ cout << " look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
+ }
+
+ // add MCS effect
+ AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCluster2,AliMUONConstants::ChamberThicknessInX0(),1.);
+
+ // reset cluster iterator of chamber 1
+ nextInCh1.Reset();
+ iCluster1 = -1;
+
+ // look for second candidates in chamber 1
+ while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) {
+ iCluster1++;
+
+ // try to add the current cluster fast
+ if (!TryOneClusterFast(extrapTrackParamAtCluster2, clusterCh1)) continue;
+
+ // try to add the current cluster in addition to the one found in the previous chamber
+ chi2WithTwoClusters = TryTwoClustersFast(extrapTrackParamAtCluster2, clusterCh1, extrapTrackParamAtCluster1);
+
+ // if good chi2 then consider to add the 2 clusters to the "trackCandidate"
+ if (chi2WithTwoClusters < maxChi2WithTwoClusters) {
+ foundSecondCluster = kTRUE;
+ foundTwoClusters = kTRUE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInStation: found one cluster in chamber(1..): " << ch1+1
+ << " (Chi2 = " << chi2WithTwoClusters << ")" << endl;
+ clusterCh1->Print();
+ }
+
+ if (AliMUONReconstructor::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);
+ extrapTrackParamAtCluster1.SetRemovable(kTRUE);
+ newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster1,*clusterCh1);
+ extrapTrackParamAtCluster2.SetRemovable(kTRUE);
+ newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster2,*clusterCh2);
+ fNRecTracks++;
+
+ // Tag clusterCh1 as used
+ clusterCh1Used[iCluster1] = kTRUE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInStation: added two clusters in station(1..): " << nextStation+1 << endl;
+ if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+ }
+
+ } else if (chi2WithTwoClusters < bestChi2WithTwoClusters) {
+ // keep track of the best couple of clusters
+ bestChi2WithTwoClusters = chi2WithTwoClusters;
+ bestTrackParamAtCluster1 = extrapTrackParamAtCluster1;
+ bestTrackParamAtCluster2 = extrapTrackParamAtCluster2;
+ }
+