38 #include <Riostream.h>
43 using std::streamsize;
44 using std::setprecision;
56 fTrackParamAtCluster(0x0),
57 fFitWithVertex(kFALSE),
60 fClusterWeightsNonBending(0x0),
61 fClusterWeightsBending(0x0),
65 fChi2MatchTrigger(0.),
67 fTrackParamAtVertex(0x0),
68 fHitsPatternInTrigCh(0),
69 fHitsPatternInTrigChTrk(0),
74 fVertexErrXY2[0] = 0.;
75 fVertexErrXY2[1] = 0.;
82 fFitWithVertex(kFALSE),
85 fClusterWeightsNonBending(0x0),
86 fClusterWeightsBending(0x0),
90 fChi2MatchTrigger(0.),
92 fTrackParamAtVertex(0x0),
93 fHitsPatternInTrigCh(0),
94 fHitsPatternInTrigChTrk(0),
110 Double_t z1 = firstCluster->
GetZ();
111 Double_t z2 = lastCluster->
GetZ();
112 Double_t
dZ = z1 - z2;
114 Double_t nonBendingCoor1 = firstCluster->
GetX();
115 Double_t nonBendingCoor2 = lastCluster->
GetX();
116 Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
118 Double_t bendingCoor1 = firstCluster->
GetY();
119 Double_t bendingCoor2 = lastCluster->
GetY();
120 Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
122 Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
127 trackParamAtFirstCluster.
SetZ(z1);
136 trackParamAtLastCluster.
SetZ(z2);
144 TMatrixD paramCov(5,5);
147 paramCov(0,0) = firstCluster->
GetErrX2();
148 paramCov(0,1) = firstCluster->
GetErrX2() /
dZ;
149 paramCov(1,0) = paramCov(0,1);
150 paramCov(1,1) = ( firstCluster->
GetErrX2() + lastCluster->
GetErrX2() ) / dZ / dZ;
152 paramCov(2,2) = firstCluster->
GetErrY2();
153 paramCov(2,3) = firstCluster->
GetErrY2() /
dZ;
154 paramCov(3,2) = paramCov(2,3);
155 paramCov(3,3) = ( firstCluster->
GetErrY2() + lastCluster->
GetErrY2() ) / dZ / dZ;
158 paramCov(4,4) = ( ( bendingVertexDispersion*bendingVertexDispersion +
159 (z1 * z1 * lastCluster->
GetErrY2() + z2 * z2 * firstCluster->
GetErrY2()) / dZ / dZ) /
160 bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum ;
161 paramCov(2,4) = - z2 * firstCluster->
GetErrY2() * inverseBendingMomentum / bendingImpact /
dZ;
162 paramCov(4,2) = paramCov(2,4);
163 paramCov(3,4) = - (z1 * lastCluster->
GetErrY2() + z2 * firstCluster->
GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
164 paramCov(4,3) = paramCov(3,4);
165 }
else paramCov(4,4) = inverseBendingMomentum*inverseBendingMomentum;
170 paramCov(0,0) = lastCluster->
GetErrX2();
171 paramCov(0,1) = - lastCluster->
GetErrX2() /
dZ;
172 paramCov(1,0) = paramCov(0,1);
174 paramCov(2,2) = lastCluster->
GetErrY2();
175 paramCov(2,3) = - lastCluster->
GetErrY2() /
dZ;
176 paramCov(3,2) = paramCov(2,3);
179 paramCov(2,4) = z1 * lastCluster->
GetErrY2() * inverseBendingMomentum / bendingImpact /
dZ;
180 paramCov(4,2) = paramCov(2,4);
193 fTrackParamAtCluster(0x0),
194 fFitWithVertex(track.fFitWithVertex),
196 fFitWithMCS(track.fFitWithMCS),
197 fClusterWeightsNonBending(0x0),
198 fClusterWeightsBending(0x0),
199 fGlobalChi2(track.fGlobalChi2),
200 fImproved(track.fImproved),
201 fMatchTrigger(track.fMatchTrigger),
202 fChi2MatchTrigger(track.fChi2MatchTrigger),
203 fTrackID(track.fTrackID),
204 fTrackParamAtVertex(0x0),
205 fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
206 fHitsPatternInTrigChTrk(track.fHitsPatternInTrigChTrk),
207 fLocalTrigger(track.fLocalTrigger),
208 fConnected(track.fConnected)
242 TObject::operator=(track);
359 AliError(Form(
"Chamber ID of the associated cluster is not valid (ChamberId=%d)",cluster.
GetChamberId()));
364 if (TMath::Abs(cluster.
GetZ() - trackParam.
GetZ())>1.e-5) {
365 AliError(
"track parameters are given at a different z position than the one of the associated cluster");
396 if (trackParamAtCluster) {
399 delete trackParamAtCluster;
404 }
else AliWarning(
"object to remove does not exist in array fTrackParamAtCluster");
406 }
else AliWarning(
"array fTrackParamAtCluster does not exist");
417 if (nClusters == 0) {
418 AliWarning(
"no cluster attached to the track");
422 Bool_t extrapStatus = kTRUE;
425 for (Int_t i = 1; i < nClusters; i++) {
430 trackParamAtCluster->
SetZ(startingTrackParam->
GetZ());
436 startingTrackParam = trackParamAtCluster;
453 if (nClusters == 0) {
454 AliWarning(
"no cluster attached to the track");
458 Bool_t extrapStatus = kTRUE;
461 Int_t currentChamber;
463 for (Int_t i = 1; i < nClusters; i++) {
468 trackParamAtCluster->
SetZ(startingTrackParam->
GetZ());
476 while (currentChamber > expectedChamber) {
488 expectedChamber = currentChamber + 1;
489 startingTrackParam = trackParamAtCluster;
508 Int_t currentCh, currentSt, previousCh = -1, nChHitInSt4 = 0, nChHitInSt5 = 0;
509 UInt_t presentStationMask(0);
512 for (Int_t i = 0; i < nClusters; i++) {
516 currentSt = currentCh/2;
519 presentStationMask |= ( 1 << currentSt );
522 if (currentSt == 3 && currentCh != previousCh) {
524 previousCh = currentCh;
528 if (currentSt == 4 && currentCh != previousCh) {
530 previousCh = currentCh;
539 if (request2ChInSameSt45)
return (nChHitInSt4 == 2 || nChHitInSt5 == 2);
541 else return (nChHitInSt4+nChHitInSt5 >= 2);
553 Int_t currentCh, nextCh, currentSt, nextSt, previousCh = -1, nChHitInSt45 = 0;
556 for (Int_t i = 0; i < nClusters; i++) {
560 currentSt = currentCh/2;
563 if ((1 << currentSt) & requestedStationMask) trackParam->
SetRemovable(kFALSE);
567 if (currentCh > 5 && currentCh != previousCh) {
569 previousCh = currentCh;
575 for (Int_t i = 0; i < nClusters; i++) {
579 currentSt = currentCh/2;
583 if (nChHitInSt45 < 3 && currentSt > 2) {
585 if (i == nClusters-1) {
595 if (nextCh == currentCh) {
611 for (Int_t j = i+1; j < nClusters; j++) {
618 if (nextSt == currentSt) {
640 AliDebug(1,
"Enter ComputeLocalChi2");
643 AliWarning(
"no cluster attached to this track");
651 TMatrixD mcsCovariances(nClusters,nClusters);
656 AliWarning(
"cannot take into account the multiple scattering effects");
662 if (globalChi2 < 0.)
return kFALSE;
668 Int_t iCluster1, iCluster2, iCurrentCluster1, iCurrentCluster2;
669 TMatrixD clusterWeightsNB(nClusters-1,nClusters-1);
670 TMatrixD clusterWeightsB(nClusters-1,nClusters-1);
671 Double_t *dX =
new Double_t[nClusters-1];
672 Double_t *
dY =
new Double_t[nClusters-1];
673 Double_t globalChi2b;
674 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
681 AliWarning(
"cannot take into account the multiple scattering effects");
689 iCurrentCluster1 = 0;
690 for (iCluster1 = 0; iCluster1 < nClusters ; iCluster1++) {
694 if (cluster == discardedCluster)
continue;
700 iCurrentCluster2 = 0;
701 for (iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
704 if (cluster == discardedCluster)
continue;
707 globalChi2b += (clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) +
708 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1)) * dX[iCurrentCluster1] * dX[iCurrentCluster2] +
709 (clusterWeightsB(iCurrentCluster1, iCurrentCluster2) +
710 clusterWeightsB(iCurrentCluster2, iCurrentCluster1)) * dY[iCurrentCluster1] * dY[iCurrentCluster2];
716 globalChi2b += clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) * dX[iCurrentCluster1] * dX[iCurrentCluster1] +
717 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) * dY[iCurrentCluster1] * dY[iCurrentCluster1];
723 trackParamAtCluster->
SetLocalChi2(globalChi2 - globalChi2b);
735 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
761 AliDebug(1,
"Enter ComputeGlobalChi2");
764 AliWarning(
"no cluster attached to this track");
774 AliWarning(
"cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
779 AliWarning(
"cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
785 Double_t *dX =
new Double_t[nClusters];
786 Double_t *
dY =
new Double_t[nClusters];
788 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
793 for (Int_t iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
794 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster2) + (*
fClusterWeightsNonBending)(iCluster2, iCluster1)) * dX[iCluster1] * dX[iCluster2] +
795 ((*fClusterWeightsBending)(iCluster1, iCluster2) + (*
fClusterWeightsBending)(iCluster2, iCluster1)) * dY[iCluster1] * dY[iCluster2];
797 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster1) * dX[iCluster1] * dX[iCluster1]) +
798 ((*fClusterWeightsBending)(iCluster1, iCluster1) * dY[iCluster1] * dY[iCluster1]);
809 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
831 AliDebug(1,
"Enter ComputeClusterWeights1");
834 AliWarning(
"no cluster attached to this track");
852 TMatrixD* mcsCovariances,
const AliMUONVCluster* discardedCluster)
const
859 AliDebug(1,
"Enter ComputeClusterWeights2");
863 Bool_t deleteMCSCov = kFALSE;
864 if (!mcsCovariances) {
865 mcsCovariances =
new TMatrixD(nClusters,nClusters);
866 deleteMCSCov = kTRUE;
871 if (discardedCluster) {
872 clusterWeightsNB.ResizeTo(nClusters-1,nClusters-1);
873 clusterWeightsB.ResizeTo(nClusters-1,nClusters-1);
875 clusterWeightsNB.ResizeTo(nClusters,nClusters);
876 clusterWeightsB.ResizeTo(nClusters,nClusters);
881 Int_t iCurrentCluster1, iCurrentCluster2;
884 iCurrentCluster1 = 0;
885 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
888 if (cluster1 == discardedCluster)
continue;
891 iCurrentCluster2 = iCurrentCluster1;
892 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
895 if (cluster2 == discardedCluster)
continue;
898 clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) = (*mcsCovariances)(iCluster1,iCluster2);
901 clusterWeightsB(iCurrentCluster1, iCurrentCluster2) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
904 if (iCurrentCluster1 == iCurrentCluster2) {
907 clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) += cluster1->
GetErrX2();
909 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) += cluster1->
GetErrY2();
914 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
916 clusterWeightsB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsB(iCurrentCluster1, iCurrentCluster2);
927 if (clusterWeightsNB.Determinant() != 0 && clusterWeightsB.Determinant() != 0) {
928 clusterWeightsNB.Invert();
929 clusterWeightsB.Invert();
931 AliWarning(
" Determinant = 0");
932 clusterWeightsNB.ResizeTo(0,0);
933 clusterWeightsB.ResizeTo(0,0);
934 if(deleteMCSCov)
delete mcsCovariances;
938 if(deleteMCSCov)
delete mcsCovariances;
949 AliDebug(1,
"Enter ComputeMCSCovariances");
953 if (mcsCovariances.GetNrows() != nClusters) mcsCovariances.ResizeTo(nClusters,nClusters);
959 Int_t currentChamber = 0, expectedChamber = 0, size = 0;
960 Double_t *mcsAngle2 =
new Double_t[2*nChambers];
961 Double_t *zMCS =
new Double_t[2*nChambers];
962 Int_t *indices =
new Int_t[2*nClusters];
966 for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
971 while (currentChamber > expectedChamber) {
980 extrapTrackParam = *trackParamAtCluster;
986 }
else mcsAngle2[size] = 0.;
993 zMCS[size] = trackParamAtCluster->
GetZ();
999 indices[iCluster] = size;
1001 expectedChamber = currentChamber + 1;
1009 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
1011 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
1014 mcsCovariances(iCluster1,iCluster2) = 0.;
1017 for (Int_t k = 0; k < indices[iCluster1]; k++) {
1018 mcsCovariances(iCluster1,iCluster2) += (zMCS[indices[iCluster1]] - zMCS[k]) * (zMCS[indices[iCluster2]] - zMCS[k]) * mcsAngle2[k];
1022 mcsCovariances(iCluster2,iCluster1) = mcsCovariances(iCluster1,iCluster2);
1027 delete [] mcsAngle2;
1041 Int_t chMin = 2 * stMin;
1042 Int_t chMax = 2 * stMax + 1;
1043 Int_t clustersInCommon = 0;
1047 for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
1051 if (chCl1 < chMin || chCl1 > chMax)
continue;
1055 for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
1059 if (chCl2 < chMin || chCl2 > chMax)
continue;
1062 if (cl1->GetUniqueID() == cl2->GetUniqueID()) {
1071 return clustersInCommon;
1080 return (ndf > 0) ? ndf : 0;
1088 Double_t ndf = (Double_t)
GetNDF();
1100 Double_t chi2Max = sigmaCut *
sigmaCut;
1103 Int_t nMatchClusters = 0;
1110 for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
1115 for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
1122 dX = cluster1->
GetX() - cluster2->
GetX();
1123 dY = cluster1->
GetY() - cluster2->
GetY();
1125 if (chi2 > 2. * chi2Max)
continue;
1134 return nMatchClusters;
1144 Bool_t compTrack[10];
1147 if ((compTrack[0] || compTrack[1] || compTrack[2] || compTrack[3]) &&
1148 (compTrack[6] || compTrack[7] || compTrack[8] || compTrack[9]) &&
1158 if (trackParam == 0x0)
return;
1169 cout <<
"Recursive dump of Track: " <<
this << endl;
1172 for (Int_t iCluster = 0; iCluster <
GetNClusters(); iCluster++) {
1175 cout <<
"trackParamAtCluster: " << trackParamAtCluster <<
" (index: " << iCluster <<
")" << endl;
1176 trackParamAtCluster->Dump();
1179 cout <<
"cluster: " << cluster << endl;
1190 streamsize curW = cout.width();
1191 streamsize curPrecision = cout.precision();
1192 cout <<
"<AliMUONTrack> No.Clusters=" << setw(2) <<
GetNClusters() <<
1194 ", LoTrgNum=" << setw(3) <<
LoCircuit() <<
1197 cout << Form(
" MClabel=%d",
fTrackID) << endl;
1200 cout.precision(curPrecision);
1208 if (loCirc < 0)
return;
1228 Int_t halfCluster = nClusters/2;
1234 for (Int_t iCluster1 = 0; iCluster1 < nClusters-halfCluster; iCluster1++) {
1241 if (label1 < 0)
continue;
1243 Int_t nIdenticalLabel = 1;
1246 for (Int_t iCluster2 = iCluster1+1; iCluster2 < nClusters; iCluster2++) {
1249 if (cluster2->
GetMCLabel() != label1)
continue;
1254 if (nIdenticalLabel > halfCluster && cluster2->
GetChamberId() > 5) {
void RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
Int_t GetNClusters() const
return the number of clusters attached to the track
Bool_t fFitWithMCS
! kTRUE if accounting for multiple scattering in the fit, kFALSE if not
Double_t fGlobalChi2
Global chi2 of the track.
Int_t GetMatchTrigger(void) const
return 1,2,3 if track matches with trigger track, 0 if not
virtual Double_t GetZ() const =0
Return coordinate Z (cm)
static Int_t NTrackingCh()
Return number of tracking chambers.
Double_t GetBendingCoor() const
return bending coordinate (cm)
Int_t ClustersInCommon(AliMUONTrack *track, Int_t stMin=0, Int_t stMax=4) const
const TMatrixD & GetParameters() const
return track parameters
UInt_t fHitsPatternInTrigChTrk
Word containing info on the hits left in trigger chambers (calculated from extrapolated tracker track...
Double_t GetZ() const
return Z coordinate (cm)
Int_t fLocalTrigger
packed local trigger information
void ComputeMCSCovariances(TMatrixD &mcsCovariances) const
Track parameters in ALICE dimuon spectrometer.
Double_t GetNormalizedChi2() const
virtual Double_t GetErrX2() const =0
Return resolution**2 (cm**2) on coordinate X.
void SetNonBendingCoor(Double_t nonBendingCoor)
set non bending coordinate (cm)
void SetLocalChi2(Double_t chi2)
set the local chi2 of the associated cluster with respect to the track
TObject * First() const
Return the first element of the pair.
Bool_t request2ChInSameSt45
Bool_t ComputeLocalChi2(Bool_t accountForMCS)
Bool_t IsValid(UInt_t requestedStationMask, Bool_t request2ChInSameSt45=kFALSE)
UShort_t fHitsPatternInTrigCh
Word containing info on the hits left in trigger chambers.
TObjArray * fTrackParamAtCluster
Track parameters at cluster.
Double_t GetChi2MatchTrigger(void) const
return the chi2 of trigger/track matching
Bool_t fFitWithVertex
! kTRUE if using the vertex to constrain the fit, kFALSE if not
virtual void Clear(Option_t *opt="")
Bool_t Match(AliMUONTrack &track, Double_t sigma2Cut, Int_t &nMatchClusters) const
Bool_t UpdateCovTrackParamAtCluster()
Int_t FindCompatibleClusters(const AliMUONTrack &track, Double_t sigma2Cut, Bool_t compatibleCluster[10]) const
virtual void Print(Option_t *option="") const
Double_t ComputeGlobalChi2(Bool_t accountForMCS)
void SetBendingSlope(Double_t bendingSlope)
set bending slope (cm ** -1)
abstract base class for clusters
void SetTrackParamAtVertex(const AliMUONTrackParam *trackParam)
Int_t LoCircuit(void) const
number of triggering circuit
void SetClusterPtr(AliMUONVCluster *cluster, Bool_t owner=kFALSE)
TObject * Second() const
Return the second element of the pair.
Bool_t UpdateTrackParamAtCluster()
void AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy=kFALSE)
Bool_t IsRemovable() const
return kTRUE if the associated cluster can be removed from the track it belongs to ...
void SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt, UChar_t respWithoutChamber=0)
set local trigger information for the matched trigger track
TMatrixD * fClusterWeightsNonBending
! (accounting for multiple scattering and cluster resolution)
Int_t fTrackID
Point to the corresponding MC track.
void SetNonBendingSlope(Double_t nonBendingSlope)
set non bending slope (cm ** -1)
virtual Double_t GetErrY2() const =0
Return resolution**2 (cm**2) on coordinate Y.
AliMUONTrackParam * fTrackParamAtVertex
! Track parameters at vertex
void SetParameters(const TMatrixD ¶meters)
set track parameters
static Int_t GetChamberId(UInt_t uniqueID)
Return chamber id (0..), part of the uniqueID.
void SetInverseBendingMomentum(Double_t inverseBendingMomentum)
set inverse bending momentum (GeV/c ** -1) times the charge (assumed forward motion) ...
TMatrixD * fClusterWeightsBending
! (accounting for multiple scattering and cluster resolution)
virtual Double_t GetY() const =0
Return coordinate Y (cm)
Bool_t fConnected
kTRUE if that track shares cluster(s) with another
UInt_t requestedStationMask
void SetBendingCoor(Double_t bendingCoor)
set bending coordinate (cm)
Double_t fChi2MatchTrigger
chi2 of trigger/track matching
static Float_t * DefaultChamberZ()
Return pointer to array of positions.
Double_t GetNonBendingCoor() const
return non bending coordinate (cm)
Bool_t fImproved
! kTRUE if the track has been improved
void SetRemovable(Bool_t removable)
set the flag telling whether the associated cluster can be removed from the track it belongs to or no...
AliMUONVCluster * GetClusterPtr() const
get pointeur to associated cluster
static Double_t ChamberThicknessInX0(Int_t chId)
Return chamber thickness in X0.
static Int_t GetDetElemId(UInt_t uniqueID)
Return detection element id, part of the uniqueID.
virtual Double_t GetX() const =0
Return coordinate X (cm)
void RecursiveDump(void) const
Double_t fVertexErrXY2[2]
! Vertex resolution square used during the tracking procedure if required
Reconstructed track in ALICE dimuon spectrometer.
void SetCovariances(const TMatrixD &covariances)
AliMUONTrack & operator=(const AliMUONTrack &track)
void SetZ(Double_t z)
set Z coordinate (cm)
const TMatrixD & GetCovariances() const
virtual void Print(Option_t *opt="") const
The equivalent of a std::pair<TObject*,TObject*> ;-)
void TagRemovableClusters(UInt_t requestedStationMask)
static Double_t MaxChi2()
return the maximum chi2 above which the track can be considered as abnormal (due to extrapolation fai...
TObjArray * GetTrackParamAtCluster() const
Bool_t ComputeClusterWeights(TMatrixD *mcsCovariances=0)
virtual Int_t GetMCLabel() const =0
Return the corresponding MC track number.
void SetGlobalChi2(Double_t chi2)
set the minimum value of the function minimized by the fit