- 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();
+ // check if the current chamber is useable
+ if (!fClusterServer || !GetRecoParam()->UseChamber(chamber)) return;
+
+ // maximum distance between the center of the chamber and a detection element
+ // (accounting for the inclination of the chamber)
+ static const Double_t kMaxDZ = 15.; // 15 cm
+
+ // extrapolate track parameters to the chamber
+ AliMUONTrackParam extrapTrackParam(trackParam);
+ AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(chamber));
+
+ // build the searching area using the track resolution and the maximum-distance-to-track value
+ const TMatrixD& kParamCov = extrapTrackParam.GetCovariances();
+ Double_t errX2 = kParamCov(0,0) + kMaxDZ * kMaxDZ * kParamCov(1,1) + 2. * kMaxDZ * TMath::Abs(kParamCov(0,1));
+ Double_t errY2 = kParamCov(2,2) + kMaxDZ * kMaxDZ * kParamCov(3,3) + 2. * kMaxDZ * TMath::Abs(kParamCov(2,3));
+ Double_t dX = TMath::Abs(trackParam.GetNonBendingSlope()) * kMaxDZ +
+ GetRecoParam()->GetMaxNonBendingDistanceToTrack() +
+ GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errX2);
+ Double_t dY = TMath::Abs(trackParam.GetBendingSlope()) * kMaxDZ +
+ GetRecoParam()->GetMaxBendingDistanceToTrack() +
+ GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errY2);
+ TVector2 dimensions(dX, dY);
+ TVector2 position(extrapTrackParam.GetNonBendingCoor(), extrapTrackParam.GetBendingCoor());
+ AliMpArea area(position, dimensions);
+
+ // ask to cluterize in the given area of the given chamber
+ fClusterServer->Clusterize(chamber, clusterStore, area, GetRecoParam());
+
+}
+
+ //__________________________________________________________________________
+void AliMUONVTrackReconstructor::AskForNewClustersInStation(const AliMUONTrackParam &trackParam,
+ AliMUONVClusterStore& clusterStore, Int_t station)
+{
+ /// Ask the clustering to reconstruct new clusters around the track candidate position
+ /// in the 2 chambers of the given station
+ AskForNewClustersInChamber(trackParam, clusterStore, 2*station+1);
+ AskForNewClustersInChamber(trackParam, clusterStore, 2*station);
+}
+
+ //__________________________________________________________________________
+Double_t AliMUONVTrackReconstructor::TryOneCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster* cluster,
+ AliMUONTrackParam &trackParamAtCluster, Bool_t updatePropagator)
+{
+/// Test the compatibility between the track and the cluster (using trackParam's covariance matrix):
+/// return the corresponding Chi2
+/// return trackParamAtCluster
+
+ // extrapolate track parameters and covariances at the z position of the tested cluster
+ trackParamAtCluster = trackParam;
+ AliMUONTrackExtrap::ExtrapToZCov(&trackParamAtCluster, cluster->GetZ(), updatePropagator);
+
+ // set pointer to cluster into trackParamAtCluster
+ trackParamAtCluster.SetClusterPtr(cluster);
+
+ // Set differences between trackParam and cluster in the bending and non bending directions
+ Double_t dX = cluster->GetX() - trackParamAtCluster.GetNonBendingCoor();
+ Double_t dY = cluster->GetY() - trackParamAtCluster.GetBendingCoor();
+
+ // Calculate errors and covariances
+ const TMatrixD& kParamCov = trackParamAtCluster.GetCovariances();
+ Double_t sigmaX2 = kParamCov(0,0) + cluster->GetErrX2();
+ Double_t sigmaY2 = kParamCov(2,2) + cluster->GetErrY2();
+
+ // Compute chi2
+ return dX * dX / sigmaX2 + dY * dY / sigmaY2;
+
+}
+
+ //__________________________________________________________________________
+Bool_t AliMUONVTrackReconstructor::TryOneClusterFast(const AliMUONTrackParam &trackParam, const AliMUONVCluster* cluster)
+{
+/// Test the compatibility between the track and the cluster
+/// given the track resolution + the maximum-distance-to-track value
+/// and assuming linear propagation of the track:
+/// return kTRUE if they are compatibles
+
+ Double_t dZ = cluster->GetZ() - trackParam.GetZ();
+ Double_t dX = cluster->GetX() - (trackParam.GetNonBendingCoor() + trackParam.GetNonBendingSlope() * dZ);
+ Double_t dY = cluster->GetY() - (trackParam.GetBendingCoor() + trackParam.GetBendingSlope() * dZ);
+ const TMatrixD& kParamCov = trackParam.GetCovariances();
+ Double_t errX2 = kParamCov(0,0) + dZ * dZ * kParamCov(1,1) + 2. * dZ * kParamCov(0,1);
+ Double_t errY2 = kParamCov(2,2) + dZ * dZ * kParamCov(3,3) + 2. * dZ * kParamCov(2,3);
+
+ Double_t dXmax = GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errX2) +
+ GetRecoParam()->GetMaxNonBendingDistanceToTrack();
+ Double_t dYmax = GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errY2) +
+ GetRecoParam()->GetMaxBendingDistanceToTrack();
+
+ if (TMath::Abs(dX) > dXmax || TMath::Abs(dY) > dYmax) return kFALSE;
+
+ return kTRUE;
+
+}
+
+ //__________________________________________________________________________
+Double_t AliMUONVTrackReconstructor::TryTwoClustersFast(const AliMUONTrackParam &trackParamAtCluster1, AliMUONVCluster* cluster2,
+ AliMUONTrackParam &trackParamAtCluster2)
+{
+/// Test the compatibility between the track and the 2 clusters together (using trackParam's covariance matrix)
+/// assuming linear propagation between the two clusters:
+/// return the corresponding Chi2 accounting for covariances between the 2 clusters
+/// return trackParamAtCluster2
+
+ // extrapolate linearly track parameters and covariances at the z position of the second cluster
+ trackParamAtCluster2 = trackParamAtCluster1;
+ AliMUONTrackExtrap::LinearExtrapToZ(&trackParamAtCluster2, cluster2->GetZ());
+
+ // set pointer to cluster2 into trackParamAtCluster2
+ trackParamAtCluster2.SetClusterPtr(cluster2);
+
+ // Set differences between track and clusters in the bending and non bending directions
+ AliMUONVCluster* cluster1 = trackParamAtCluster1.GetClusterPtr();
+ Double_t dX1 = cluster1->GetX() - trackParamAtCluster1.GetNonBendingCoor();
+ Double_t dX2 = cluster2->GetX() - trackParamAtCluster2.GetNonBendingCoor();
+ Double_t dY1 = cluster1->GetY() - trackParamAtCluster1.GetBendingCoor();
+ Double_t dY2 = cluster2->GetY() - trackParamAtCluster2.GetBendingCoor();
+
+ // Calculate errors and covariances
+ const TMatrixD& kParamCov1 = trackParamAtCluster1.GetCovariances();
+ const TMatrixD& kParamCov2 = trackParamAtCluster2.GetCovariances();
+ Double_t dZ = trackParamAtCluster2.GetZ() - trackParamAtCluster1.GetZ();
+ Double_t sigma2X1 = kParamCov1(0,0) + cluster1->GetErrX2();
+ Double_t sigma2X2 = kParamCov2(0,0) + cluster2->GetErrX2();
+ Double_t covX1X2 = kParamCov1(0,0) + dZ * kParamCov1(0,1);
+ Double_t sigma2Y1 = kParamCov1(2,2) + cluster1->GetErrY2();
+ Double_t sigma2Y2 = kParamCov2(2,2) + cluster2->GetErrY2();
+ Double_t covY1Y2 = kParamCov1(2,2) + dZ * kParamCov1(2,3);
+
+ // Compute chi2
+ Double_t detX = sigma2X1 * sigma2X2 - covX1X2 * covX1X2;
+ Double_t detY = sigma2Y1 * sigma2Y2 - covY1Y2 * covY1Y2;
+ if (detX == 0. || detY == 0.) return 1.e10;
+ return (dX1 * dX1 * sigma2X2 + dX2 * dX2 * sigma2X1 - 2. * dX1 * dX2 * covX1X2) / detX
+ + (dY1 * dY1 * sigma2Y2 + dY2 * dY2 * sigma2Y1 - 2. * dY1 * dY2 * covY1Y2) / detY;
+
+}
+
+ //__________________________________________________________________________
+Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInChamber(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore,
+ Int_t nextChamber)
+{
+ /// Follow trackCandidate in chamber(0..) nextChamber assuming linear propagation, 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 FollowLinearTrackInChamber(1..) %d", nextChamber+1));
+
+ Double_t chi2WithOneCluster = 1.e10;
+ Double_t maxChi2WithOneCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
+ GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+ Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
+ Bool_t foundOneCluster = kFALSE;
+ AliMUONTrack *newTrack = 0x0;
+ AliMUONVCluster *cluster;
+ AliMUONTrackParam trackParam;
+ AliMUONTrackParam extrapTrackParamAtCluster;
+ AliMUONTrackParam bestTrackParamAtCluster;
+
+ // Get track parameters according to the propagation direction
+ if (nextChamber > 7) 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 << "FollowLinearTrackInChamber: look for cluster in chamber(1..): " << nextChamber+1 << endl;
+ }
+
+ // Create iterators to loop over clusters in chamber
+ TIter next(clusterStore.CreateChamberIterator(nextChamber,nextChamber));
+
+ // look for candidates in chamber
+ while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) ) {
+
+ // try to add the current cluster fast
+ if (!TryOneClusterFast(trackParam, cluster)) continue;
+
+ // try to add the current cluster accuratly
+ extrapTrackParamAtCluster = trackParam;
+ AliMUONTrackExtrap::LinearExtrapToZ(&extrapTrackParamAtCluster, cluster->GetZ());
+ chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCluster, cluster, extrapTrackParamAtCluster);
+
+ // if good chi2 then consider to add cluster
+ if (chi2WithOneCluster < maxChi2WithOneCluster) {
+ foundOneCluster = kTRUE;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInChamber: found one cluster in chamber(1..): " << nextChamber+1
+ << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+ cluster->Print();
+ }
+
+ 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);
+ if (GetRecoParam()->RequestStation(nextChamber/2))
+ extrapTrackParamAtCluster.SetRemovable(kFALSE);
+ else extrapTrackParamAtCluster.SetRemovable(kTRUE);
+ newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster,*cluster);
+ fNRecTracks++;
+
+ // Printout for debuging
+ if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+ cout << "FollowLinearTrackInChamber: added one cluster in chamber(1..): " << nextChamber+1 << endl;
+ if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();