#include "AliMUONTrack.h"
#include "AliMUONReconstructor.h"
#include "AliMUONVCluster.h"
#include "AliMUONVClusterStore.h"
#include "AliMUONObjectPair.h"
#include "AliMUONTrackExtrap.h"
#include "AliMUONConstants.h"
#include "AliMUONTrackParam.h"
#include "AliLog.h"
#include <TMath.h>
#include <Riostream.h>
using std::setw;
using std::endl;
using std::cout;
using std::streamsize;
using std::setprecision;
ClassImp(AliMUONTrack)
const Double_t AliMUONTrack::fgkMaxChi2 = 1.e10;
AliMUONTrack::AliMUONTrack()
: TObject(),
fTrackParamAtCluster(0x0),
fFitWithVertex(kFALSE),
fVertexErrXY2(),
fFitWithMCS(kFALSE),
fClusterWeightsNonBending(0x0),
fClusterWeightsBending(0x0),
fGlobalChi2(-1.),
fImproved(kFALSE),
fMatchTrigger(-1),
fChi2MatchTrigger(0.),
fTrackID(-1),
fTrackParamAtVertex(0x0),
fHitsPatternInTrigCh(0),
fHitsPatternInTrigChTrk(0),
fLocalTrigger(0),
fConnected(kFALSE)
{
fVertexErrXY2[0] = 0.;
fVertexErrXY2[1] = 0.;
}
AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment, Double_t bendingVertexDispersion)
: TObject(),
fTrackParamAtCluster(new TObjArray(20)),
fFitWithVertex(kFALSE),
fVertexErrXY2(),
fFitWithMCS(kFALSE),
fClusterWeightsNonBending(0x0),
fClusterWeightsBending(0x0),
fGlobalChi2(0.),
fImproved(kFALSE),
fMatchTrigger(-1),
fChi2MatchTrigger(0.),
fTrackID(-1),
fTrackParamAtVertex(0x0),
fHitsPatternInTrigCh(0),
fHitsPatternInTrigChTrk(0),
fLocalTrigger(0),
fConnected(kFALSE)
{
fTrackParamAtCluster->SetOwner(kTRUE);
fVertexErrXY2[0] = 0.;
fVertexErrXY2[1] = 0.;
AliMUONVCluster* firstCluster = (AliMUONVCluster*) segment->First();
AliMUONVCluster* lastCluster = (AliMUONVCluster*) segment->Second();
Double_t z1 = firstCluster->GetZ();
Double_t z2 = lastCluster->GetZ();
Double_t dZ = z1 - z2;
Double_t nonBendingCoor1 = firstCluster->GetX();
Double_t nonBendingCoor2 = lastCluster->GetX();
Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
Double_t bendingCoor1 = firstCluster->GetY();
Double_t bendingCoor2 = lastCluster->GetY();
Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
AliMUONTrackParam trackParamAtFirstCluster;
trackParamAtFirstCluster.SetZ(z1);
trackParamAtFirstCluster.SetNonBendingCoor(nonBendingCoor1);
trackParamAtFirstCluster.SetNonBendingSlope(nonBendingSlope);
trackParamAtFirstCluster.SetBendingCoor(bendingCoor1);
trackParamAtFirstCluster.SetBendingSlope(bendingSlope);
trackParamAtFirstCluster.SetInverseBendingMomentum(inverseBendingMomentum);
AliMUONTrackParam trackParamAtLastCluster;
trackParamAtLastCluster.SetZ(z2);
trackParamAtLastCluster.SetNonBendingCoor(nonBendingCoor2);
trackParamAtLastCluster.SetNonBendingSlope(nonBendingSlope);
trackParamAtLastCluster.SetBendingCoor(bendingCoor2);
trackParamAtLastCluster.SetBendingSlope(bendingSlope);
trackParamAtLastCluster.SetInverseBendingMomentum(inverseBendingMomentum);
TMatrixD paramCov(5,5);
paramCov.Zero();
paramCov(0,0) = firstCluster->GetErrX2();
paramCov(0,1) = firstCluster->GetErrX2() / dZ;
paramCov(1,0) = paramCov(0,1);
paramCov(1,1) = ( firstCluster->GetErrX2() + lastCluster->GetErrX2() ) / dZ / dZ;
paramCov(2,2) = firstCluster->GetErrY2();
paramCov(2,3) = firstCluster->GetErrY2() / dZ;
paramCov(3,2) = paramCov(2,3);
paramCov(3,3) = ( firstCluster->GetErrY2() + lastCluster->GetErrY2() ) / dZ / dZ;
if (AliMUONTrackExtrap::IsFieldON()) {
paramCov(4,4) = ( ( bendingVertexDispersion*bendingVertexDispersion +
(z1 * z1 * lastCluster->GetErrY2() + z2 * z2 * firstCluster->GetErrY2()) / dZ / dZ) /
bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum ;
paramCov(2,4) = - z2 * firstCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
paramCov(4,2) = paramCov(2,4);
paramCov(3,4) = - (z1 * lastCluster->GetErrY2() + z2 * firstCluster->GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
paramCov(4,3) = paramCov(3,4);
} else paramCov(4,4) = inverseBendingMomentum*inverseBendingMomentum;
trackParamAtFirstCluster.SetCovariances(paramCov);
paramCov(0,0) = lastCluster->GetErrX2();
paramCov(0,1) = - lastCluster->GetErrX2() / dZ;
paramCov(1,0) = paramCov(0,1);
paramCov(2,2) = lastCluster->GetErrY2();
paramCov(2,3) = - lastCluster->GetErrY2() / dZ;
paramCov(3,2) = paramCov(2,3);
if (AliMUONTrackExtrap::IsFieldON()) {
paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
paramCov(4,2) = paramCov(2,4);
}
trackParamAtLastCluster.SetCovariances(paramCov);
AddTrackParamAtCluster(trackParamAtFirstCluster,*firstCluster);
AddTrackParamAtCluster(trackParamAtLastCluster,*lastCluster);
}
AliMUONTrack::AliMUONTrack(const AliMUONTrack& track)
: TObject(track),
fTrackParamAtCluster(0x0),
fFitWithVertex(track.fFitWithVertex),
fVertexErrXY2(),
fFitWithMCS(track.fFitWithMCS),
fClusterWeightsNonBending(0x0),
fClusterWeightsBending(0x0),
fGlobalChi2(track.fGlobalChi2),
fImproved(track.fImproved),
fMatchTrigger(track.fMatchTrigger),
fChi2MatchTrigger(track.fChi2MatchTrigger),
fTrackID(track.fTrackID),
fTrackParamAtVertex(0x0),
fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
fHitsPatternInTrigChTrk(track.fHitsPatternInTrigChTrk),
fLocalTrigger(track.fLocalTrigger),
fConnected(track.fConnected)
{
if (track.fTrackParamAtCluster) {
fTrackParamAtCluster = new TObjArray(track.fTrackParamAtCluster->GetSize());
fTrackParamAtCluster->SetOwner(kTRUE);
for (Int_t i = 0; i < track.GetNClusters(); i++)
fTrackParamAtCluster->AddLast(new AliMUONTrackParam(*static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(i))));
}
fVertexErrXY2[0] = track.fVertexErrXY2[0];
fVertexErrXY2[1] = track.fVertexErrXY2[1];
if (track.fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
if (track.fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
if (track.fTrackParamAtVertex) fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
}
AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
{
if (this == &track)
return *this;
TObject::operator=(track);
Clear();
if (track.fTrackParamAtCluster) {
fTrackParamAtCluster = new TObjArray(track.fTrackParamAtCluster->GetSize());
fTrackParamAtCluster->SetOwner(kTRUE);
for (Int_t i = 0; i < track.GetNClusters(); i++)
fTrackParamAtCluster->AddLast(new AliMUONTrackParam(*static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(i))));
}
if (track.fClusterWeightsNonBending) {
if (fClusterWeightsNonBending) {
fClusterWeightsNonBending->ResizeTo(*(track.fClusterWeightsNonBending));
*fClusterWeightsNonBending = *(track.fClusterWeightsNonBending);
} else fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
}
if (track.fClusterWeightsBending) {
if (fClusterWeightsBending) {
fClusterWeightsBending->ResizeTo(*(track.fClusterWeightsBending));
*fClusterWeightsBending = *(track.fClusterWeightsBending);
} else fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
}
if (track.fTrackParamAtVertex) {
if (fTrackParamAtVertex) *fTrackParamAtVertex = *(track.fTrackParamAtVertex);
else fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
}
fFitWithVertex = track.fFitWithVertex;
fVertexErrXY2[0] = track.fVertexErrXY2[0];
fVertexErrXY2[1] = track.fVertexErrXY2[1];
fFitWithMCS = track.fFitWithMCS;
fGlobalChi2 = track.fGlobalChi2;
fImproved = track.fImproved;
fMatchTrigger = track.fMatchTrigger;
fChi2MatchTrigger = track.fChi2MatchTrigger;
fTrackID = track.fTrackID;
fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
fHitsPatternInTrigChTrk = track.fHitsPatternInTrigChTrk;
fLocalTrigger = track.fLocalTrigger;
fConnected = track.fConnected;
return *this;
}
AliMUONTrack::~AliMUONTrack()
{
delete fTrackParamAtCluster;
delete fClusterWeightsNonBending;
delete fClusterWeightsBending;
delete fTrackParamAtVertex;
}
void AliMUONTrack::Clear(Option_t* )
{
delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
}
void AliMUONTrack::Reset()
{
SetUniqueID(0);
fFitWithVertex = kFALSE;
fVertexErrXY2[0] = 0.;
fVertexErrXY2[1] = 0.;
fFitWithMCS = kFALSE;
fGlobalChi2 = -1.;
fImproved = kFALSE;
fMatchTrigger = -1;
fChi2MatchTrigger = 0.;
fTrackID = -1;
fHitsPatternInTrigCh = 0;
fHitsPatternInTrigChTrk = 0;
fLocalTrigger = 0;
fConnected = kFALSE;
delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
}
TObjArray* AliMUONTrack::GetTrackParamAtCluster() const
{
if (!fTrackParamAtCluster) {
fTrackParamAtCluster = new TObjArray(20);
fTrackParamAtCluster->SetOwner(kTRUE);
}
return fTrackParamAtCluster;
}
void AliMUONTrack::AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy)
{
if (cluster.GetChamberId() < 0 || cluster.GetChamberId() > AliMUONConstants::NTrackingCh()) {
AliError(Form("Chamber ID of the associated cluster is not valid (ChamberId=%d)",cluster.GetChamberId()));
return;
}
if (TMath::Abs(cluster.GetZ() - trackParam.GetZ())>1.e-5) {
AliError("track parameters are given at a different z position than the one of the associated cluster");
return;
}
if (!fTrackParamAtCluster) {
fTrackParamAtCluster = new TObjArray(20);
fTrackParamAtCluster->SetOwner(kTRUE);
}
AliMUONTrackParam* trackParamAtCluster = new AliMUONTrackParam(trackParam);
fTrackParamAtCluster->AddLast(trackParamAtCluster);
if (copy) {
AliMUONVCluster *clusterCopy = static_cast<AliMUONVCluster*>(cluster.Clone());
trackParamAtCluster->SetClusterPtr(clusterCopy, kTRUE);
} else trackParamAtCluster->SetClusterPtr(&cluster);
fTrackParamAtCluster->Sort();
}
void AliMUONTrack::RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
{
if (fTrackParamAtCluster) {
AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->Remove(trackParam));
if (trackParamAtCluster) {
delete trackParamAtCluster;
fTrackParamAtCluster->Compress();
} else AliWarning("object to remove does not exist in array fTrackParamAtCluster");
} else AliWarning("array fTrackParamAtCluster does not exist");
}
Bool_t AliMUONTrack::UpdateTrackParamAtCluster()
{
Int_t nClusters = GetNClusters();
if (nClusters == 0) {
AliWarning("no cluster attached to the track");
return kFALSE;
}
Bool_t extrapStatus = kTRUE;
AliMUONTrackParam* startingTrackParam = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(0));
for (Int_t i = 1; i < nClusters; i++) {
AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(i));
trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
trackParamAtCluster->SetZ(startingTrackParam->GetZ());
if (!AliMUONTrackExtrap::ExtrapToZ(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ())) extrapStatus = kFALSE;
startingTrackParam = trackParamAtCluster;
}
if (!extrapStatus) SetGlobalChi2(2.*MaxChi2());
return extrapStatus;
}
Bool_t AliMUONTrack::UpdateCovTrackParamAtCluster()
{
Int_t nClusters = GetNClusters();
if (nClusters == 0) {
AliWarning("no cluster attached to the track");
return kFALSE;
}
Bool_t extrapStatus = kTRUE;
AliMUONTrackParam* startingTrackParam = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(0));
Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() + 1;
Int_t currentChamber;
for (Int_t i = 1; i < nClusters; i++) {
AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(i));
trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
trackParamAtCluster->SetZ(startingTrackParam->GetZ());
trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances());
AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber-1),-1.);
currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
while (currentChamber > expectedChamber) {
if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber))) extrapStatus = kFALSE;
AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber),-1.);
expectedChamber++;
}
if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ())) extrapStatus = kFALSE;
expectedChamber = currentChamber + 1;
startingTrackParam = trackParamAtCluster;
}
if (!extrapStatus) SetGlobalChi2(2.*MaxChi2());
return extrapStatus;
}
Bool_t AliMUONTrack::IsValid(UInt_t requestedStationMask, Bool_t request2ChInSameSt45)
{
Int_t nClusters = GetNClusters();
AliMUONTrackParam *trackParam;
Int_t currentCh, currentSt, previousCh = -1, nChHitInSt4 = 0, nChHitInSt5 = 0;
UInt_t presentStationMask(0);
for (Int_t i = 0; i < nClusters; i++) {
trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
currentCh = trackParam->GetClusterPtr()->GetChamberId();
currentSt = currentCh/2;
presentStationMask |= ( 1 << currentSt );
if (currentSt == 3 && currentCh != previousCh) {
nChHitInSt4++;
previousCh = currentCh;
}
if (currentSt == 4 && currentCh != previousCh) {
nChHitInSt5++;
previousCh = currentCh;
}
}
if ((requestedStationMask & presentStationMask) != requestedStationMask) return kFALSE;
if (request2ChInSameSt45) return (nChHitInSt4 == 2 || nChHitInSt5 == 2);
else return (nChHitInSt4+nChHitInSt5 >= 2);
}
void AliMUONTrack::TagRemovableClusters(UInt_t requestedStationMask) {
Int_t nClusters = GetNClusters();
AliMUONTrackParam *trackParam, *nextTrackParam;
Int_t currentCh, nextCh, currentSt, nextSt, previousCh = -1, nChHitInSt45 = 0;
for (Int_t i = 0; i < nClusters; i++) {
trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
currentCh = trackParam->GetClusterPtr()->GetChamberId();
currentSt = currentCh/2;
if ((1 << currentSt) & requestedStationMask) trackParam->SetRemovable(kFALSE);
else trackParam->SetRemovable(kTRUE);
if (currentCh > 5 && currentCh != previousCh) {
nChHitInSt45++;
previousCh = currentCh;
}
}
for (Int_t i = 0; i < nClusters; i++) {
trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
currentCh = trackParam->GetClusterPtr()->GetChamberId();
currentSt = currentCh/2;
if (nChHitInSt45 < 3 && currentSt > 2) {
if (i == nClusters-1) {
trackParam->SetRemovable(kFALSE);
} else {
nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i+1);
nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
if (nextCh == currentCh) {
trackParam->SetRemovable(kTRUE);
nextTrackParam->SetRemovable(kTRUE);
i++;
} else {
trackParam->SetRemovable(kFALSE);
}
}
} else {
if (trackParam->IsRemovable()) continue;
for (Int_t j = i+1; j < nClusters; j++) {
nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(j);
nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
nextSt = nextCh/2;
if (nextSt == currentSt) {
trackParam->SetRemovable(kTRUE);
nextTrackParam->SetRemovable(kTRUE);
i++;
}
}
}
}
}
Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
{
AliDebug(1,"Enter ComputeLocalChi2");
if (!fTrackParamAtCluster) {
AliWarning("no cluster attached to this track");
return kFALSE;
}
if (accountForMCS) {
Int_t nClusters = GetNClusters();
TMatrixD mcsCovariances(nClusters,nClusters);
ComputeMCSCovariances(mcsCovariances);
if (!ComputeClusterWeights(&mcsCovariances)) {
AliWarning("cannot take into account the multiple scattering effects");
return ComputeLocalChi2(kFALSE);
}
Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
if (globalChi2 < 0.) return kFALSE;
AliMUONTrackParam* trackParamAtCluster;
AliMUONTrackParam* trackParamAtCluster1;
AliMUONVCluster *cluster, *discardedCluster;
Int_t iCluster1, iCluster2, iCurrentCluster1, iCurrentCluster2;
TMatrixD clusterWeightsNB(nClusters-1,nClusters-1);
TMatrixD clusterWeightsB(nClusters-1,nClusters-1);
Double_t *dX = new Double_t[nClusters-1];
Double_t *dY = new Double_t[nClusters-1];
Double_t globalChi2b;
for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(iCluster));
discardedCluster = trackParamAtCluster->GetClusterPtr();
if (!ComputeClusterWeights(clusterWeightsNB, clusterWeightsB, &mcsCovariances, discardedCluster)) {
AliWarning("cannot take into account the multiple scattering effects");
delete [] dX;
delete [] dY;
return ComputeLocalChi2(kFALSE);
}
globalChi2b = 0.;
iCurrentCluster1 = 0;
for (iCluster1 = 0; iCluster1 < nClusters ; iCluster1++) {
trackParamAtCluster1 = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
cluster = trackParamAtCluster1->GetClusterPtr();
if (cluster == discardedCluster) continue;
dX[iCurrentCluster1] = cluster->GetX() - trackParamAtCluster1->GetNonBendingCoor();
dY[iCurrentCluster1] = cluster->GetY() - trackParamAtCluster1->GetBendingCoor();
iCurrentCluster2 = 0;
for (iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
cluster = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
if (cluster == discardedCluster) continue;
globalChi2b += (clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) +
clusterWeightsNB(iCurrentCluster2, iCurrentCluster1)) * dX[iCurrentCluster1] * dX[iCurrentCluster2] +
(clusterWeightsB(iCurrentCluster1, iCurrentCluster2) +
clusterWeightsB(iCurrentCluster2, iCurrentCluster1)) * dY[iCurrentCluster1] * dY[iCurrentCluster2];
iCurrentCluster2++;
}
globalChi2b += clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) * dX[iCurrentCluster1] * dX[iCurrentCluster1] +
clusterWeightsB(iCurrentCluster1, iCurrentCluster1) * dY[iCurrentCluster1] * dY[iCurrentCluster1];
iCurrentCluster1++;
}
trackParamAtCluster->SetLocalChi2(globalChi2 - globalChi2b);
}
delete [] dX;
delete [] dY;
} else {
Int_t nClusters = GetNClusters();
AliMUONTrackParam* trackParamAtCluster;
AliMUONVCluster *discardedCluster;
Double_t dX, dY;
for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(iCluster));
discardedCluster = trackParamAtCluster->GetClusterPtr();
dX = discardedCluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
dY = discardedCluster->GetY() - trackParamAtCluster->GetBendingCoor();
trackParamAtCluster->SetLocalChi2(dX * dX / discardedCluster->GetErrX2() + dY * dY / discardedCluster->GetErrY2());
}
}
return kTRUE;
}
Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
{
AliDebug(1,"Enter ComputeGlobalChi2");
if (!fTrackParamAtCluster) {
AliWarning("no cluster attached to this track");
return 2.*MaxChi2();
}
Double_t chi2 = 0.;
if (accountForMCS) {
if (!fClusterWeightsNonBending || !fClusterWeightsBending) {
AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
return ComputeGlobalChi2(kFALSE);
}
Int_t nClusters = GetNClusters();
if (fClusterWeightsNonBending->GetNrows() != nClusters || fClusterWeightsBending->GetNcols() != nClusters) {
AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
return ComputeGlobalChi2(kFALSE);
}
AliMUONVCluster *cluster;
Double_t *dX = new Double_t[nClusters];
Double_t *dY = new Double_t[nClusters];
AliMUONTrackParam* trackParamAtCluster;
for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
cluster = trackParamAtCluster->GetClusterPtr();
dX[iCluster1] = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
dY[iCluster1] = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
for (Int_t iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster2) + (*fClusterWeightsNonBending)(iCluster2, iCluster1)) * dX[iCluster1] * dX[iCluster2] +
((*fClusterWeightsBending)(iCluster1, iCluster2) + (*fClusterWeightsBending)(iCluster2, iCluster1)) * dY[iCluster1] * dY[iCluster2];
}
chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster1) * dX[iCluster1] * dX[iCluster1]) +
((*fClusterWeightsBending)(iCluster1, iCluster1) * dY[iCluster1] * dY[iCluster1]);
}
delete [] dX;
delete [] dY;
} else {
AliMUONVCluster *cluster;
Double_t dX, dY;
AliMUONTrackParam* trackParamAtCluster;
Int_t nClusters = GetNClusters();
for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
cluster = trackParamAtCluster->GetClusterPtr();
dX = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
dY = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
chi2 += dX * dX / cluster->GetErrX2() + dY * dY / cluster->GetErrY2();
}
}
return chi2;
}
Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD* mcsCovariances)
{
AliDebug(1,"Enter ComputeClusterWeights1");
if (!fTrackParamAtCluster) {
AliWarning("no cluster attached to this track");
return kFALSE;
}
Int_t nClusters = GetNClusters();
if (!fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(nClusters,nClusters);
if (!fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(nClusters,nClusters);
if (!ComputeClusterWeights(*fClusterWeightsNonBending, *fClusterWeightsBending, mcsCovariances)) return kFALSE;
return kTRUE;
}
Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD& clusterWeightsNB, TMatrixD& clusterWeightsB,
TMatrixD* mcsCovariances, const AliMUONVCluster* discardedCluster) const
{
AliDebug(1,"Enter ComputeClusterWeights2");
Int_t nClusters = GetNClusters();
Bool_t deleteMCSCov = kFALSE;
if (!mcsCovariances) {
mcsCovariances = new TMatrixD(nClusters,nClusters);
deleteMCSCov = kTRUE;
ComputeMCSCovariances(*mcsCovariances);
}
if (discardedCluster) {
clusterWeightsNB.ResizeTo(nClusters-1,nClusters-1);
clusterWeightsB.ResizeTo(nClusters-1,nClusters-1);
} else {
clusterWeightsNB.ResizeTo(nClusters,nClusters);
clusterWeightsB.ResizeTo(nClusters,nClusters);
}
AliMUONVCluster *cluster1, *cluster2;
Int_t iCurrentCluster1, iCurrentCluster2;
iCurrentCluster1 = 0;
for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
if (cluster1 == discardedCluster) continue;
iCurrentCluster2 = iCurrentCluster1;
for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
if (cluster2 == discardedCluster) continue;
clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) = (*mcsCovariances)(iCluster1,iCluster2);
clusterWeightsB(iCurrentCluster1, iCurrentCluster2) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
if (iCurrentCluster1 == iCurrentCluster2) {
clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrX2();
clusterWeightsB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrY2();
} else {
clusterWeightsNB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
clusterWeightsB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsB(iCurrentCluster1, iCurrentCluster2);
}
iCurrentCluster2++;
}
iCurrentCluster1++;
}
if (clusterWeightsNB.Determinant() != 0 && clusterWeightsB.Determinant() != 0) {
clusterWeightsNB.Invert();
clusterWeightsB.Invert();
} else {
AliWarning(" Determinant = 0");
clusterWeightsNB.ResizeTo(0,0);
clusterWeightsB.ResizeTo(0,0);
if(deleteMCSCov) delete mcsCovariances;
return kFALSE;
}
if(deleteMCSCov) delete mcsCovariances;
return kTRUE;
}
void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
{
AliDebug(1,"Enter ComputeMCSCovariances");
Int_t nClusters = GetNClusters();
if (mcsCovariances.GetNrows() != nClusters) mcsCovariances.ResizeTo(nClusters,nClusters);
Int_t nChambers = AliMUONConstants::NTrackingCh();
AliMUONTrackParam* trackParamAtCluster;
AliMUONTrackParam extrapTrackParam;
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*nClusters];
for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
while (currentChamber > expectedChamber) {
zMCS[size] = AliMUONConstants::DefaultChamberZ(expectedChamber);
if (iCluster > 0) {
extrapTrackParam = *trackParamAtCluster;
AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[size]);
mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(expectedChamber),1.);
} else mcsAngle2[size] = 0.;
expectedChamber++;
size++;
}
zMCS[size] = trackParamAtCluster->GetZ();
mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(currentChamber),1.);
indices[iCluster] = size;
expectedChamber = currentChamber + 1;
size++;
}
if (currentChamber != nChambers-1) zMCS[size++] = AliMUONConstants::DefaultChamberZ(nChambers-1);
for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
mcsCovariances(iCluster1,iCluster2) = 0.;
for (Int_t k = 0; k < indices[iCluster1]; k++) {
mcsCovariances(iCluster1,iCluster2) += (zMCS[indices[iCluster1]] - zMCS[k]) * (zMCS[indices[iCluster2]] - zMCS[k]) * mcsAngle2[k];
}
mcsCovariances(iCluster2,iCluster1) = mcsCovariances(iCluster1,iCluster2);
}
}
delete [] mcsAngle2;
delete [] zMCS;
delete [] indices;
}
Int_t AliMUONTrack::ClustersInCommon(AliMUONTrack* track, Int_t stMin, Int_t stMax) const
{
if (!track || !track->fTrackParamAtCluster || !this->fTrackParamAtCluster) return 0;
Int_t chMin = 2 * stMin;
Int_t chMax = 2 * stMax + 1;
Int_t clustersInCommon = 0;
Int_t nCl1 = this->GetNClusters();
for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
AliMUONVCluster* cl1 = ((AliMUONTrackParam*) this->fTrackParamAtCluster->UncheckedAt(iCl1))->GetClusterPtr();
Int_t chCl1 = cl1->GetChamberId();
if (chCl1 < chMin || chCl1 > chMax) continue;
Int_t nCl2 = track->GetNClusters();
for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
AliMUONVCluster* cl2 = ((AliMUONTrackParam*) track->fTrackParamAtCluster->UncheckedAt(iCl2))->GetClusterPtr();
Int_t chCl2 = cl2->GetChamberId();
if (chCl2 < chMin || chCl2 > chMax) continue;
if (cl1->GetUniqueID() == cl2->GetUniqueID()) {
clustersInCommon++;
break;
}
}
}
return clustersInCommon;
}
Int_t AliMUONTrack::GetNDF() const
{
Int_t ndf = 2 * GetNClusters() - 5;
return (ndf > 0) ? ndf : 0;
}
Double_t AliMUONTrack::GetNormalizedChi2() const
{
Double_t ndf = (Double_t) GetNDF();
return (ndf > 0.) ? fGlobalChi2 / ndf : 2.*MaxChi2();
}
Int_t AliMUONTrack::FindCompatibleClusters(const AliMUONTrack &track, Double_t sigmaCut, Bool_t compatibleCluster[10]) const
{
AliMUONVCluster *cluster1, *cluster2;
Double_t chi2, dX, dY;
Double_t chi2Max = sigmaCut * sigmaCut;
Int_t nMatchClusters = 0;
for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) compatibleCluster[ch] = kFALSE;
if (!track.fTrackParamAtCluster || !this->fTrackParamAtCluster) return nMatchClusters;
Int_t nCl1 = this->GetNClusters();
for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
cluster1 = static_cast<AliMUONTrackParam*>(this->fTrackParamAtCluster->UncheckedAt(iCl1))->GetClusterPtr();
Int_t nCl2 = track.GetNClusters();
for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
cluster2 = static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(iCl2))->GetClusterPtr();
if (cluster1->GetDetElemId() != cluster2->GetDetElemId()) continue;
dX = cluster1->GetX() - cluster2->GetX();
dY = cluster1->GetY() - cluster2->GetY();
chi2 = dX * dX / (cluster1->GetErrX2() + cluster2->GetErrX2()) + dY * dY / (cluster1->GetErrY2() + cluster2->GetErrY2());
if (chi2 > 2. * chi2Max) continue;
compatibleCluster[cluster1->GetChamberId()] = kTRUE;
nMatchClusters++;
break;
}
}
return nMatchClusters;
}
Bool_t AliMUONTrack::Match(AliMUONTrack &track, Double_t sigmaCut, Int_t &nMatchClusters) const
{
Bool_t compTrack[10];
nMatchClusters = FindCompatibleClusters(track, sigmaCut, compTrack);
if ((compTrack[0] || compTrack[1] || compTrack[2] || compTrack[3]) &&
(compTrack[6] || compTrack[7] || compTrack[8] || compTrack[9]) &&
2 * nMatchClusters > GetNClusters()) return kTRUE;
else return kFALSE;
}
void AliMUONTrack::SetTrackParamAtVertex(const AliMUONTrackParam* trackParam)
{
if (trackParam == 0x0) return;
if (fTrackParamAtVertex) *fTrackParamAtVertex = *trackParam;
else fTrackParamAtVertex = new AliMUONTrackParam(*trackParam);
}
void AliMUONTrack::RecursiveDump() const
{
AliMUONTrackParam *trackParamAtCluster;
AliMUONVCluster *cluster;
cout << "Recursive dump of Track: " << this << endl;
this->Dump();
for (Int_t iCluster = 0; iCluster < GetNClusters(); iCluster++) {
trackParamAtCluster = (AliMUONTrackParam*) ((*fTrackParamAtCluster)[iCluster]);
cout << "trackParamAtCluster: " << trackParamAtCluster << " (index: " << iCluster << ")" << endl;
trackParamAtCluster->Dump();
cluster = trackParamAtCluster->GetClusterPtr();
cout << "cluster: " << cluster << endl;
cluster->Print();
}
return;
}
void AliMUONTrack::Print(Option_t*) const
{
streamsize curW = cout.width();
streamsize curPrecision = cout.precision();
cout << "<AliMUONTrack> No.Clusters=" << setw(2) << GetNClusters() <<
", Match2Trig=" << setw(1) << GetMatchTrigger() <<
", LoTrgNum=" << setw(3) << LoCircuit() <<
", Chi2-tracking-trigger=" << setw(8) << setprecision(5) << GetChi2MatchTrigger();
cout << Form(" HitTriggerPattern trig %x track %x",fHitsPatternInTrigCh, fHitsPatternInTrigChTrk);
cout << Form(" MClabel=%d",fTrackID) << endl;
if (fTrackParamAtCluster) fTrackParamAtCluster->First()->Print("FULL");
cout.width(curW);
cout.precision(curPrecision);
}
void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt, UChar_t respWithoutChamber)
{
if (loCirc < 0) return;
fLocalTrigger = 0;
fLocalTrigger += loCirc;
fLocalTrigger += loStripX << 8;
fLocalTrigger += loStripY << 13;
fLocalTrigger += loDev << 17;
fLocalTrigger += loLpt << 22;
fLocalTrigger += loHpt << 24;
fLocalTrigger += respWithoutChamber << 26;
}
void AliMUONTrack::FindMCLabel()
{
Int_t nClusters = GetNClusters();
Int_t halfCluster = nClusters/2;
fTrackID = -1;
for (Int_t iCluster1 = 0; iCluster1 < nClusters-halfCluster; iCluster1++) {
AliMUONVCluster* cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
if (cluster1->GetChamberId() > 3) return;
Int_t label1 = cluster1->GetMCLabel();
if (label1 < 0) continue;
Int_t nIdenticalLabel = 1;
for (Int_t iCluster2 = iCluster1+1; iCluster2 < nClusters; iCluster2++) {
AliMUONVCluster* cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
if (cluster2->GetMCLabel() != label1) continue;
nIdenticalLabel++;
if (nIdenticalLabel > halfCluster && cluster2->GetChamberId() > 5) {
fTrackID = label1;
return;
}
}
}
}