+ /// Constructor from two clusters
+
+ fVertexErrXY2[0] = 0.;
+ fVertexErrXY2[1] = 0.;
+
+ // Pointers to clusters from the segment
+ AliMUONVCluster* firstCluster = (AliMUONVCluster*) segment->First();
+ AliMUONVCluster* lastCluster = (AliMUONVCluster*) segment->Second();
+
+ // Compute track parameters
+ Double_t z1 = firstCluster->GetZ();
+ Double_t z2 = lastCluster->GetZ();
+ Double_t dZ = z1 - z2;
+ // Non bending plane
+ Double_t nonBendingCoor1 = firstCluster->GetX();
+ Double_t nonBendingCoor2 = lastCluster->GetX();
+ Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
+ // Bending plane
+ Double_t bendingCoor1 = firstCluster->GetY();
+ Double_t bendingCoor2 = lastCluster->GetY();
+ Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
+ // Inverse bending momentum
+ Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
+ Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
+
+ // Set track parameters at first cluster
+ AliMUONTrackParam trackParamAtFirstCluster;
+ trackParamAtFirstCluster.SetZ(z1);
+ trackParamAtFirstCluster.SetNonBendingCoor(nonBendingCoor1);
+ trackParamAtFirstCluster.SetNonBendingSlope(nonBendingSlope);
+ trackParamAtFirstCluster.SetBendingCoor(bendingCoor1);
+ trackParamAtFirstCluster.SetBendingSlope(bendingSlope);
+ trackParamAtFirstCluster.SetInverseBendingMomentum(inverseBendingMomentum);
+
+ // Set track parameters at last cluster
+ AliMUONTrackParam trackParamAtLastCluster;
+ trackParamAtLastCluster.SetZ(z2);
+ trackParamAtLastCluster.SetNonBendingCoor(nonBendingCoor2);
+ trackParamAtLastCluster.SetNonBendingSlope(nonBendingSlope);
+ trackParamAtLastCluster.SetBendingCoor(bendingCoor2);
+ trackParamAtLastCluster.SetBendingSlope(bendingSlope);
+ trackParamAtLastCluster.SetInverseBendingMomentum(inverseBendingMomentum);
+
+ // Compute and set track parameters covariances at first cluster
+ TMatrixD paramCov(5,5);
+ paramCov.Zero();
+ // Non bending plane
+ 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;
+ // Bending plane
+ 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;
+ // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
+ 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);
+
+ // Compute and set track parameters covariances at last cluster
+ // Non bending plane
+ paramCov(0,0) = lastCluster->GetErrX2();
+ paramCov(0,1) = - lastCluster->GetErrX2() / dZ;
+ paramCov(1,0) = paramCov(0,1);
+ // Bending plane
+ paramCov(2,2) = lastCluster->GetErrY2();
+ paramCov(2,3) = - lastCluster->GetErrY2() / dZ;
+ paramCov(3,2) = paramCov(2,3);
+ // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
+ if (AliMUONTrackExtrap::IsFieldON()) {
+ paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
+ paramCov(4,2) = paramCov(2,4);
+ }
+ trackParamAtLastCluster.SetCovariances(paramCov);
+
+ // Add track parameters at clusters
+ 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),
+ floTrgNum(track.floTrgNum),
+ fChi2MatchTrigger(track.fChi2MatchTrigger),
+ fTrackID(track.fTrackID),
+ fTrackParamAtVertex(0x0),
+ fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
+ fLocalTrigger(track.fLocalTrigger)
+{
+ ///copy constructor
+
+ // necessary to make a copy of the objects and not only the pointers in TClonesArray.
+ if (track.fTrackParamAtCluster) {
+ fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
+ AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->First();
+ while (trackParamAtCluster) {
+ new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(*trackParamAtCluster);
+ trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->After(trackParamAtCluster);
+ }
+ }
+
+ // copy vertex resolution square used during the tracking procedure
+ fVertexErrXY2[0] = track.fVertexErrXY2[0];
+ fVertexErrXY2[1] = track.fVertexErrXY2[1];
+
+ // copy cluster weights matrices if any
+ if (track.fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
+ if (track.fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
+
+ // copy track parameters at vertex if any
+ if (track.fTrackParamAtVertex) fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
+