potentially missing clusters to the reconstructed tracks.
(This can happen when muons hit 2 detection elements within the same chamber,
because they overlap).
- Modified the option ImproveTracks() to remove bad tracks.
- Added timer info to monitor the tracking algorithm.
(Philippe P.)
if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
// Compute MCS covariance matrix only once
- TMatrixD mcsCovariances(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
+ TMatrixD mcsCovariances(fNTrackHits,fNTrackHits);
ComputeMCSCovariances(mcsCovariances);
// Make sure hit weights are consistent with following calculations
}
-
return kTRUE;
}
if (accountForMCS) {
- // Check the weight matrices
- Bool_t weightsAvailable = kTRUE;
- if (!fHitWeightsNonBending || !fHitWeightsBending) weightsAvailable = kFALSE;
- else if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsNonBending->GetNcols() != fNTrackHits ||
- fHitWeightsBending->GetNrows() != fNTrackHits || fHitWeightsBending->GetNcols() != fNTrackHits) weightsAvailable = kFALSE;
-
- // if weight matrices are not available compute chi2 without MCS
- if (!weightsAvailable) {
+ // Check the weight matrices. If weight matrices are not available compute chi2 without MCS
+ if (!fHitWeightsNonBending || !fHitWeightsBending) {
+ AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
+ return ComputeGlobalChi2(kFALSE);
+ }
+ if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsBending->GetNcols() != fNTrackHits) {
AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
return ComputeGlobalChi2(kFALSE);
}
// Check MCS covariance matrix and recompute it if need
Bool_t deleteMCSCov = kFALSE;
if (!mcsCovariances) {
-
- // build MCS covariance matrix
- mcsCovariances = new TMatrixD(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
+ mcsCovariances = new TMatrixD(fNTrackHits,fNTrackHits);
deleteMCSCov = kTRUE;
ComputeMCSCovariances(*mcsCovariances);
-
- } else {
-
- // check MCS covariance matrix size
- if (mcsCovariances->GetNrows() != AliMUONConstants::NTrackingCh() || mcsCovariances->GetNcols() != AliMUONConstants::NTrackingCh()) {
- ComputeMCSCovariances(*mcsCovariances);
- }
-
}
// Resize the weights matrices; alocate memory
// Define variables
AliMUONHitForRec *hitForRec1, *hitForRec2;
- Int_t chamber1, chamber2, currentHitNumber1, currentHitNumber2;
+ Int_t currentHitNumber1, currentHitNumber2;
// Compute the covariance matrices
currentHitNumber1 = 0;
if (hitForRec1 == discardedHit) continue;
- chamber1 = hitForRec1->GetChamberNumber();
-
// Loop over next hits
currentHitNumber2 = currentHitNumber1;
for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
if (hitForRec2 == discardedHit) continue;
- chamber2 = hitForRec2->GetChamberNumber();
-
// Fill with MCS covariances
- hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(chamber1,chamber2);
+ hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(hitNumber1,hitNumber2);
// Equal contribution from multiple scattering in non bending and bending directions
hitWeightsB(currentHitNumber1, currentHitNumber2) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
{
/// Compute the multiple scattering covariance matrix
- /// - Assume that track parameters at each hit are corrects
- /// - Return kFALSE if computation failed
+ /// (assume that track parameters at each hit are corrects)
- // Make sure the size of the covariance matrix is correct
- Int_t nChambers = AliMUONConstants::NTrackingCh();
- mcsCovariances.ResizeTo(nChambers,nChambers);
-
- // check for too many track hits
- if (fNTrackHits > nChambers) {
- AliWarning("more than 1 hit per chamber!!");
- mcsCovariances.Zero();
- return;
- }
+ // Reset the size of the covariance matrix if needed
+ if (mcsCovariances.GetNrows() != fNTrackHits) mcsCovariances.ResizeTo(fNTrackHits,fNTrackHits);
// Define variables
+ Int_t nChambers = AliMUONConstants::NTrackingCh();
AliMUONTrackParam* trackParamAtHit;
AliMUONHitForRec *hitForRec;
AliMUONTrackParam extrapTrackParam;
- Int_t currentChamber, expectedChamber;
- Double_t *mcsAngle2 = new Double_t[nChambers];
- Double_t *zMCS = new Double_t[nChambers];
+ Int_t currentChamber = 0, expectedChamber = 0, size = 0;
+ Double_t *mcsAngle2 = new Double_t[2*nChambers];
+ Double_t *zMCS = new Double_t[2*nChambers];
+ Int_t *indices = new Int_t[2*fNTrackHits];
// Compute multiple scattering dispersion angle at each chamber
// and save the z position where it is calculated
- currentChamber = 0;
- expectedChamber = 0;
for (Int_t hitNumber = 0; hitNumber < fNTrackHits; hitNumber++) {
trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
hitForRec = trackParamAtHit->GetHitForRecPtr();
while (currentChamber > expectedChamber) {
// Save the z position where MCS dispersion is calculated
- zMCS[expectedChamber] = AliMUONConstants::DefaultChamberZ(expectedChamber);
+ zMCS[size] = AliMUONConstants::DefaultChamberZ(expectedChamber);
// Do not take into account MCS in chambers prior the first hit
if (hitNumber > 0) {
AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[expectedChamber]);
// Save multiple scattering dispersion angle in missing chamber
- mcsAngle2[expectedChamber] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
+ mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
- } else mcsAngle2[expectedChamber] = 0.;
+ } else mcsAngle2[size] = 0.;
expectedChamber++;
+ size++;
}
// Save z position where MCS dispersion is calculated
- zMCS[currentChamber] = trackParamAtHit->GetZ();
+ zMCS[size] = trackParamAtHit->GetZ();
// Save multiple scattering dispersion angle in current chamber
- mcsAngle2[currentChamber] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
+ mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
+
+ // Save indice in zMCS array corresponding to the current cluster
+ indices[hitNumber] = size;
- expectedChamber++;
+ expectedChamber = currentChamber + 1;
+ size++;
}
// complete array of z if last hit is on the last but one chamber
- if (currentChamber != nChambers-1) zMCS[nChambers-1] = AliMUONConstants::DefaultChamberZ(nChambers-1);
-
+ if (currentChamber != nChambers-1) zMCS[size++] = AliMUONConstants::DefaultChamberZ(nChambers-1);
// Compute the covariance matrix
- for (Int_t chamber1 = 0; chamber1 < nChambers; chamber1++) {
+ for (Int_t hitNumber1 = 0; hitNumber1 < fNTrackHits; hitNumber1++) {
- for (Int_t chamber2 = chamber1; chamber2 < nChambers; chamber2++) {
+ for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
// Initialization to 0 (diagonal plus upper triangular part)
- mcsCovariances(chamber1, chamber2) = 0.;
+ mcsCovariances(hitNumber1,hitNumber2) = 0.;
// Compute contribution from multiple scattering in upstream chambers
- for (currentChamber = 0; currentChamber < chamber1; currentChamber++) {
- mcsCovariances(chamber1, chamber2) += (zMCS[chamber1] - zMCS[currentChamber]) * (zMCS[chamber2] - zMCS[currentChamber]) * mcsAngle2[currentChamber];
+ for (Int_t k = 0; k < indices[hitNumber1]; k++) {
+ mcsCovariances(hitNumber1,hitNumber2) += (zMCS[indices[hitNumber1]] - zMCS[k]) * (zMCS[indices[hitNumber2]] - zMCS[k]) * mcsAngle2[k];
}
// Symetrize the matrix
- mcsCovariances(chamber2, chamber1) = mcsCovariances(chamber1, chamber2);
+ mcsCovariances(hitNumber2,hitNumber1) = mcsCovariances(hitNumber1,hitNumber2);
}
}
delete [] mcsAngle2;
delete [] zMCS;
+ delete [] indices;
}
fSmoothCovariances(0x0),
fHitForRecPtr(0x0),
fRemovable(kFALSE),
+ fAloneInChamber(kTRUE),
fTrackChi2(0.),
fLocalChi2(0.)
{
fSmoothCovariances(0x0),
fHitForRecPtr(theMUONTrackParam.fHitForRecPtr),
fRemovable(theMUONTrackParam.fRemovable),
+ fAloneInChamber(theMUONTrackParam.fAloneInChamber),
fTrackChi2(theMUONTrackParam.fTrackChi2),
fLocalChi2(theMUONTrackParam.fLocalChi2)
{
fRemovable = theMUONTrackParam.fRemovable;
+ fAloneInChamber = theMUONTrackParam.fAloneInChamber;
+
fTrackChi2 = theMUONTrackParam.fTrackChi2;
fLocalChi2 = theMUONTrackParam.fLocalChi2;
/// set the flag telling whether the associated hit can be removed from the track it belongs to or not
void SetRemovable(Bool_t removable) {fRemovable = removable;}
- /// return the chi2 of the track when the associated HitForRec was attached
+ /// return kTRUE if the associated hit alone in its chamber
+ Bool_t IsAloneInChamber() const {return fAloneInChamber;}
+ /// set the flag telling whether the associated hi alone in its chamber or not
+ void SetAloneInChamber(Bool_t aloneInChamber) {fAloneInChamber = aloneInChamber;}
+
+ /// return the chi2 of the track when the associated HitForRec was attached
Double_t GetTrackChi2() const {return fTrackChi2;}
/// set the chi2 of the track when the associated HitForRec was attached
void SetTrackChi2(Double_t chi2) {fTrackChi2 = chi2;}
Bool_t fRemovable; //!< kTRUE if the associated hit can be removed from the track it belongs to
+ Bool_t fAloneInChamber; //!< kTRUE if the associated hit is alone in its chamber
+
Double_t fTrackChi2; //!< Chi2 of the track when the associated HitForRec was attached
Double_t fLocalChi2; //!< Local chi2 of the associated HitForRec with respect to the track
#include "AliMUONTrack.h"
#include "AliMUONTrackParam.h"
#include "AliMUONTrackExtrap.h"
+
#include "AliLog.h"
#include <TMinuit.h>
/// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
/// Good candidates are made of at least three hitForRec's.
/// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
+
TClonesArray *segments;
AliMUONTrack *track;
Int_t iCandidate = 0;
AliDebug(1,"Enter FollowTracks");
AliMUONTrack *track, *nextTrack;
+ AliMUONTrackParam *trackParam, *nextTrackParam;
Int_t currentNRecTracks;
Bool_t hitFound;
continue;
}
+ // save parameters from fit into smoothed parameters to complete track afterward
+ if (fgkComplementTracks) {
+
+ if (station==2) { // save track parameters on stations 4 and 5
+
+ // extrapolate track parameters and covariances at each cluster
+ track->UpdateCovTrackParamAtHit();
+
+ // save them
+ trackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
+ while (trackParam) {
+ trackParam->SetSmoothParameters(trackParam->GetParameters());
+ trackParam->SetSmoothCovariances(trackParam->GetCovariances());
+ trackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->After(trackParam);
+ }
+
+ } else { // or save track parameters on last station only
+
+ // save parameters from fit
+ trackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
+ trackParam->SetSmoothParameters(trackParam->GetParameters());
+ trackParam->SetSmoothCovariances(trackParam->GetCovariances());
+
+ // save parameters extrapolated to the second chamber of the same station if it has been hit
+ nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->After(trackParam);
+ if (nextTrackParam->GetHitForRecPtr()->GetChamberNumber() < 2*(station+2)) {
+
+ // reset parameters and covariances
+ nextTrackParam->SetParameters(trackParam->GetParameters());
+ nextTrackParam->SetZ(trackParam->GetZ());
+ nextTrackParam->SetCovariances(trackParam->GetCovariances());
+
+ // extrapolate them to the z of the corresponding cluster
+ AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetHitForRecPtr()->GetZ());
+
+ // save them
+ nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
+ nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+
+ }
+
+ }
+
+ }
+
// Printout for debuging
if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
cout<<endl<<"Track parameter covariances at first hit with multiple Coulomb scattering effects:"<<endl;
fNRecTracks--;
}
+ // save parameters from fit into smoothed parameters to complete track afterward
+ if (fgkComplementTracks) {
+
+ // save parameters from fit
+ trackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
+ trackParam->SetSmoothParameters(trackParam->GetParameters());
+ trackParam->SetSmoothCovariances(trackParam->GetCovariances());
+
+ // save parameters extrapolated to the second chamber of the same station if it has been hit
+ nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->After(trackParam);
+ if (nextTrackParam->GetHitForRecPtr()->GetChamberNumber() < 2) {
+
+ // reset parameters and covariances
+ nextTrackParam->SetParameters(trackParam->GetParameters());
+ nextTrackParam->SetZ(trackParam->GetZ());
+ nextTrackParam->SetCovariances(trackParam->GetCovariances());
+
+ // extrapolate them to the z of the corresponding cluster
+ AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetHitForRecPtr()->GetZ());
+
+ // save them
+ nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
+ nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+
+ }
+
+ }
+
track = nextTrack;
}
}
// compute chi2 w/wo multiple scattering
- if (trackBeingFitted->GetFitWithMCS()) chi2 += trackBeingFitted->ComputeGlobalChi2(kTRUE);
- else chi2 += trackBeingFitted->ComputeGlobalChi2(kFALSE);
+ chi2 += trackBeingFitted->ComputeGlobalChi2(trackBeingFitted->GetFitWithMCS());
+
+}
+
+ //__________________________________________________________________________
+void AliMUONTrackReconstructor::ComplementTracks()
+{
+ /// Complete tracks by adding missing clusters (if there is an overlap between
+ /// two detection elements, the track may have two clusters in the same chamber)
+ /// Re-fit track parameters and covariances
+ AliDebug(1,"Enter ComplementTracks");
+
+ Int_t chamberId, detElemId;
+ Double_t chi2OfHitForRec, bestChi2OfHitForRec;
+ Bool_t foundOneHit, trackModified;
+ AliMUONHitForRec* hitForRec;
+ AliMUONTrackParam* trackParam, *nextTrackParam;
+ AliMUONTrackParam copyOfTrackParam;
+ AliMUONTrackParam trackParamAtHit;
+ AliMUONTrackParam bestTrackParamAtHit;
+
+ // Remove double track to complete only "good" tracks
+ RemoveDoubleTracks();
+
+ AliMUONTrack *track = (AliMUONTrack*) fRecTracksPtr->First();
+ while (track) {
+ trackModified = kFALSE;
+
+ trackParam = (AliMUONTrackParam*)track->GetTrackParamAtHit()->First();
+ while (trackParam) {
+ foundOneHit = kFALSE;
+ bestChi2OfHitForRec = 2. * fgkSigmaToCutForTracking * fgkSigmaToCutForTracking; // 2 because 2 quantities in chi2
+
+ // prepare nextTrackParam before adding new cluster because of the sorting
+ nextTrackParam = (AliMUONTrackParam*)track->GetTrackParamAtHit()->After(trackParam);
+
+ chamberId = trackParam->GetHitForRecPtr()->GetChamberNumber();
+ detElemId = trackParam->GetHitForRecPtr()->GetDetElemId();
+
+ // recover track parameters from local fit and put them into a copy of trackParam
+ copyOfTrackParam.SetZ(trackParam->GetZ());
+ copyOfTrackParam.SetParameters(trackParam->GetSmoothParameters());
+ copyOfTrackParam.SetCovariances(trackParam->GetSmoothCovariances());
+
+ // look for one second candidate in the same chamber
+ for (Int_t hit = 0; hit < fNHitsForRecPerChamber[chamberId]; hit++) {
+
+ hitForRec = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[chamberId]+hit);
+
+ // look for a cluster in another detection element
+ if (hitForRec->GetDetElemId() == detElemId) continue;
+
+ // try to add the current hit fast
+ if (!TryOneHitForRecFast(copyOfTrackParam, hitForRec)) continue;
+
+ // try to add the current hit accurately
+ chi2OfHitForRec = TryOneHitForRec(copyOfTrackParam, hitForRec, trackParamAtHit);
+
+ // if better chi2 then prepare to add this cluster to the track
+ if (chi2OfHitForRec < bestChi2OfHitForRec) {
+ bestChi2OfHitForRec = chi2OfHitForRec;
+ bestTrackParamAtHit = trackParamAtHit;
+ foundOneHit = kTRUE;
+ }
+
+ }
+
+ // add new cluster if any
+ if (foundOneHit) {
+ UpdateTrack(*track,bestTrackParamAtHit);
+ bestTrackParamAtHit.SetAloneInChamber(kFALSE);
+ trackParam->SetAloneInChamber(kFALSE);
+ trackModified = kTRUE;
+ }
+
+ trackParam = nextTrackParam;
+ }
+
+ // re-fit track parameters if needed
+ if (trackModified) Fit(*track, kTRUE, kTRUE);
+
+ track = (AliMUONTrack*) fRecTracksPtr->After(track);
+ }
}
AliDebug(1,"Enter ImproveTracks");
Double_t localChi2, worstLocalChi2;
- Int_t worstChamber;
- AliMUONTrackParam *trackParamAtHit, *worstTrackParamAtHit;
+ Int_t worstChamber, previousChamber;
+ AliMUONTrack *track, *nextTrack;
+ AliMUONTrackParam *trackParamAtHit, *worstTrackParamAtHit, *previousTrackParam, *nextTrackParam;
// Remove double track to improve only "good" tracks
RemoveDoubleTracks();
- AliMUONTrack *track = (AliMUONTrack*) fRecTracksPtr->First();
+ track = (AliMUONTrack*) fRecTracksPtr->First();
while (track) {
+ // prepare next track in case the actual track is suppressed
+ nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track);
+
while (!track->IsImproved()) {
// Update track parameters and covariances
track->ComputeLocalChi2(kTRUE);
// Look for the hit to remove
- worstTrackParamAtHit = 0;
+ worstTrackParamAtHit = NULL;
worstLocalChi2 = 0.;
trackParamAtHit = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
while (trackParamAtHit) {
break;
}
- // check whether the worst hit is removable or not
- if (!worstTrackParamAtHit->IsRemovable()) {
+ // Check whether the worst chi2 is under requirement or not
+ if (worstLocalChi2 < 2. * fgkSigmaToCutForImprovement * fgkSigmaToCutForImprovement) { // 2 because 2 quantities in chi2
track->SetImproved(kTRUE);
break;
}
- // Check whether the worst chi2 is under requirement or not
- if (worstLocalChi2 < 2. * fgkSigmaToCutForImprovement * fgkSigmaToCutForImprovement) { // 2 because 2 quantities in chi2
- track->SetImproved(kTRUE);
+ // if the worst hit is not removable then remove the entire track
+ if (!worstTrackParamAtHit->IsRemovable() && worstTrackParamAtHit->IsAloneInChamber()) {
+ fRecTracksPtr->Remove(track);
+ fNRecTracks--;
break;
}
- // Reset the second hit in the same station as the bad one as being NOT removable
+ // Reset the second hit in the same station as being not removable
+ // or reset the second hit in the same chamber as being alone
worstChamber = worstTrackParamAtHit->GetHitForRecPtr()->GetChamberNumber();
- if (worstChamber%2 == 0) ((AliMUONTrackParam*)track->GetTrackParamAtHit()->After(worstTrackParamAtHit))->SetRemovable(kFALSE);
- else ((AliMUONTrackParam*)track->GetTrackParamAtHit()->Before(worstTrackParamAtHit))->SetRemovable(kFALSE);
+ previousTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->Before(worstTrackParamAtHit);
+ nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->After(worstTrackParamAtHit);
+ if (worstTrackParamAtHit->IsAloneInChamber()) { // Worst hit removable and alone in chamber
+
+ if (worstChamber%2 == 0) { // Modify flags in next chamber
+
+ nextTrackParam->SetRemovable(kFALSE);
+ if (!nextTrackParam->IsAloneInChamber()) // Make sure both hits in second chamber are not removable anymore
+ ((AliMUONTrackParam*) track->GetTrackParamAtHit()->After(nextTrackParam))->SetRemovable(kFALSE);
+
+ } else { // Modify flags in previous chamber
+
+ previousTrackParam->SetRemovable(kFALSE);
+ if (!previousTrackParam->IsAloneInChamber()) // Make sure both hits in second chamber are not removable anymore
+ ((AliMUONTrackParam*) track->GetTrackParamAtHit()->Before(previousTrackParam))->SetRemovable(kFALSE);
+
+ }
+
+ } else { // Worst hit not alone in its chamber
+
+ if (previousTrackParam) previousChamber = previousTrackParam->GetHitForRecPtr()->GetChamberNumber();
+ else previousChamber = -1;
+
+ if (previousChamber == worstChamber) { // the second hit on the same chamber is the previous one
+
+ previousTrackParam->SetAloneInChamber(kTRUE);
+ // transfert the removability to the second hit
+ if (worstTrackParamAtHit->IsRemovable()) previousTrackParam->SetRemovable(kTRUE);
+
+ } else { // the second hit on the same chamber is the next one
+
+ nextTrackParam->SetAloneInChamber(kTRUE);
+ // transfert the removability to the second hit
+ if (worstTrackParamAtHit->IsRemovable()) nextTrackParam->SetRemovable(kTRUE);
+
+ }
+
+ }
// Remove the worst hit
track->RemoveTrackParamAtHit(worstTrackParamAtHit);
// Re-fit the track:
// Take into account the multiple scattering
// Calculate the track parameter covariance matrix
- track->SetFitWithVertex(kFALSE); // To be sure
Fit(*track, kTRUE, kTRUE);
// Printout for debuging
}
- track = (AliMUONTrack*) fRecTracksPtr->After(track);
+ track = nextTrack;
}
+ // compress the array in case of some tracks have been removed
+ fRecTracksPtr->Compress();
+
}
//__________________________________________________________________________
{
/// Fill AliMUONTrack's fHitForRecAtHit array
/// Recompute track parameters and covariances at each attached cluster from those at the first one
+
AliMUONTrack *track;
AliMUONTrackParam *trackParamAtHit;
// Functions
virtual void MakeTrackCandidates();
virtual void FollowTracks();
+ virtual void ComplementTracks();
virtual void ImproveTracks();
virtual void Finalize();
/// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
/// Good candidates are made of at least three hitForRec's.
/// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
+
TClonesArray *segments;
AliMUONTrack *track;
Int_t iCandidate = 0;
}
//__________________________________________________________________________
+void AliMUONTrackReconstructorK::ComplementTracks()
+{
+ /// Complete tracks by adding missing clusters (if there is an overlap between
+ /// two detection elements, the track may have two clusters in the same chamber)
+ /// Recompute track parameters and covariances at each clusters
+ AliDebug(1,"Enter ComplementTracks");
+
+ Int_t chamberId, detElemId;
+ Double_t chi2OfHitForRec, addChi2TrackAtHit, bestAddChi2TrackAtHit;
+ Double_t maxChi2OfHitForRec = 2. * fgkSigmaToCutForTracking * fgkSigmaToCutForTracking; // 2 because 2 quantities in chi2
+ Bool_t foundOneHit, trackModified;
+ AliMUONHitForRec *hitForRec;
+ AliMUONTrackParam *trackParam, *previousTrackParam, *nextTrackParam;
+ AliMUONTrackParam trackParamAtHit;
+ AliMUONTrackParam bestTrackParamAtHit;
+
+ // Remove double track to complete only "good" tracks
+ RemoveDoubleTracks();
+
+ AliMUONTrack *track = (AliMUONTrack*) fRecTracksPtr->First();
+ while (track) {
+ trackModified = kFALSE;
+
+ trackParam = (AliMUONTrackParam*)track->GetTrackParamAtHit()->First();
+ previousTrackParam = trackParam;
+ while (trackParam) {
+ foundOneHit = kFALSE;
+ bestAddChi2TrackAtHit = 1.e10;
+
+ // prepare nextTrackParam before adding new cluster because of the sorting
+ nextTrackParam = (AliMUONTrackParam*)track->GetTrackParamAtHit()->After(trackParam);
+
+ chamberId = trackParam->GetHitForRecPtr()->GetChamberNumber();
+ detElemId = trackParam->GetHitForRecPtr()->GetDetElemId();
+
+ // look for one second candidate in the same chamber
+ for (Int_t hit = 0; hit < fNHitsForRecPerChamber[chamberId]; hit++) {
+
+ hitForRec = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[chamberId]+hit);
+
+ // look for a cluster in another detection element
+ if (hitForRec->GetDetElemId() == detElemId) continue;
+
+ // try to add the current hit fast
+ if (!TryOneHitForRecFast(*trackParam, hitForRec)) continue;
+
+ // try to add the current hit accurately
+ // never use track parameters at last cluster because the covariance matrix is meaningless
+ if (nextTrackParam) chi2OfHitForRec = TryOneHitForRec(*trackParam, hitForRec, trackParamAtHit);
+ else chi2OfHitForRec = TryOneHitForRec(*previousTrackParam, hitForRec, trackParamAtHit);
+
+ // if good chi2 then consider to add this cluster to the track
+ if (chi2OfHitForRec < maxChi2OfHitForRec) {
+
+ // Compute local track parameters including "hitForRec" using kalman filter
+ addChi2TrackAtHit = RunKalmanFilter(trackParamAtHit);
+
+ // keep track of the best cluster
+ if (addChi2TrackAtHit < bestAddChi2TrackAtHit) {
+ bestAddChi2TrackAtHit = addChi2TrackAtHit;
+ bestTrackParamAtHit = trackParamAtHit;
+ foundOneHit = kTRUE;
+ }
+
+ }
+
+ }
+
+ // add new cluster if any
+ if (foundOneHit) {
+ UpdateTrack(*track,bestTrackParamAtHit,bestAddChi2TrackAtHit);
+ bestTrackParamAtHit.SetAloneInChamber(kFALSE);
+ trackParam->SetAloneInChamber(kFALSE);
+ trackModified = kTRUE;
+ }
+
+ previousTrackParam = trackParam;
+ trackParam = nextTrackParam;
+ }
+
+ // re-compute track parameters using kalman filter if needed
+ if (trackModified) RetraceTrack(*track,kTRUE);
+
+ track = (AliMUONTrack*) fRecTracksPtr->After(track);
+ }
+
+}
+
+//__________________________________________________________________________
void AliMUONTrackReconstructorK::ImproveTracks()
{
/// Improve tracks by removing clusters with local chi2 highter than the defined cut
AliDebug(1,"Enter ImproveTracks");
Double_t localChi2, worstLocalChi2;
- Int_t worstChamber;
- AliMUONTrackParam *trackParamAtHit, *worstTrackParamAtHit;
+ Int_t worstChamber, previousChamber;
+ AliMUONTrack *track, *nextTrack;
+ AliMUONTrackParam *trackParamAtHit, *worstTrackParamAtHit, *previousTrackParam, *nextTrackParam;
Bool_t smoothed;
// Remove double track to improve only "good" tracks
RemoveDoubleTracks();
- AliMUONTrack *track = (AliMUONTrack*) fRecTracksPtr->First();
+ track = (AliMUONTrack*) fRecTracksPtr->First();
while (track) {
+ // prepare next track in case the actual track is suppressed
+ nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track);
+
while (!track->IsImproved()) {
// Run smoother if required
worstTrackParamAtHit = trackParamAtHit;
}
- trackParamAtHit = (AliMUONTrackParam*)track->GetTrackParamAtHit()->After(trackParamAtHit);
+ trackParamAtHit = (AliMUONTrackParam*)track->GetTrackParamAtHit()->After(trackParamAtHit);
}
// Check if bad removable hit found
break;
}
- // check whether the worst hit is removable or not
- if (!worstTrackParamAtHit->IsRemovable()) {
+ // Check whether the worst chi2 is under requirement or not
+ if (worstLocalChi2 < 2. * fgkSigmaToCutForImprovement * fgkSigmaToCutForImprovement) { // 2 because 2 quantities in chi2
track->SetImproved(kTRUE);
break;
}
- // Check whether the worst chi2 is under requirement or not
- if (worstLocalChi2 < 2. * fgkSigmaToCutForImprovement * fgkSigmaToCutForImprovement) { // 2 because 2 quantities in chi2
- track->SetImproved(kTRUE);
+ // if the worst hit is not removable then remove the entire track
+ if (!worstTrackParamAtHit->IsRemovable() && worstTrackParamAtHit->IsAloneInChamber()) {
+ fRecTracksPtr->Remove(track);
+ fNRecTracks--;
break;
}
- // Reset the second hit in the same station as the bad one as being NOT removable
+ // Reset the second hit in the same station as being not removable
+ // or reset the second hit in the same chamber as being alone
worstChamber = worstTrackParamAtHit->GetHitForRecPtr()->GetChamberNumber();
- if (worstChamber%2 == 0) ((AliMUONTrackParam*)track->GetTrackParamAtHit()->After(worstTrackParamAtHit))->SetRemovable(kFALSE);
- else ((AliMUONTrackParam*)track->GetTrackParamAtHit()->Before(worstTrackParamAtHit))->SetRemovable(kFALSE);
-
- // Save pointer to the trackParamAtHit next to the one to be removed
- trackParamAtHit = (AliMUONTrackParam*)track->GetTrackParamAtHit()->After(worstTrackParamAtHit);
+ previousTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->Before(worstTrackParamAtHit);
+ nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtHit()->After(worstTrackParamAtHit);
+ if (worstTrackParamAtHit->IsAloneInChamber()) { // Worst hit removable and alone in chamber
+
+ if (worstChamber%2 == 0) { // Modify flags in next chamber
+
+ nextTrackParam->SetRemovable(kFALSE);
+ if (!nextTrackParam->IsAloneInChamber()) // Make sure both hits in second chamber are not removable anymore
+ ((AliMUONTrackParam*) track->GetTrackParamAtHit()->After(nextTrackParam))->SetRemovable(kFALSE);
+
+ } else { // Modify flags in previous chamber
+
+ previousTrackParam->SetRemovable(kFALSE);
+ if (!previousTrackParam->IsAloneInChamber()) // Make sure both hits in second chamber are not removable anymore
+ ((AliMUONTrackParam*) track->GetTrackParamAtHit()->Before(previousTrackParam))->SetRemovable(kFALSE);
+
+ }
+
+ } else { // Worst hit not alone in its chamber
+
+ if (previousTrackParam) previousChamber = previousTrackParam->GetHitForRecPtr()->GetChamberNumber();
+ else previousChamber = -1;
+
+ if (previousChamber == worstChamber) { // the second hit on the same chamber is the previous one
+
+ previousTrackParam->SetAloneInChamber(kTRUE);
+ // transfert the removability to the second hit
+ if (worstTrackParamAtHit->IsRemovable()) previousTrackParam->SetRemovable(kTRUE);
+
+ } else { // the second hit on the same chamber is the next one
+
+ nextTrackParam->SetAloneInChamber(kTRUE);
+ // transfert the removability to the second hit
+ if (worstTrackParamAtHit->IsRemovable()) nextTrackParam->SetRemovable(kTRUE);
+
+ }
+
+ }
// Remove the worst hit
track->RemoveTrackParamAtHit(worstTrackParamAtHit);
// - from the hit immediately downstream the one suppressed
// - or from the begining - if parameters have been re-computed using the standard method (kalman parameters have been lost)
// - or if the removed hit was the last one
- if (smoothed && trackParamAtHit) RetracePartialTrack(*track,trackParamAtHit);
+ if (smoothed && nextTrackParam) RetracePartialTrack(*track,nextTrackParam);
else RetraceTrack(*track,kTRUE);
// Printout for debuging
}
- track = (AliMUONTrack*) fRecTracksPtr->After(track);
+ track = nextTrack;
}
+ // compress the array in case of some tracks have been removed
+ fRecTracksPtr->Compress();
+
}
//__________________________________________________________________________
void AliMUONTrackReconstructorK::Finalize()
{
/// Fill AliMUONTrack's fHitForRecAtHit array
+
AliMUONTrack *track;
AliMUONTrackParam *trackParamAtHit;
Bool_t smoothed = kFALSE;
// Functions
virtual void MakeTrackCandidates();
virtual void FollowTracks();
+ virtual void ComplementTracks();
virtual void ImproveTracks();
virtual void Finalize();
#include "AliMpDEManager.h"
#include "AliLog.h"
+#include "AliCodeTimer.h"
#include "AliTracker.h"
#include <TClonesArray.h>
const Bool_t AliMUONVTrackReconstructor::fgkMakeTrackCandidatesFast = kFALSE;
const Bool_t AliMUONVTrackReconstructor::fgkTrackAllTracks = kTRUE;
const Bool_t AliMUONVTrackReconstructor::fgkRecoverTracks = kTRUE;
+const Bool_t AliMUONVTrackReconstructor::fgkComplementTracks = kTRUE;
const Bool_t AliMUONVTrackReconstructor::fgkImproveTracks = kTRUE;
-const Double_t AliMUONVTrackReconstructor::fgkSigmaToCutForImprovement = 4.0;
+const Double_t AliMUONVTrackReconstructor::fgkSigmaToCutForImprovement = 5.0;
//__________________________________________________________________________
{
/// To reconstruct one event
AliDebug(1,"");
+ AliCodeTimerAuto("");
ResetTracks();
ResetHitsForRec();
hitForRec->SetChamberNumber(ch);
hitForRec->SetHitNumber(iclus);
// Z coordinate of the raw cluster (cm)
- hitForRec->SetZ(clus->GetZ(0));
+ hitForRec->SetZ(clus->GetZ());
if (AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 3) {
cout << "Chamber " << ch <<" raw cluster " << iclus << " : " << endl;
clus->Print("full");
if (fRecTracksPtr->GetEntriesFast() == 0) return;
// Follow tracks in stations(1..) 3, 2 and 1
FollowTracks();
+ // Complement the reconstructed tracks
+ if (fgkComplementTracks) ComplementTracks();
// Improve the reconstructed tracks
if (fgkImproveTracks) ImproveTracks();
// Remove double tracks
const AliMUONTrackHitPattern& trackHitPattern)
{
/// Try to match track from tracking system with trigger track
+ AliCodeTimerAuto("");
+
static const Double_t kDistSigma[3]={1,1,0.02}; // sigma of distributions (trigger-track) X,Y,slopeY
Int_t matchTrigger;
{
/// To make the trigger tracks from Local Trigger
AliDebug(1, "");
+ AliCodeTimerAuto("");
AliMUONGlobalTrigger* globalTrigger = triggerStore.Global();
static const Double_t fgkMaxTrackingDistanceBending; ///< Maximum distance to the track to search for compatible hitForRec(s) in bending direction
static const Double_t fgkMaxTrackingDistanceNonBending; ///< Maximum distance to the track to search for compatible hitForRec(s) in non bending direction
static const Bool_t fgkRecoverTracks; ///< kTRUE to try to recover the tracks being lost during reconstruction
- static const Bool_t fgkImproveTracks; ///< kTRUE to try to improve the reconstructed tracks
+ static const Bool_t fgkComplementTracks; ///< kTRUE to try to complete the reconstructed tracks by adding missing clusters
+ static const Bool_t fgkImproveTracks; ///< kTRUE to try to improve the reconstructed tracks by removing bad clusters
// Parameters for track reconstruction
Double_t fMinBendingMomentum; ///< minimum value (GeV/c) of momentum in bending plane
virtual void MakeTrackCandidates() = 0;
/// Follow tracks in stations(1..) 3, 2 and 1
virtual void FollowTracks() = 0;
+ /// Complement the reconstructed tracks
+ virtual void ComplementTracks() = 0;
/// Improve the reconstructed tracks
virtual void ImproveTracks() = 0;
/// Finalize the tracking results