///////////////////////////////////////////////////////////////////////////////
//
// Kalman filter based aligner:
-// Aligns two tracking volumes (by default ITS and TPC)
-// Determines the transformation of the second volume (TPC) wrt the first (ITS)
-// additionally calculates some callibration parameters for TPC
+// Finds alignement constants for two tracking volumes (by default ITS
+// and TPC)
+// Determines the inverse transformation of the second volume (TPC)
+// with respect to the first (ITS) (how to realign TPC to ITS)
+// by measuring the residual between the 2 tracks.
+// Additionally calculates some callibration parameters for TPC
// Fit parameters are:
// - 3 shifts, x,y,z
// - 3 Cardan angles, psi, theta, phi (see definition in alignment docs),
-// - TPC drift velocity correction (vel_true = vel*(1+correction)),
-// - TPC offset correction.
+// - TPC drift velocity correction,
+// - TPC time offset correction.
//
// Basic usage:
-// When aligning two volumes at any given time a single instance of
+// When aligning two volumes, at any given time a single instance of
// the class should be active. The fit of the parameters is updated
-// by adding new data using one of the Add.... methods.
+// by adding new data using one of the Add.... methods:
//
-// User methods:
-// In collision events add an ESD track to update the fit,
-// track will be automatically split in ITS and TPC tracklets
-// and the fit of the alignment constants will be updated:
-//
-// Bool_t AddESDTrack( AliESDtrack* pTrack );
-//
-// You may also give it the AliTrackPointArray,
-// the fit will be updated if there are enough ITS and TPC
-// points in it. Again, all is done automatically:
-//
-// Bool_t AddTrackPointArray( AliTrackPointArray* pTrackPointArr );
-//
-// For cosmic data, the assumption is that the tracking is done separately
-// for ITS and TPC and the tracklets are saved inside one AliESDEvent. The
-// method
-//
-// Bool_t AddCosmicEventSeparateTracking( AliESDEvent* pEvent );
-//
-// then searches the event for matching tracklets and upon succes it updates
-// the fit. For cosmics the fitter switches to a 3 tracks mode, the 3 tracks
-// being: 1 ITS and 2 TPC tracklets (upper and lower).
-//
-// Experts only:
+// In collision events add an ESD event to update the fit (adds all tracks):
+//
+// Bool_t AddESDevent( AliESDevent* pTrack );
//
+// or add each individual track
+//
+// AddESDtrack( AliESDtrack* pTrack );
+//
+// For cosmic data, the assumption is that the tracking is done twice:
+// once global and once only ITS and the tracklets are saved inside
+// one AliESDEvent. The method
+//
+// Bool_t AddCosmicEvent( AliESDEvent* pEvent );
+//
+// then searches the event for matching tracklets and upon succes it updates.
+// One cosmic ideally triggers two updates: for the upper and lower half of
+// the cosmic (upper ITS tracklet+upper TPC tracklet, idem dito for lower)
+//
+// by default give misalignment parameters for TPC as they appear to be.
+// TPC calibration parameters are always given as correction to values used in reco.
+//
+// _________________________________________________________________________
+// Expert options:
+// look at AddESDevent() and AddCosmicEvent() to get the idea of how the
+// aligner works, it's safe to repeat the needed steps outside of the class,
+// only public methods are used.
//
// Origin: Mikolaj Krzewicki, Nikhef, Mikolaj.Krzewicki@cern.ch
//
//////////////////////////////////////////////////////////////////////////////
-#include <Riostream.h>
+#include <iostream>
+#include <TObject.h>
+#include <TMath.h>
+#include <TMatrix.h>
+#include <TVector.h>
+#include <TVector3.h>
+#include <TDecompLU.h>
+#include <TArrayI.h>
+#include <TH1D.h>
+#include <TF1.h>
+
+#include "AliESDtrack.h"
+#include "AliTrackPointArray.h"
+#include "AliGeomManager.h"
+#include "AliTrackFitterKalman.h"
+#include "AliTrackFitterRieman.h"
+#include "AliESDfriendTrack.h"
+#include "AliESDEvent.h"
+#include "AliESDVertex.h"
+#include "AliExternalTrackParam.h"
#include "AliRelAlignerKalman.h"
ClassImp(AliRelAlignerKalman)
-//########################################################
-//
-// Control section
-//
-//########################################################
-
+//______________________________________________________________________________
AliRelAlignerKalman::AliRelAlignerKalman():
- fPTrackPointArray1(new AliTrackPointArray(1)),
- fPTrackPointArray2(new AliTrackPointArray(1)),
- fPTrackPointArray2b(new AliTrackPointArray(1)),
- fPVolIDArray1(new TArrayI(1)),
- fPVolIDArray2(new TArrayI(1)),
- fPVolIDArray2b(new TArrayI(1)),
- fQ(1e-10),
- fNMeasurementParams(fgkNMeasurementParams2TrackMode),
- fNSystemParams(fgkNSystemParams),
- fOutRejSigmas(2.),
- f3TracksMode(kFALSE),
- fSortTrackPointsWithY(kTRUE),
- fFixedMeasurementCovariance(kTRUE),
- fCalibrationPass(kFALSE),
- fCalibrationUpdated(kFALSE),
- fFitted(kFALSE),
+ TObject(),
+ fAlpha(0.),
+ fLocalX(80.),
+ fPTrackParamArr1(new AliExternalTrackParam[fgkNTracksPerMeasurement]),
+ fPTrackParamArr2(new AliExternalTrackParam[fgkNTracksPerMeasurement]),
+ fMagField(0.),
+ fPX(new TVectorD( fgkNSystemParams )),
+ fPXcov(new TMatrixDSym( fgkNSystemParams )),
+ fPH(new TMatrixD( fgkNMeasurementParams, fgkNSystemParams )),
+ fQ(1.e-15),
+ fPMeasurement(new TVectorD( fgkNMeasurementParams )),
+ fPMeasurementCov(new TMatrixDSym( fgkNMeasurementParams )),
+ fPMeasurementPrediction(new TVectorD( fgkNMeasurementParams )),
+ fOutRejSigmas(1.),
+ //fDelta(new Double_t[fgkNSystemParams]),
+ fNumericalParanoia(kTRUE),
+ fRejectOutliers(kTRUE),
+ fRequireMatchInTPC(kFALSE),
fCuts(kFALSE),
+ fMinPointsVol1(3),
+ fMinPointsVol2(50),
+ fMinMom(0.),
+ fMaxMom(1.e100),
+ fMaxMatchingAngle(0.1),
+ fMaxMatchingDistance(10.), //in cm
+ fCorrectionMode(kFALSE),
fNTracks(0),
fNUpdates(0),
fNOutliers(0),
- fNUnfitted(0),
fNMatchedCosmics(0),
- fMinPointsVol1(2),
- fMinPointsVol2(10),
- fMinMom(0.),
- fMaxMom(1e100),
- fMinAbsSinPhi(0.),
- fMaxAbsSinPhi(1.),
- fMinSinTheta(-1.),
- fMaxSinTheta(1.),
- fMaxMatchingAngle(0.1),
- fMaxMatchingDistance(1.), //in cm
- fFirstLayerVol1(1),
- fLastLayerVol1(6),
- fFirstLayerVol2(7),
- fLastLayerVol2(8)
+ fNMatchedTPCtracklets(0),
+ fNProcessedEvents(0),
+ fTrackInBuffer(0),
+ fTimeStamp(0),
+ fRunNumber(0),
+ fTPCvd(2.64),
+ fTPCZLengthA(2.4972500e02),
+ fTPCZLengthC(2.4969799e02)
{
- //Default constructor
-
- fPDir1 = new TVector3; //Direction
- fPDir2 = new TVector3;
- fPDir2b = new TVector3;
- fPDir1Cov = new TMatrixDSym(3);
- fPDir2Cov = new TMatrixDSym(3);
- fPDir2bCov = new TMatrixDSym(3);
- fPDir1ThetaPhiCov = new TMatrixDSym(2); //Direction vectors are unit vectors, therefore 2 independent components!
- fPDir2ThetaPhiCov = new TMatrixDSym(2);
- fPDir2bThetaPhiCov = new TMatrixDSym(2);
- fPPoint1 = new TVector3;
- fPPoint2 = new TVector3;
- fPPoint2b = new TVector3;
- fPPoint1Cov = new TMatrixDSym(3);
- fPPoint2Cov = new TMatrixDSym(3);
- fPPoint2bCov = new TMatrixDSym(3);
- fPRefPoint = new TVector3(0.,0.,0.);
- fPRefPointDir = new TVector3(0.,1.,0.);
- Float_t refpointcov[6] = { 1., 0., 0.,
- 0., 0.,
- 1. };
- fPRefAliTrackPoint = new AliTrackPoint( 0.,0.,0.,refpointcov,0 );
- fPMeasurement = new TVectorD( fNMeasurementParams );
- fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
- fPX = new TVectorD( fNSystemParams );
- fPXcov = new TMatrixDSym( fNSystemParams );
- fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
- fPRotMat = new TMatrixD(3,3);
- fPVec010 = new TVector3(0,1,0);
-
- //default seed: zero, unit(large) errors
- fPXcov->UnitMatrix();
- (*fPXcov) *= 1.;
-
- fPPhiMesHist = new TH1D("phi","phi", 50, 0, 0);
- fPThetaMesHist = new TH1D("theta","theta", 50, 0, 0);
- fPXMesHist = new TH1D("x","x", 50, 0, 0);
- fPZMesHist = new TH1D("z","z", 50, 0, 0);
- fPPhiMesHist2 = new TH1D("phi_","phi_", 50, 0, 0);
- fPThetaMesHist2 = new TH1D("theta_","theta_", 50, 0, 0);
- fPXMesHist2 = new TH1D("x_","x_", 50, 0, 0);
- fPZMesHist2 = new TH1D("z_","z_", 50, 0, 0);
+ //Default constructor
+
+ //default seed: zero, reset errors to large default
+ Reset();
}
-Bool_t AliRelAlignerKalman::AddESDTrack( AliESDtrack* pTrack )
+//______________________________________________________________________________
+AliRelAlignerKalman::AliRelAlignerKalman(const AliRelAlignerKalman& a):
+ TObject(static_cast<TObject>(a)),
+ fAlpha(a.fAlpha),
+ fLocalX(a.fLocalX),
+ fPTrackParamArr1(new AliExternalTrackParam[fgkNTracksPerMeasurement]),
+ fPTrackParamArr2(new AliExternalTrackParam[fgkNTracksPerMeasurement]),
+ fMagField(a.fMagField),
+ fPX(new TVectorD( *a.fPX )),
+ fPXcov(new TMatrixDSym( *a.fPXcov )),
+ fPH(new TMatrixD( *a.fPH )),
+ fQ(a.fQ),
+ fPMeasurement(new TVectorD( *a.fPMeasurement )),
+ fPMeasurementCov(new TMatrixDSym( *a.fPMeasurementCov )),
+ fPMeasurementPrediction(new TVectorD( *a.fPMeasurement )),
+ fOutRejSigmas(a.fOutRejSigmas),
+ //fDelta(new Double_t[fgkNSystemParams]),
+ fNumericalParanoia(a.fNumericalParanoia),
+ fRejectOutliers(a.fRejectOutliers),
+ fRequireMatchInTPC(a.fRequireMatchInTPC),
+ fCuts(a.fCuts),
+ fMinPointsVol1(a.fMinPointsVol1),
+ fMinPointsVol2(a.fMinPointsVol2),
+ fMinMom(a.fMinMom),
+ fMaxMom(a.fMaxMom),
+ fMaxMatchingAngle(a.fMaxMatchingAngle),
+ fMaxMatchingDistance(a.fMaxMatchingDistance), //in cm
+ fCorrectionMode(a.fCorrectionMode),
+ fNTracks(a.fNTracks),
+ fNUpdates(a.fNUpdates),
+ fNOutliers(a.fNOutliers),
+ fNMatchedCosmics(a.fNMatchedCosmics),
+ fNMatchedTPCtracklets(a.fNMatchedTPCtracklets),
+ fNProcessedEvents(a.fNProcessedEvents),
+ fTrackInBuffer(a.fTrackInBuffer),
+ fTimeStamp(a.fTimeStamp),
+ fRunNumber(a.fRunNumber),
+ fTPCvd(a.fTPCvd),
+ fTPCZLengthA(a.fTPCZLengthA),
+ fTPCZLengthC(a.fTPCZLengthC)
+ //fApplyCovarianceCorrection(a.fApplyCovarianceCorrection),
+ //fCalibrationMode(a.fCalibrationMode),
+ //fFillHistograms(a.fFillHistograms),
+ //fNHistogramBins(a.fNHistogramBins),
+ //fPMes0Hist(new TH1D(*a.fPMes0Hist)),
+ //fPMes1Hist(new TH1D(*a.fPMes1Hist)),
+ //fPMes2Hist(new TH1D(*a.fPMes2Hist)),
+ //fPMes3Hist(new TH1D(*a.fPMes3Hist)),
+ //fPMesErr0Hist(new TH1D(*a.fPMesErr0Hist)),
+ //fPMesErr1Hist(new TH1D(*a.fPMesErr1Hist)),
+ //fPMesErr2Hist(new TH1D(*a.fPMesErr2Hist)),
+ //fPMesErr3Hist(new TH1D(*a.fPMesErr3Hist)),
+ //fPMeasurementCovCorr(new TMatrixDSym(*a.fPMeasurementCovCorr)),
{
- //Add an ESD track from a central event
- //from the ESDtrack extract the pointarray
-
- SetCosmicEvent(kFALSE);
-
- const AliTrackPointArray *pTrackPointArrayConst = pTrack->GetTrackPointArray();
- AliTrackPointArray* pTrackPointArray = const_cast < AliTrackPointArray* > (pTrackPointArrayConst);
- if (pTrackPointArray == 0) return kFALSE;
-
- if (!AddTrackPointArray( pTrackPointArray )) return kFALSE;
- return kTRUE;
+ //copy constructor
+ memcpy(fDelta,a.fDelta,fgkNSystemParams*sizeof(Double_t));
}
-Bool_t AliRelAlignerKalman::AddTrackPointArray( AliTrackPointArray* pTrackPointArray )
+//______________________________________________________________________________
+AliRelAlignerKalman& AliRelAlignerKalman::operator=(const AliRelAlignerKalman& a)
{
- //Add a trackpointarray from a central event
-
- SetCosmicEvent(kFALSE);
- fNTracks++;
-
- if (!ExtractSubTrackPointArray( fPTrackPointArray1, fPVolIDArray1, pTrackPointArray, 1,6 ))
- return kFALSE;
- if (!ExtractSubTrackPointArray( fPTrackPointArray2, fPVolIDArray2, pTrackPointArray, 7,8 ))
- return kFALSE;
-
- if (!ProcessTrackPointArrays()) return kFALSE;
- if (!PrepareUpdate()) return kFALSE;
- if (!Update()) return kFALSE;
-
- return kTRUE;
+ //assignment operator
+ //fAlpha=a.fAlpha;
+ //fLocalX=a.fLocalX;
+ //memcpy(fPTrackParamArr1,a.fPTrackParamArr1,fgkNTracksPerMeasurement*sizeof(AliExternalTrackParam));
+ //memcpy(fPTrackParamArr2,a.fPTrackParamArr2,fgkNTracksPerMeasurement*sizeof(AliExternalTrackParam));
+ fMagField=a.fMagField,
+ *fPX = *a.fPX;
+ *fPXcov = *a.fPXcov;
+ //*fPH = *a.fPH;
+ fQ=a.fQ;
+ //*fPMeasurement=*a.fPMeasurement;
+ //*fPMeasurementCov=*a.fPMeasurementCov;
+ fOutRejSigmas=a.fOutRejSigmas;
+ memcpy(fDelta,a.fDelta,fgkNSystemParams*sizeof(Double_t));
+ fNumericalParanoia=a.fNumericalParanoia;
+ fRejectOutliers=a.fRejectOutliers;
+ fRequireMatchInTPC=a.fRequireMatchInTPC;
+ fCuts=a.fCuts;
+ fMinPointsVol1=a.fMinPointsVol1;
+ fMinPointsVol2=a.fMinPointsVol2;
+ fMinMom=a.fMinMom;
+ fMaxMom=a.fMaxMom;
+ fMaxMatchingAngle=a.fMaxMatchingAngle;
+ fMaxMatchingDistance=a.fMaxMatchingDistance; //in c;
+ fCorrectionMode=a.fCorrectionMode;
+ fNTracks=a.fNTracks;
+ fNUpdates=a.fNUpdates;
+ fNOutliers=a.fNOutliers;
+ fNMatchedCosmics=a.fNMatchedCosmics;
+ fNMatchedTPCtracklets=a.fNMatchedTPCtracklets;
+ fNProcessedEvents=a.fNProcessedEvents;
+ fTrackInBuffer=a.fTrackInBuffer;
+ fTimeStamp=a.fTimeStamp;
+ fRunNumber=a.fRunNumber;
+ //fApplyCovarianceCorrection=a.fApplyCovarianceCorrection;
+ //fCalibrationMode=a.fCalibrationMode;
+ //fFillHistograms=a.fFillHistograms;
+ //fNHistogramBins=a.fNHistogramBins;
+ //*fPMes0Hist=*(a.fPMes0Hist);
+ //*fPMes1Hist=*(a.fPMes1Hist);
+ //*fPMes2Hist=*(a.fPMes2Hist);
+ //*fPMes3Hist=*(a.fPMes3Hist);
+ //*fPMesErr0Hist=*(a.fPMesErr0Hist);
+ //*fPMesErr1Hist=*(a.fPMesErr1Hist);
+ //*fPMesErr2Hist=*(a.fPMesErr2Hist);
+ //*fPMesErr3Hist=*(a.fPMesErr3Hist);
+ //*fPMeasurementCovCorr=*(a.fPMeasurementCovCorr);
+ fTPCvd=a.fTPCvd;
+ fTPCZLengthA=a.fTPCZLengthA;
+ fTPCZLengthC=a.fTPCZLengthC;
+ return *this;
}
-Bool_t AliRelAlignerKalman::AddCosmicEventSeparateTracking( AliESDEvent* pEvent )
+//______________________________________________________________________________
+AliRelAlignerKalman::~AliRelAlignerKalman()
{
- //Add an cosmic with separately tracked ITS and TPC parts, do trackmatching
-
- SetCosmicEvent(kTRUE); //set the cosmic flag
- fNTracks++;
-
- if (!FindCosmicInEvent( pEvent )) return kFALSE;
- if (!ProcessTrackPointArrays()) return kFALSE;
- //PrintDebugInfo();
- if (!PrepareUpdate()) return kFALSE;
- if (!Update()) return kFALSE;
- printf("fpMeasurementCov:\n");
- fPMeasurementCov->Print();
-
- return kTRUE;
+ //destructor
+ if (fPTrackParamArr1) delete [] fPTrackParamArr1;
+ if (fPTrackParamArr2) delete [] fPTrackParamArr2;
+ if (fPX) delete fPX;
+ if (fPXcov) delete fPXcov;
+ if (fPH) delete fPH;
+ if (fPMeasurement) delete fPMeasurement;
+ if (fPMeasurementCov) delete fPMeasurementCov;
+ //if (fDelta) delete [] fDelta;
+ //if (fPMes0Hist) delete fPMes0Hist;
+ //if (fPMes1Hist) delete fPMes1Hist;
+ //if (fPMes2Hist) delete fPMes2Hist;
+ //if (fPMes3Hist) delete fPMes3Hist;
+ //if (fPMesErr0Hist) delete fPMesErr0Hist;
+ //if (fPMesErr1Hist) delete fPMesErr1Hist;
+ //if (fPMesErr2Hist) delete fPMesErr2Hist;
+ //if (fPMesErr3Hist) delete fPMesErr3Hist;
+ //if (fPMeasurementCovCorr) delete fPMeasurementCovCorr;
}
-void AliRelAlignerKalman::Print()
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::AddESDevent( const AliESDEvent* pEvent )
{
- //Print some useful info
- printf("\nAliRelAlignerKalman:\n");
- printf(" %i tracks, %i updates, %i outliers, ", fNTracks, fNUpdates, fNOutliers );
- printf("%i not fitted, %i matched cosmic tracklets\n", fNUnfitted, fNMatchedCosmics );
- printf(" psi(x): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(0),1e3*TMath::Sqrt((*fPXcov)(0,0)));
- printf(" theta(y): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(1),1e3*TMath::Sqrt((*fPXcov)(1,1)));
- printf(" phi(z): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(2),1e3*TMath::Sqrt((*fPXcov)(2,2)));
- printf(" x: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(3),1e4*TMath::Sqrt((*fPXcov)(3,3)));
- printf(" y: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(4),1e4*TMath::Sqrt((*fPXcov)(4,4)));
- printf(" z: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(5),1e4*TMath::Sqrt((*fPXcov)(5,5)));
- printf(" TPC(drift corr) %.1f ± (%.1f) percent\n", 1e2*(*fPX)(6),1e2*TMath::Sqrt((*fPXcov)(6,6)));
- printf(" TPC(offset) %.1f ± (%.1f) micron\n", 1e4*(*fPX)(7),1e4*TMath::Sqrt((*fPXcov)(7,7)));
- return;
+ //Add all tracks in an ESD event
+
+ fNProcessedEvents++; //update the counter
+
+ Bool_t success=kFALSE;
+ SetMagField( pEvent->GetMagneticField() );
+ AliESDtrack* track;
+
+ for (Int_t i=0; i<pEvent->GetNumberOfTracks(); i++)
+ {
+ track = pEvent->GetTrack(i);
+ if (!track) continue;
+ if ( ((track->GetStatus()&AliESDtrack::kTPCin)>0)&&
+ ((track->GetStatus()&AliESDtrack::kITSout)>0)&&
+ (track->GetNcls(0)>=fMinPointsVol1)&&
+ (track->GetNcls(1)>=fMinPointsVol2) )
+ {
+ success = ( AddESDtrack( track ) || success );
+ }
+ }
+ if (success)
+ {
+ fTimeStamp = pEvent->GetTimeStamp();
+ fRunNumber = pEvent->GetRunNumber();
+ }
+ return success;
}
-void AliRelAlignerKalman::SetTrackParams1( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::AddESDtrack( const AliESDtrack* pTrack )
{
- //Set the trackparameters for track in the first volume at reference
- *fPPoint1 = point;
- *fPPoint1Cov = pointcov;
- *fPDir1 = dir;
- *fPDir1Cov = dircov;
+ //Adds a full track, returns true if results in a new estimate
+ // gets the inner TPC parameters from AliESDTrack::GetInnerParam()
+ // gets the outer ITS parameters from AliESDTrack::GetOuterParam()
+
+ const AliExternalTrackParam* pconstparamsITS = pTrack->GetOuterParam();
+ if (!pconstparamsITS) return kFALSE;
+ const AliExternalTrackParam* pconstparamsTPC = pTrack->GetInnerParam();
+ if (!pconstparamsTPC) return kFALSE;
+
+ //TPC part
+ AliExternalTrackParam paramsTPC = (*pconstparamsTPC);
+ paramsTPC.Rotate(pconstparamsITS->GetAlpha());
+ paramsTPC.PropagateTo(pconstparamsITS->GetX(), fMagField);
+
+ return (AddTrackParams(pconstparamsITS, ¶msTPC));
}
-void AliRelAlignerKalman::SetTrackParams2( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::AddTrackParams( const AliExternalTrackParam* p1, const AliExternalTrackParam* p2 )
{
- //Set the trackparameters for track in the second volume at reference
- *fPPoint2 = point;
- *fPPoint2Cov = pointcov;
- *fPDir2 = dir;
- *fPDir2Cov = dircov;
+ //Update the estimate using new matching tracklets
+
+ if (!SetTrackParams(p1, p2)) return kFALSE;
+ return Update();
}
-void AliRelAlignerKalman::SetTrackParams2b( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::AddCosmicEvent( const AliESDEvent* pEvent )
{
- //Set the trackparameters for second track in the second volume at reference
- *fPPoint2b = point;
- *fPPoint2bCov = pointcov;
- *fPDir2b = dir;
- *fPDir2bCov = dircov;
-}
-
-void AliRelAlignerKalman::SetRefSurface( const Double_t yref )
-{
- //set the reference surface
- fPRefPoint->SetXYZ( 0., 1.*yref, 0. );
- fPRefPointDir->SetXYZ( 0., 1., 0. );
- Float_t refpointcov[6] = { 1., 0., 0.,
- 0., 0.,
- 1. };
- fPRefAliTrackPoint->SetXYZ( 0., 1.*yref, 0., refpointcov );
+ //Add an cosmic with separately tracked ITS and TPC parts, do trackmatching
+
+ fNProcessedEvents++; //update the counter
+
+ Bool_t success=kFALSE;
+ TArrayI trackTArrITS(1);
+ TArrayI trackTArrTPC(1);
+ if (!FindCosmicTrackletNumbersInEvent( trackTArrITS, trackTArrTPC, pEvent )) return kFALSE;
+ SetMagField( pEvent->GetMagneticField() );
+ AliESDtrack* ptrack;
+ const AliExternalTrackParam* pconstparams1;
+ const AliExternalTrackParam* pconstparams2;
+ AliExternalTrackParam params1;
+ AliExternalTrackParam params2;
+
+ ////////////////////////////////
+ for (Int_t i=0;i<trackTArrITS.GetSize();i++)
+ {
+ //ITS track
+ ptrack = pEvent->GetTrack(trackTArrITS[i]);
+ pconstparams1 = ptrack->GetOuterParam();
+ if (!pconstparams1) continue;
+ params1 = *pconstparams1; //make copy to be safe
+
+ //TPC track
+ ptrack = pEvent->GetTrack(trackTArrTPC[i]);
+ pconstparams2 = ptrack->GetInnerParam();
+ if (!pconstparams2) continue;
+ params2 = *pconstparams2; //make copy
+ params2.Rotate(params1.GetAlpha());
+ params2.PropagateTo( params1.GetX(), fMagField );
+
+ if (!SetTrackParams( ¶ms1, ¶ms2 )) continue;
+
+ //do some accounting and update
+ if (Update())
+ success = kTRUE;
+ else
+ continue;
+ }
+ fTimeStamp=pEvent->GetTimeStamp(); //always update timestamp even when no update performed
+ fRunNumber=pEvent->GetRunNumber();
+ return success;
}
-void AliRelAlignerKalman::SetRefSurface( const TVector3& point, const TVector3& dir )
+//______________________________________________________________________________
+void AliRelAlignerKalman::Print(Option_t*) const
{
- //set the reference surface
- *fPRefPoint = point;
- *fPRefPointDir = dir;
+ //Print some useful info
+ Double_t rad2deg = 180./TMath::Pi();
+ printf("\nAliRelAlignerKalman\n");
+ if (fCorrectionMode) printf("(Correction mode)\n");
+ printf(" %i pairs, %i updates, %i outliers,\n", fNTracks, fNUpdates, fNOutliers );
+ printf(" %i TPC matches, %i ITS-TPC matches in %i events\n", fNMatchedTPCtracklets, fNMatchedCosmics, fNProcessedEvents );
+ printf(" psi(x): % .3f ± (%.2f) mrad | % .3f ± (%.2f) deg\n",1e3*(*fPX)(0), 1e3*TMath::Sqrt((*fPXcov)(0,0)),(*fPX)(0)*rad2deg,TMath::Sqrt((*fPXcov)(0,0))*rad2deg);
+ printf(" theta(y): % .3f ± (%.2f) mrad | % .3f ± (%.2f) deg\n",1e3*(*fPX)(1), 1e3*TMath::Sqrt((*fPXcov)(1,1)),(*fPX)(1)*rad2deg,TMath::Sqrt((*fPXcov)(1,1))*rad2deg);
+ printf(" phi(z): % .3f ± (%.2f) mrad | % .3f ± (%.2f) deg\n",1e3*(*fPX)(2), 1e3*TMath::Sqrt((*fPXcov)(2,2)),(*fPX)(2)*rad2deg,TMath::Sqrt((*fPXcov)(2,2))*rad2deg);
+ printf(" x: % .3f ± (%.2f) micron\n", 1e4*(*fPX)(3), 1e4*TMath::Sqrt((*fPXcov)(3,3)));
+ printf(" y: % .3f ± (%.2f) micron\n", 1e4*(*fPX)(4), 1e4*TMath::Sqrt((*fPXcov)(4,4)));
+ printf(" z: % .3f ± (%.2f) micron\n", 1e4*(*fPX)(5), 1e4*TMath::Sqrt((*fPXcov)(5,5)));
+ if (fgkNSystemParams>6) printf(" vd corr % .5g ± (%.2g) [ vd should be %.4g (was %.4g in reco) ]\n", (*fPX)(6), TMath::Sqrt((*fPXcov)(6,6)), (*fPX)(6)*fTPCvd, fTPCvd);
+ if (fgkNSystemParams>7) printf(" t0 % .5g ± (%.2g) us | %.4g ± (%.2g) cm [ t0_real = t0_rec+t0 ]\n",(*fPX)(7), TMath::Sqrt((*fPXcov)(7,7)), fTPCvd*(*fPX)(7), fTPCvd*TMath::Sqrt((*fPXcov)(7,7)));
+ if (fgkNSystemParams>8) printf(" vd/dy % .5f ± (%.2f) (cm/us)/m\n", (*fPX)(8), TMath::Sqrt((*fPXcov)(8,8)));
+ printf(" run: %i, timestamp: %i\n", fRunNumber, fTimeStamp);
+ printf("\n");
+ return;
}
-void AliRelAlignerKalman::SetRefSurface( const AliTrackPoint& point, const Bool_t horizontal )
+//______________________________________________________________________________
+void AliRelAlignerKalman::PrintSystemMatrix()
{
- //set the reference surface
- (*fPRefAliTrackPoint) = point;
-
- (*fPRefPoint)(0) = point.GetX();
- (*fPRefPoint)(1) = point.GetY();
- (*fPRefPoint)(2) = point.GetZ();
-
- if (horizontal)
- {
- (*fPRefPointDir)(0) = 0.;
- (*fPRefPointDir)(1) = 1.;
- (*fPRefPointDir)(2) = 0.;
-
- Float_t refpointcov[6] = { 1., 0., 0.,
- 0., 0.,
- 1. };
- fPRefAliTrackPoint->SetXYZ( point.GetX(), point.GetY() , point.GetZ(), refpointcov );
-
- }
- else
+ //Print the system matrix for this measurement
+ printf("Kalman system matrix:\n");
+ for ( Int_t i=0; i<fgkNMeasurementParams; i++ )
+ {
+ for ( Int_t j=0; j<fgkNSystemParams; j++ )
{
- Double_t angle = point.GetAngle();
- (*fPRefPointDir)(0) = TMath::Cos(angle);
- (*fPRefPointDir)(1) = TMath::Sin(angle);
- (*fPRefPointDir)(2) = 0.;
- *fPRefPointDir = fPRefPointDir->Unit();
- }
+ printf("% -2.2f ", (*fPH)(i,j) );
+ }//for i
+ printf("\n");
+ }//for j
+ printf("\n");
+ return;
}
-void AliRelAlignerKalman::Set3TracksMode( Bool_t mode )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::SetTrackParams( const AliExternalTrackParam* exparam1, const AliExternalTrackParam* exparam2 )
{
- //set the mode where 2 tracklets are allowed in volume 2 (default:TPC)
- //used for alignment with cosmics
+ //Set the parameters, exparam1 will normally be ITS and exparam 2 tht TPC
+
+ fPTrackParamArr1[fTrackInBuffer] = *exparam1;
+ fPTrackParamArr2[fTrackInBuffer] = *exparam2;
+
+ fTrackInBuffer++;
- f3TracksMode = mode;
- if (mode)
- {
- if (fNMeasurementParams!=fgkNMeasurementParams3TrackMode) //do something only if necessary
- {
- fNMeasurementParams = fgkNMeasurementParams3TrackMode;
- delete fPMeasurement;
- delete fPMeasurementCov;
- delete fPH;
- fPMeasurement = new TVectorD( fNMeasurementParams );
- fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
- fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
- }
- }
- else
- {
- if (fNMeasurementParams!=fgkNMeasurementParams2TrackMode)
- {
- fNMeasurementParams = fgkNMeasurementParams2TrackMode;
- delete fPMeasurement;
- delete fPMeasurementCov;
- delete fPH;
- fPMeasurement = new TVectorD( fNMeasurementParams );
- fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
- fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
- }
- }
+ if (fTrackInBuffer == fgkNTracksPerMeasurement)
+ {
+ fTrackInBuffer = 0;
+ return kTRUE;
+ }
+ return kFALSE;
}
-
-Bool_t AliRelAlignerKalman::PrepareUpdate()
+
+//______________________________________________________________________________
+void AliRelAlignerKalman::SetRefSurface( const Double_t radius, const Double_t alpha )
{
- //Cast the extrapolated data (points and directions) into
- //the internal Kalman filter data representation.
- //takes the 3d coordinates of the points of intersection with
- //the reference surface and projects them onto a 2D plane.
- //does the same for angles, combines the result in one vector
-
- if (!FillMeasurement()) return kFALSE;
- if (!FillMeasurementMatrix()) return kFALSE;
- return kTRUE;
+ //sets the reference surface by setting the radius (localx)
+ //and rotation angle wrt the global frame of reference
+ //locally the reference surface becomes a plane with x=r;
+ fLocalX = radius;
+ fAlpha = alpha;
}
+//______________________________________________________________________________
Bool_t AliRelAlignerKalman::Update()
{
- //perform the update - either kalman or calibration
- if (fCalibrationPass) return UpdateCalibration();
- else return UpdateEstimateKalman();
+ //perform the update
+
+ //if (fCalibrationMode) return UpdateCalibration();
+ //if (fFillHistograms)
+ //{
+ // if (!UpdateEstimateKalman()) return kFALSE;
+ // return UpdateCalibration(); //Update histograms only when update ok.
+ //}
+ //else return UpdateEstimateKalman();
+ if (!PrepareMeasurement()) return kFALSE;
+ if (!PrepareSystemMatrix()) return kFALSE;
+ if (!PreparePrediction()) return kFALSE;
+ return UpdateEstimateKalman();
}
+//______________________________________________________________________________
void AliRelAlignerKalman::RotMat( TMatrixD &R, const TVectorD& angles )
{
-//Get Rotation matrix R given the Cardan angles psi, theta, phi (around x, y, z).
- Double_t sinpsi = TMath::Sin(angles(0));
- Double_t sintheta = TMath::Sin(angles(1));
- Double_t sinphi = TMath::Sin(angles(2));
- Double_t cospsi = TMath::Cos(angles(0));
- Double_t costheta = TMath::Cos(angles(1));
- Double_t cosphi = TMath::Cos(angles(2));
-
- R(0,0) = costheta*cosphi;
- R(0,1) = -costheta*sinphi;
- R(0,2) = sintheta;
- R(1,0) = sinpsi*sintheta*cosphi + cospsi*sinphi;
- R(1,1) = -sinpsi*sintheta*sinphi + cospsi*cosphi;
- R(1,2) = -costheta*sinpsi;
- R(2,0) = -cospsi*sintheta*cosphi + sinpsi*sinphi;
- R(2,1) = cospsi*sintheta*sinphi + sinpsi*cosphi;
- R(2,2) = costheta*cospsi;
- return;
+ //Get Rotation matrix R given the Cardan angles psi, theta, phi (around x, y, z).
+ Double_t sinpsi = TMath::Sin(angles(0));
+ Double_t sintheta = TMath::Sin(angles(1));
+ Double_t sinphi = TMath::Sin(angles(2));
+ Double_t cospsi = TMath::Cos(angles(0));
+ Double_t costheta = TMath::Cos(angles(1));
+ Double_t cosphi = TMath::Cos(angles(2));
+
+ R(0,0) = costheta*cosphi;
+ R(0,1) = -costheta*sinphi;
+ R(0,2) = sintheta;
+ R(1,0) = sinpsi*sintheta*cosphi + cospsi*sinphi;
+ R(1,1) = -sinpsi*sintheta*sinphi + cospsi*cosphi;
+ R(1,2) = -costheta*sinpsi;
+ R(2,0) = -cospsi*sintheta*cosphi + sinpsi*sinphi;
+ R(2,1) = cospsi*sintheta*sinphi + sinpsi*cosphi;
+ R(2,2) = costheta*cospsi;
}
-Bool_t AliRelAlignerKalman::FillMeasurement()
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::PrepareMeasurement()
{
- //Take the track parameters and calculate the input to the Kalman filter
+ //Calculate the residuals and their covariance matrix
+
+ for (Int_t i=0;i<fgkNTracksPerMeasurement;i++)
+ {
+ const Double_t* pararr1 = fPTrackParamArr1[i].GetParameter();
+ const Double_t* pararr2 = fPTrackParamArr2[i].GetParameter();
- //Direction vectors
- //Measured is the difference between the polar angles - convert to that
- (*fPMeasurement)(0) = fPDir2->Theta() - fPDir1->Theta();
- (*fPMeasurement)(1) = fPDir2->Phi() - fPDir1->Phi();
+ //Take the track parameters and calculate the input to the Kalman filter
+ Int_t x = i*4;
+ (*fPMeasurement)(x+0) = pararr2[0]-pararr1[0];
+ (*fPMeasurement)(x+1) = pararr2[1]-pararr1[1];
+ (*fPMeasurement)(x+2) = pararr2[2]-pararr1[2];
+ (*fPMeasurement)(x+3) = pararr2[3]-pararr1[3];
+
+ //the covariance
+ const Double_t* parcovarr1 = fPTrackParamArr1[i].GetCovariance();
+ const Double_t* parcovarr2 = fPTrackParamArr2[i].GetCovariance();
+ (*fPMeasurementCov)(x+0,x+0)=parcovarr1[0];
+ (*fPMeasurementCov)(x+0,x+1)=parcovarr1[1];
+ (*fPMeasurementCov)(x+0,x+2)=parcovarr1[3];
+ (*fPMeasurementCov)(x+0,x+3)=parcovarr1[6];
+ (*fPMeasurementCov)(x+1,x+0)=parcovarr1[1];
+ (*fPMeasurementCov)(x+1,x+1)=parcovarr1[2];
+ (*fPMeasurementCov)(x+1,x+2)=parcovarr1[4];
+ (*fPMeasurementCov)(x+1,x+3)=parcovarr1[7];
+ (*fPMeasurementCov)(x+2,x+0)=parcovarr1[3];
+ (*fPMeasurementCov)(x+2,x+1)=parcovarr1[4];
+ (*fPMeasurementCov)(x+2,x+2)=parcovarr1[5];
+ (*fPMeasurementCov)(x+2,x+3)=parcovarr1[8];
+ (*fPMeasurementCov)(x+3,x+0)=parcovarr1[6];
+ (*fPMeasurementCov)(x+3,x+1)=parcovarr1[7];
+ (*fPMeasurementCov)(x+3,x+2)=parcovarr1[8];
+ (*fPMeasurementCov)(x+3,x+3)=parcovarr1[9];
+ (*fPMeasurementCov)(x+0,x+0)+=parcovarr2[0];
+ (*fPMeasurementCov)(x+0,x+1)+=parcovarr2[1];
+ (*fPMeasurementCov)(x+0,x+2)+=parcovarr2[3];
+ (*fPMeasurementCov)(x+0,x+3)+=parcovarr2[6];
+ (*fPMeasurementCov)(x+1,x+0)+=parcovarr2[1];
+ (*fPMeasurementCov)(x+1,x+1)+=parcovarr2[2];
+ (*fPMeasurementCov)(x+1,x+2)+=parcovarr2[4];
+ (*fPMeasurementCov)(x+1,x+3)+=parcovarr2[7];
+ (*fPMeasurementCov)(x+2,x+0)+=parcovarr2[3];
+ (*fPMeasurementCov)(x+2,x+1)+=parcovarr2[4];
+ (*fPMeasurementCov)(x+2,x+2)+=parcovarr2[5];
+ (*fPMeasurementCov)(x+2,x+3)+=parcovarr2[8];
+ (*fPMeasurementCov)(x+3,x+0)+=parcovarr2[6];
+ (*fPMeasurementCov)(x+3,x+1)+=parcovarr2[7];
+ (*fPMeasurementCov)(x+3,x+2)+=parcovarr2[8];
+ (*fPMeasurementCov)(x+3,x+3)+=parcovarr2[9];
- //Points
- //Measured is the distance in XZ plane at Y of the reference point
- (*fPMeasurement)(2) = fPPoint2->X() - fPPoint1->X();
- (*fPMeasurement)(3) = fPPoint2->Z() - fPPoint1->Z();
-
- //if 3 track mode set, set also the stuff for 2nd TPC track
- if (f3TracksMode)
- {
- (*fPMeasurement)(4) = fPDir2b->Theta() - fPDir1->Theta();
- (*fPMeasurement)(5) = fPDir2b->Phi() - fPDir1->Phi();
- (*fPMeasurement)(6) = fPPoint2b->X() - fPPoint1->X();
- (*fPMeasurement)(7) = fPPoint2b->Z() - fPPoint1->Z();
- }
+ fNTracks++; //count added track sets
+ }
+ //if (fApplyCovarianceCorrection)
+ // *fPMeasurementCov += *fPMeasurementCovCorr;
+ return kTRUE;
+}
- //Fill the covariance
- if (fFixedMeasurementCovariance) return kTRUE;
- //the dirs
- GetThetaPhiCov( *fPDir1ThetaPhiCov, *fPDir1, *fPDir1Cov );
- GetThetaPhiCov( *fPDir2ThetaPhiCov, *fPDir2, *fPDir2Cov );
- fPMeasurementCov->SetSub( 0, (*fPDir1ThetaPhiCov) + (*fPDir2ThetaPhiCov) );
-
- //the points
- (*fPMeasurementCov)(2,2) = (*fPPoint1Cov)(0,0)+(*fPPoint2Cov)(0,0);
- (*fPMeasurementCov)(2,3) = (*fPPoint1Cov)(0,2)+(*fPPoint2Cov)(0,2);
- (*fPMeasurementCov)(3,2) = (*fPPoint1Cov)(2,0)+(*fPPoint2Cov)(2,0);
- (*fPMeasurementCov)(3,3) = (*fPPoint1Cov)(2,2)+(*fPPoint2Cov)(2,2);
-
- //if 3 track mode set, set also the stuff for 2nd TPC track
- if (f3TracksMode)
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::PrepareSystemMatrix()
+{
+ //Calculate the system matrix for the Kalman filter
+ //approximate the system using as reference the track in the first volume
+
+ TVectorD z1( fgkNMeasurementParams );
+ TVectorD z2( fgkNMeasurementParams );
+ TVectorD x1( fgkNSystemParams );
+ TVectorD x2( fgkNSystemParams );
+ //get the derivatives
+ for ( Int_t i=0; i<fgkNSystemParams; i++ )
+ {
+ x1 = *fPX;
+ x2 = *fPX;
+ x1(i) = x1(i) - fDelta[i]/(2.0);
+ x2(i) = x2(i) + fDelta[i]/(2.0);
+ if (!PredictMeasurement( z1, x1 )) return kFALSE;
+ if (!PredictMeasurement( z2, x2 )) return kFALSE;
+ for (Int_t j=0; j<fgkNMeasurementParams; j++ )
{
- GetThetaPhiCov( *fPDir2bThetaPhiCov, *fPDir2b, *fPDir2bCov );
- fPMeasurementCov->SetSub( 4, (*fPDir1ThetaPhiCov) + (*fPDir2bThetaPhiCov) );
- (*fPMeasurementCov)(6,6) = (*fPPoint1Cov)(0,0)+(*fPPoint2bCov)(0,0);
- (*fPMeasurementCov)(6,7) = (*fPPoint1Cov)(0,2)+(*fPPoint2bCov)(0,2);
- (*fPMeasurementCov)(7,6) = (*fPPoint1Cov)(2,0)+(*fPPoint2bCov)(2,0);
- (*fPMeasurementCov)(7,7) = (*fPPoint1Cov)(2,2)+(*fPPoint2bCov)(2,2);
+ (*fPH)(j,i) = ( z2(j)-z1(j) ) / fDelta[i];
}
- return kTRUE;
+ }
+ return kTRUE;
}
-Bool_t AliRelAlignerKalman::FillMeasurementMatrix()
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::PreparePrediction()
{
- //Calculate the system matrix for the Kalman filter
- //approximate the system using as reference the track in the first volume
-
- Double_t delta = 1.e-8;
- TVectorD z1( fNMeasurementParams );
- TVectorD z2( fNMeasurementParams );
- TVectorD x1( *fPX );
- TVectorD x2( *fPX );
- TMatrixD D( fNMeasurementParams, 1 );
- for ( Int_t i=0; i<fNSystemParams; i++ )
- {
- x1 = *fPX;
- x2 = *fPX;
- x1(i) -= delta;
- x2(i) += delta;
- if (!PredictMeasurement( z1, x1 )) return kFALSE;
- if (!PredictMeasurement( z2, x2 )) return kFALSE;
- for (Int_t j=0; j<fNMeasurementParams; j++ )
- D.GetMatrixArray()[j] = (z2.GetMatrixArray()[j]-z1.GetMatrixArray()[j])/(2.*delta);
- fPH->SetSub( 0, i, D );
- }
- return kTRUE;
+ //Prepare the prediction of the measurement using state vector
+ return PredictMeasurement( (*fPMeasurementPrediction), (*fPX) );
}
+//______________________________________________________________________________
Bool_t AliRelAlignerKalman::PredictMeasurement( TVectorD& pred, const TVectorD& state )
{
- // Implements a system model for the Kalman fit
- // pred is [dtheta, dphi, dx, dz, [dtheta', dphi', dx', dz'] ] - second part is for 2nd TPC track in cosmics
- // state is [psi,theta,phi,x,y,z,driftTPC,offsetTPC]
-
- TVector3 newPoint = *fPPoint1;
- TVector3 newDir = *fPDir1;
- TVector3 shift;
- //TPC drift correction
- newDir(2) *= (1.+state(6));
- newPoint(2) *= (1.+state(6));
- //TPC offset
- if (newPoint(2)>0) newPoint(2) += state(7);
- else newPoint(2) -= state(7);
- //rotate
- TMatrixD rotmat(3,3);
- RotMat( rotmat, state );
- newDir = rotmat * newDir;
- newPoint = rotmat * newPoint;
- //shift
- shift(0) = state(3);
- shift(1) = state(4);
- shift(2) = state(5);
- newPoint += shift;
- //Predicted measurement
- if (!IntersectionLinePlane( newPoint, newPoint, newDir, *fPRefPoint, *fPVec010 )) return kFALSE;
- pred(0) = newDir.Theta() - fPDir1->Theta();
- pred(1) = newDir.Phi() - fPDir1->Phi();
- pred(2) = newPoint(0) - fPPoint1->X();
- pred(3) = newPoint(2) - fPPoint1->Z();
-
- if (f3TracksMode)
+ // Implements a system model for the Kalman fit
+ // pred is [dy,dz,dsinphi,dtgl]
+ // state is [psi,theta,phi,x,y,z,driftTPC,offsetTPC]
+ // note: the measurement is in a local frame, so the prediction also has to be
+ // note: state is the misalignment in global reference system
+
+ if (fCorrectionMode)
+ {
+ for (Int_t i=0;i<fgkNTracksPerMeasurement;i++)
{
- //Do the same for second TPC track
- //should be the same as the first TPC track
- pred(4) = pred(0);
- pred(5) = pred(1);
- pred(6) = pred(2);
- pred(7) = pred(3);
+ AliExternalTrackParam track(fPTrackParamArr2[i]); //make a copy track
+ if (!CorrectTrack( &track, state )) return kFALSE; //predict what the ideal track would be by applying correction
+
+ const Double_t* oldparam = fPTrackParamArr2[i].GetParameter();
+ const Double_t* newparam = track.GetParameter();
+
+ Int_t x = 4*i;
+ //calculate the predicted residual
+ pred(x+0) = oldparam[0] - newparam[0];
+ pred(x+1) = oldparam[1] - newparam[1];
+ pred(x+2) = oldparam[2] - newparam[2];
+ pred(x+3) = oldparam[3] - newparam[3];
+ return kTRUE;
}
- return kTRUE;
+ }
+ else
+ {
+ for (Int_t i=0;i<fgkNTracksPerMeasurement;i++)
+ {
+ AliExternalTrackParam track(fPTrackParamArr1[i]); //make a copy track
+ if (!MisalignTrack( &track, state )) return kFALSE; //predict what the measured track would be by applying misalignment
+
+ const Double_t* oldparam = fPTrackParamArr1[i].GetParameter();
+ const Double_t* newparam = track.GetParameter();
+
+ Int_t x = 4*i;
+ //calculate the predicted residual
+ pred(x+0) = newparam[0] - oldparam[0];
+ pred(x+1) = newparam[1] - oldparam[1];
+ pred(x+2) = newparam[2] - oldparam[2];
+ pred(x+3) = newparam[3] - oldparam[3];
+ return kTRUE;
+ }
+ }
+ return kFALSE;
}
+//______________________________________________________________________________
Bool_t AliRelAlignerKalman::UpdateEstimateKalman()
{
- //Kalman estimation of noisy constants: in the model A=1
- //The arguments are (following the usual convention):
- // x - the state vector (parameters)
- // P - the state covariance matrix (parameter errors)
- // z - measurement vector
- // R - measurement covariance matrix
- // H - measurement model matrix ( z = Hx + v ) v being measurement noise (error fR)
- TVectorD *x = fPX;
- TMatrixDSym *P = fPXcov;
- TVectorD *z = fPMeasurement;
- TMatrixDSym *R = fPMeasurementCov;
- TMatrixD *H = fPH;
-
- TMatrixDSym I(TMatrixDSym::kUnit, *P); //unit matrix
-
- //predict the state
- *P = *P + fQ*I; //add some process noise (diagonal)
-
- // update prediction with measurement
- // calculate Kalman gain
- // K = PH/(HPH+R)
- TMatrixD PHT( *P, TMatrixD::kMultTranspose, *H ); //common factor (used twice)
- TMatrixD HPHT( *H, TMatrixD::kMult, PHT );
- HPHT += *R;
- TMatrixD K(PHT, TMatrixD::kMult, HPHT.Invert()); //compute K
-
- // update the state and its covariance matrix
- TVectorD xupdate(*x);
- TVectorD Hx(*z);
- PredictMeasurement( Hx, *x );
- xupdate = K*((*z)-Hx);
-
- //SIMPLE OUTLIER REJECTION
- if (
- (TMath::Abs(xupdate(0)) > fOutRejSigmas*TMath::Sqrt((*P)(0,0))) ||
- (TMath::Abs(xupdate(1)) > fOutRejSigmas*TMath::Sqrt((*P)(1,1))) ||
- (TMath::Abs(xupdate(2)) > fOutRejSigmas*TMath::Sqrt((*P)(2,2))) ||
- (TMath::Abs(xupdate(3)) > fOutRejSigmas*TMath::Sqrt((*P)(3,3))) ||
- (TMath::Abs(xupdate(4)) > fOutRejSigmas*TMath::Sqrt((*P)(4,4))) ||
- (TMath::Abs(xupdate(5)) > fOutRejSigmas*TMath::Sqrt((*P)(5,5))) ||
- (TMath::Abs(xupdate(6)) > fOutRejSigmas*TMath::Sqrt((*P)(6,6))) ||
- (TMath::Abs(xupdate(7)) > fOutRejSigmas*TMath::Sqrt((*P)(7,7)))
- )
- {
- fNOutliers++;
- return kFALSE;
- }
-
- *x += xupdate;
- TMatrixD KH( K, TMatrixD::kMult, *H );
- TMatrixD IKH(I);
- IKH = I - KH;
- TMatrixD IKHP( IKH, TMatrixD::kMult, *P ); // (I-KH)P
- TMatrixDSym_from_TMatrixD( *P, IKHP );
- fNUpdates++;
- return kTRUE;
+ //Kalman estimation of noisy constants: in the model A=1
+ //The arguments are (following the usual convention):
+ // fPX - the state vector (parameters)
+ // fPXcov - the state covariance matrix (parameter errors)
+ // fPMeasurement - measurement vector
+ // fPMeasurementCov - measurement covariance matrix
+ // fPH - measurement model matrix ( fPMeasurement = Hx + v ) v being measurement noise (error fR)
+
+ TMatrixDSym identity(TMatrixDSym::kUnit, (*fPXcov)); //unit matrix
+
+ //predict the state
+ //(*fPXcov) = (*fPXcov) + fQ*identity; //add some process noise (diagonal)
+
+ // update prediction with measurement
+ // calculate Kalman gain
+ // K = PH/(HPH+fPMeasurementCov)
+ TMatrixD pht( (*fPXcov), TMatrixD::kMultTranspose, (*fPH) ); //common factor (used twice)
+ TMatrixD hpht( (*fPH), TMatrixD::kMult, pht );
+ hpht += (*fPMeasurementCov);
+
+ //shit happens so protect yourself!
+// if (fNumericalParanoia)
+// {
+// TDecompLU lu(hpht);
+// if (lu.Condition() > 1e12) return kFALSE;
+// lu.Invert(hpht);
+// }
+// else
+// {
+ Double_t det;
+ hpht.InvertFast(&det); //since the matrix is small...
+ if (det < 2e-55) return kFALSE; //we need some sort of protection even in this case....
+// }
+ //printf("KalmanUpdate: det(hpht): %.4g\n",det);
+
+ TMatrixD k(pht, TMatrixD::kMult, hpht ); //compute K (hpht is already inverted)
+
+ // update the state and its covariance matrix
+ TVectorD xupdate(fgkNSystemParams);
+ xupdate = k*((*fPMeasurement)-(*fPMeasurementPrediction));
+
+ //SIMPLE OUTLIER REJECTION
+ if ( IsOutlier( xupdate, (*fPXcov) ) && fRejectOutliers )
+ {
+ fNOutliers++;
+ return kFALSE;
+ }
+
+ TMatrixD kh( k, TMatrixD::kMult, (*fPH) );
+ TMatrixD ikh(fgkNSystemParams,fgkNSystemParams); //this is because for some reason TMatrixD::kAdd didn't work
+ ikh = identity - kh;
+ TMatrixD ikhp( ikh, TMatrixD::kMult, (*fPXcov) ); // (identity-KH)fPXcov
+ if (!IsPositiveDefinite(ikhp)) return kFALSE;
+
+ (*fPX) += xupdate;
+ TMatrixDSymFromTMatrixD( (*fPXcov), ikhp ); //make the matrix completely symetrical
+
+ fNUpdates++;
+
+ return kTRUE;
}
-void AliRelAlignerKalman::TMatrixDSym_from_TMatrixD( TMatrixDSym& matsym, const TMatrixD& mat )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::IsOutlier( const TVectorD& update, const TMatrixDSym& covmatrix )
{
- //Produce a valid symmetric matrix out of a TMatrixD
-
- //not very efficient, diagonals are computer twice, but who cares
- for (Int_t i=0; i<mat.GetNcols(); i++)
- {
- for (Int_t j=i; j<mat.GetNcols(); j++)
- {
- Double_t average = (mat(i,j)+mat(j,i))/2.;
- matsym(i,j)=average;
- matsym(j,i)=average;
- }
- }
- return;
+ //check whether an update is an outlier given the covariance matrix of the fit
+
+ Bool_t is=kFALSE;
+ for (Int_t i=0;i<fgkNSystemParams;i++)
+ {
+ if (covmatrix(i,i)<0.) return kTRUE; //if cov matrix has neg diagonals something went wrong
+ is = (is) || (TMath::Abs(update(i)) > fOutRejSigmas*TMath::Sqrt((covmatrix)(i,i)));
+ }
+ return is;
}
-void AliRelAlignerKalman::GetThetaPhiCov( TMatrixDSym& cov, const TVector3& vec, const TMatrixDSym& vecCov )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::IsPositiveDefinite( const TMatrixD& mat ) const
{
- //Given the covariance matrix of a vector in euclid.space
- //give cov matrix of the 2 spherical angles
- const Double_t delta = 1e-8;
- TVector3 vec1;
- TVector3 vec2;
- TMatrixD T(2,3);
- for (Int_t i=0; i<3; i++)
- {
- vec1 = vec;
- vec2 = vec;
- vec1(i) -= delta/2.;
- vec2(i) += delta/2.;
- T(0,i) = (vec2.Theta() - vec1.Theta())/delta;
- T(1,i) = (vec2.Phi() - vec1.Phi())/delta;
- }
- TMatrixD tmp( T, TMatrixD::kMult, vecCov );
- TMatrixD nscov( tmp, TMatrixD::kMultTranspose, T );
- cov(0,0) = nscov(0,0); cov(0,1) = nscov(0,1);
- cov(1,0) = nscov(0,1); cov(1,1) = nscov(1,1);
- return;
+ //check for positive definiteness
+
+ for (Int_t i=0; i<mat.GetNcols(); i++)
+ {
+ if (mat(i,i)<=0.) return kFALSE;
+ }
+
+ if (!fNumericalParanoia) return kTRUE;
+
+ TDecompLU lu(mat);
+ return (lu.Decompose());
}
-Bool_t AliRelAlignerKalman::IntersectionLinePlane( TVector3& intersection, const TVector3& linebase, const TVector3& linedir, const TVector3& planepoint, const TVector3& planenormal )
+//______________________________________________________________________________
+void AliRelAlignerKalman::TMatrixDSymFromTMatrixD( TMatrixDSym& matsym, const TMatrixD& mat )
{
- //calculate the intersection point between a straight line and a plane
- //plane is defined with a point in it and a normal, line has a point and direction
- if (planenormal==TVector3(0,1,0))
- {
- if (linedir(1)==0) return kFALSE;
- Double_t t = ( planepoint(1) - linebase(1) ) / linedir(1);
- intersection = linebase + t*linedir;
- return kTRUE;
- }
- else
+ //Produce a valid symmetric matrix out of an almost symmetric TMatrixD
+
+ for (Int_t i=0; i<mat.GetNcols(); i++)
+ {
+ matsym(i,i) = mat(i,i); //copy diagonal
+ for (Int_t j=i+1; j<mat.GetNcols(); j++)
{
- Double_t dirdotn = linedir.Dot(planenormal);
- if (dirdotn==0) return kFALSE;
- Double_t t = ( planepoint.Dot(planenormal) - linebase.Dot(planenormal) ) / dirdotn;
- intersection = linebase + t*linedir;
- return kTRUE;
+ //copy the rest
+ Double_t average = (mat(i,j)+mat(j,i))/2.;
+ matsym(i,j)=average;
+ matsym(j,i)=average;
}
+ }
+ matsym.MakeValid();
+ return;
}
+//______________________________________________________________________________
void AliRelAlignerKalman::Angles( TVectorD &angles, const TMatrixD &rotmat )
{
-//Calculate the Cardan angles (psi,theta,phi) from rotation matrix
-//b = R*a
-//
- angles(0) = TMath::ATan2( -rotmat(1,2), rotmat(2,2) );
- angles(1) = TMath::ASin( rotmat(0,2) );
- angles(2) = TMath::ATan2( -rotmat(0,1), rotmat(0,0) );
- return;
+ //Calculate the Cardan angles (psi,theta,phi) from rotation matrix
+ //b = R*a
+ angles(0) = TMath::ATan2( -rotmat(1,2), rotmat(2,2) );
+ angles(1) = TMath::ASin( rotmat(0,2) );
+ angles(2) = TMath::ATan2( -rotmat(0,1), rotmat(0,0) );
+ return;
}
+//______________________________________________________________________________
void AliRelAlignerKalman::PrintCorrelationMatrix()
{
- //Print the correlation matrix for the fitted parameters
-
- for ( Int_t j=0; j<fNSystemParams; j++ )
+ //Print the correlation matrix for the fitted parameters
+ printf("Correlation matrix for system parameters:\n");
+ for ( Int_t i=0; i<fgkNSystemParams; i++ )
+ {
+ for ( Int_t j=0; j<i+1; j++ )
{
- for ( Int_t i=0; i<fNSystemParams; i++ )
- {
- printf("%1.2f ", (*fPXcov)(i,j)/TMath::Sqrt( (*fPXcov)(i,i) * (*fPXcov)(j,j) ) );
- }//for i
- printf("\n");
+ if ((*fPXcov)(i,i)==0. || (*fPXcov)(j,j)==0.) printf(" NaN ");
+ else
+ printf("% -1.3f ", (*fPXcov)(i,j)/TMath::Sqrt( (*fPXcov)(i,i) * (*fPXcov)(j,j) ) );
}//for j
printf("\n");
- return;
+ }//for i
+ printf("\n");
+ return;
}
-Bool_t AliRelAlignerKalman::FindCosmicInEvent( AliESDEvent* pEvent )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::FindCosmicTrackletNumbersInEvent( TArrayI& outITSindexTArr, TArrayI& outTPCindexTArr, const AliESDEvent* pEvent )
{
- //Find track point arrays belonging to one cosmic in a separately tracked ESD
- //and put them in the apropriate data members
-
- //Sanity cuts on tracks + check which tracks are ITS which are TPC
- Int_t ntracks = pEvent->GetNumberOfTracks(); //printf("number of tracks in event: %i\n", ntracks);
- if(ntracks<2) return kFALSE;
- Float_t* phiArr = new Float_t[ntracks];
- Float_t* thetaArr = new Float_t[ntracks];
- Double_t* distanceFromVertexArr = new Double_t[ntracks];
- Int_t* goodtracksArr = new Int_t[ntracks];
- Int_t* ITStracksArr = new Int_t[ntracks];
- Int_t* TPCtracksArr = new Int_t[ntracks];
- Int_t* nPointsArr = new Int_t[ntracks];
- Int_t nITStracks = 0;
- Int_t nTPCtracks = 0;
- Int_t nGoodTracks = 0;
- AliESDtrack* pTrack = NULL;
-
- const AliESDVertex* pVertex = pEvent->GetVertex();
- Double_t vertexposition[3];
- pVertex->GetXYZ(vertexposition);
-
- Double_t magfield = pEvent->GetMagneticField();
-
- //select sane tracks
- for (Int_t itrack=0; itrack < ntracks; itrack++)
- {
- pTrack = pEvent->GetTrack(itrack);
- if (!pTrack) {cout<<"no track!"<<endl;continue;}
- if(pTrack->GetNcls(0)+pTrack->GetNcls(1) < fMinPointsVol1) continue;
- Float_t phi = pTrack->GetAlpha()+TMath::ASin(pTrack->GetSnp());
- Float_t theta = 0.5*TMath::Pi()-TMath::ATan(pTrack->GetTgl());
- //printf("phi: %4.2f theta: %4.2f\n", phi, theta);
- if(fCuts)
- {
- if(pTrack->GetP()<fMinMom || pTrack->GetP()>fMaxMom) continue;
- Float_t abssinphi = TMath::Abs(TMath::Sin(phi));
- if(abssinphi<fMinAbsSinPhi || abssinphi>fMaxAbsSinPhi) continue;
- Float_t sintheta = TMath::Sin(theta);
- if(sintheta<fMinSinTheta || sintheta>fMaxSinTheta) continue;
- }
- goodtracksArr[nGoodTracks]=itrack;
- phiArr[nGoodTracks]=phi;
- thetaArr[nGoodTracks]=theta;
-
- pTrack->RelateToVertex( pVertex, magfield, 10000. );
- Double_t trackposition[3];
- pTrack->GetXYZ( trackposition );
- distanceFromVertexArr[nGoodTracks] =
- TMath::Sqrt((trackposition[0]-vertexposition[0])*(trackposition[0]-vertexposition[0])
- + (trackposition[1]-vertexposition[1])*(trackposition[1]-vertexposition[1])
- + (trackposition[2]-vertexposition[2])*(trackposition[2]-vertexposition[2]));
-
- //check if track is ITS or TPC
- if ( ((pTrack->GetStatus()&AliESDtrack::kITSin)>0)&&
- !((pTrack->GetStatus()&AliESDtrack::kTPCin)>0) )
- {
- ITStracksArr[nITStracks] = nGoodTracks;
- nITStracks++;
- }
-
- if ( ((pTrack->GetStatus()&AliESDtrack::kTPCin)>0)&&
- !((pTrack->GetStatus()&AliESDtrack::kITSin)>0) )
- {
- TPCtracksArr[nTPCtracks] = nGoodTracks;
- nTPCtracks++;
- }
-
- nGoodTracks++;
- }//for itrack - sanity cuts
-
- //printf("there are good tracks, %d in ITS and %d TPC.\n", nITStracks, nTPCtracks);
-
- if( nITStracks < 2 || nTPCtracks < 2 )
+ //Find matching track segments in an event with tracks in TPC and ITS(standalone)
+
+ //Sanity cuts on tracks + check which tracks are ITS which are TPC
+ Int_t ntracks = pEvent->GetNumberOfTracks(); ////printf("number of tracks in event: %i\n", ntracks);
+ fMagField = pEvent->GetMagneticField();
+ if (ntracks<2)
+ {
+ //printf("TrackFinder: less than 2 tracks!\n");
+ return kFALSE;
+ }
+ Float_t* phiArr = new Float_t[ntracks];
+ Float_t* thetaArr = new Float_t[ntracks];
+ Int_t* goodtracksArr = new Int_t[ntracks];
+ Int_t* candidateTPCtracksArr = new Int_t[ntracks];
+ Int_t* matchedITStracksArr = new Int_t[ntracks];
+ Int_t* matchedTPCtracksArr = new Int_t[ntracks];
+ Int_t* tracksArrITS = new Int_t[ntracks];
+ Int_t* tracksArrTPC = new Int_t[ntracks];
+ Int_t* nPointsArr = new Int_t[ntracks];
+ Int_t nITStracks = 0;
+ Int_t nTPCtracks = 0;
+ Int_t nGoodTracks = 0;
+ Int_t nCandidateTPCtracks = 0;
+ Int_t nMatchedITStracks = 0;
+ AliESDtrack* pTrack = NULL;
+ Bool_t foundMatchTPC = kFALSE;
+
+ //select and clasify tracks
+ for (Int_t itrack=0; itrack < ntracks; itrack++)
+ {
+ pTrack = pEvent->GetTrack(itrack);
+ if (!pTrack)
{
- delete [] goodtracksArr; goodtracksArr=0;
- delete [] ITStracksArr; ITStracksArr=0;
- delete [] TPCtracksArr; TPCtracksArr=0;
- delete [] nPointsArr; nPointsArr=0;
- delete [] phiArr; phiArr=0;
- delete [] thetaArr; thetaArr=0;
- delete [] distanceFromVertexArr; distanceFromVertexArr=0;
- return kFALSE;
+ //std::cout<<"no track!"<<std::endl;
+ continue;
}
-
- //find matching in TPC
- Float_t min = 10000000.;
- Int_t TPCgood1 = -1, TPCgood2 = -1;
- for(Int_t itr1=0; itr1<nTPCtracks; itr1++)
+ if (fCuts)
{
- for(Int_t itr2=itr1+1; itr2<nTPCtracks; itr2++)
- {
- Float_t deltatheta = TMath::Abs(TMath::Pi()-thetaArr[TPCtracksArr[itr1]]-thetaArr[TPCtracksArr[itr2]]);
- if(deltatheta > fMaxMatchingAngle) continue;
- Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[TPCtracksArr[itr1]]-phiArr[TPCtracksArr[itr2]])-TMath::Pi());
- if(deltaphi > fMaxMatchingAngle) continue;
- //printf("TPC: %f %f %f %f\n",deltaphi,deltatheta,thetaArr[TPCtracksArr[itr1]],thetaArr[TPCtracksArr[itr2]]);
- if(deltatheta+deltaphi<min) //only the best matching pair
- {
- min=deltatheta+deltaphi;
- TPCgood1 = TPCtracksArr[itr1]; //store the index of track in goodtracksArr[]
- TPCgood2 = TPCtracksArr[itr2];
- }
- }
+ if (pTrack->GetP()<fMinMom || pTrack->GetP()>fMaxMom) continue;
}
- if (TPCgood1 < 0) //no dubble cosmic track
+ goodtracksArr[nGoodTracks]=itrack;
+ Float_t phi = pTrack->GetAlpha()+TMath::ASin(pTrack->GetSnp());
+ Float_t theta = 0.5*TMath::Pi()-TMath::ATan(pTrack->GetTgl());
+ phiArr[nGoodTracks]=phi;
+ thetaArr[nGoodTracks]=theta;
+
+ //check if track is ITS
+ Int_t nClsITS = pTrack->GetNcls(0);
+ Int_t nClsTPC = pTrack->GetNcls(1);
+ if ( ((pTrack->GetStatus()&AliESDtrack::kITSout)>0)&&
+ !((pTrack->GetStatus()&AliESDtrack::kTPCin)>0)&&
+ !(nClsITS<fMinPointsVol1) ) //enough points
{
- delete [] goodtracksArr; goodtracksArr=0;
- delete [] ITStracksArr; ITStracksArr=0;
- delete [] TPCtracksArr; TPCtracksArr=0;
- delete [] nPointsArr; nPointsArr=0;
- delete [] phiArr; phiArr=0;
- delete [] thetaArr; thetaArr=0;
- delete [] distanceFromVertexArr; distanceFromVertexArr=0;
- return kFALSE;
+ tracksArrITS[nITStracks] = nGoodTracks;
+ nITStracks++;
+ nGoodTracks++;
+ continue;
}
- //in ITS find 2 tracks that best match the found TPC cosmic
- Double_t min1 = 10000000.;
- Double_t min2 = 10000000.;
- Int_t ITSgood1 = -1, ITSgood2 = -1;
- for(Int_t itr1=0; itr1<nITStracks; itr1++)
- {
- if(distanceFromVertexArr[ITStracksArr[itr1]]>fMaxMatchingDistance) continue;
- Float_t deltatheta = TMath::Abs(TMath::Pi()-thetaArr[ITStracksArr[itr1]]-thetaArr[TPCgood1]);
- if(deltatheta > fMaxMatchingAngle) deltatheta = TMath::Abs( deltatheta - TMath::Pi() );
- if(deltatheta > fMaxMatchingAngle) continue;
- Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[ITStracksArr[itr1]]-phiArr[TPCgood1])-TMath::Pi());
- if(deltaphi > fMaxMatchingAngle) deltaphi = TMath::Abs( deltaphi - TMath::Pi() );
- if(deltaphi > fMaxMatchingAngle) continue;
- //printf("ITS %i dtheta, dphi, vrtx: %.4f, %.4f, %.4f\n",ITStracksArr[itr1], deltatheta, deltaphi,distanceFromVertexArr[ITStracksArr[itr1]]);
- if(deltatheta+deltaphi<min1) //only the best one
- {
- min1=deltatheta+deltaphi;
- //ITSgood2 = ITSgood1;
- ITSgood1 = ITStracksArr[itr1];
- continue;
- }
- if(deltatheta+deltaphi<min2) //the second best
- {
- min2=deltatheta+deltaphi;
- ITSgood2 = ITStracksArr[itr1];
- continue;
- }
- }
- if (ITSgood2 < 0) //no ITS cosmic track
+ //check if track is TPC
+ if ( ((pTrack->GetStatus()&AliESDtrack::kTPCin)>0)&&
+ !(nClsTPC<fMinPointsVol2) ) //enough points
{
- delete [] goodtracksArr; goodtracksArr=0;
- delete [] ITStracksArr; ITStracksArr=0;
- delete [] TPCtracksArr; TPCtracksArr=0;
- delete [] nPointsArr; nPointsArr=0;
- delete [] phiArr; phiArr=0;
- delete [] thetaArr; thetaArr=0;
- delete [] distanceFromVertexArr; distanceFromVertexArr=0;
- return kFALSE;
+ tracksArrTPC[nTPCtracks] = nGoodTracks;
+ nTPCtracks++;
+ nGoodTracks++;
+ //printf("tracksArrTPC[%d]=%d, goodtracksArr[%d]=%d\n",nTPCtracks-1,tracksArrTPC[nTPCtracks-1],nGoodTracks-1,goodtracksArr[nGoodTracks-1]);
+ continue;
}
+ }//for itrack - selection fo tracks
+
+ //printf("TrackFinder: %d ITS | %d TPC out of %d tracks in event\n", nITStracks,nTPCtracks,ntracks);
+
+ if ( nITStracks < 1 || nTPCtracks < 1 )
+ {
+ delete [] phiArr;
+ delete [] thetaArr;
+ delete [] goodtracksArr;
+ delete [] matchedITStracksArr;
+ delete [] candidateTPCtracksArr;
+ delete [] matchedTPCtracksArr;
+ delete [] tracksArrITS;
+ delete [] tracksArrTPC;
+ delete [] nPointsArr;
+ return kFALSE;
+ }
- //we found a cosmic
- fNMatchedCosmics++;
-
- //////////////////////////////////////////////////////////////////////////////////////
- // convert indexes from local goodtrackarrays to global track index
- TPCgood1 = goodtracksArr[TPCgood1];
- TPCgood2 = goodtracksArr[TPCgood2];
- ITSgood1 = goodtracksArr[ITSgood1];
- ITSgood2 = goodtracksArr[ITSgood2];
- /////////////////////////////////////////////////////////////////////////////////////
-
- AliESDtrack * pTPCtrack1 = pEvent->GetTrack(TPCgood1);
- AliESDtrack * pTPCtrack2 = pEvent->GetTrack(TPCgood2);
- AliESDtrack * pITStrack1 = pEvent->GetTrack(ITSgood1);
- AliESDtrack * pITStrack2 = pEvent->GetTrack(ITSgood2);
- const AliTrackPointArray* pTPCArray1 = pTPCtrack1->GetTrackPointArray();
- const AliTrackPointArray* pTPCArray2 = pTPCtrack2->GetTrackPointArray();
- const AliTrackPointArray* pITSArray1 = pITStrack1->GetTrackPointArray();
- const AliTrackPointArray* pITSArray2 = pITStrack2->GetTrackPointArray();
-
- AliTrackPointArray* pfullITStrackArray = new AliTrackPointArray(1);
- JoinTrackArrays( pfullITStrackArray, pITSArray1, pITSArray2 );
-
- //cout<<"selected tracks: TPC: "<<TPCgood1<<" "<<TPCgood2<<" ITS: "<<ITSgood1<<" "<<ITSgood2<<endl;
-
- //Fill the final trackpointarrays
- if (!ExtractSubTrackPointArray( fPTrackPointArray1, fPVolIDArray1, pfullITStrackArray, 1, 6 )) return kFALSE;
- if (!ExtractSubTrackPointArray( fPTrackPointArray2, fPVolIDArray2, pTPCArray1, 7, 8 )) return kFALSE;
- if (!ExtractSubTrackPointArray( fPTrackPointArray2b, fPVolIDArray2b, pTPCArray2, 7, 8 )) return kFALSE;
-
- delete pfullITStrackArray; pfullITStrackArray=NULL;
- delete [] goodtracksArr; goodtracksArr=NULL;
- delete [] ITStracksArr; ITStracksArr=NULL;
- delete [] TPCtracksArr; TPCtracksArr=NULL;
- delete [] nPointsArr; nPointsArr=NULL;
- delete [] phiArr; phiArr=NULL;
- delete [] thetaArr; thetaArr=NULL;
- delete [] distanceFromVertexArr; distanceFromVertexArr=NULL;
- //printf("FindCosmicInEvent END\n");
- return kTRUE;
-}
-
-Bool_t AliRelAlignerKalman::ExtractSubTrackPointArray( AliTrackPointArray* pTrackOut, TArrayI* pVolIDArrayOut, const AliTrackPointArray* pTrackIn, const Int_t firstlayer, const Int_t lastlayer )
-{
- //printf("ExtractSubTrackPointArray\n");
- //From pTrackIn select points between firstlayer and lastlayer and put the result in pTrackOut.
- //VolID's of selected points go in pVolIDArrayOut
- //only good points selected.
- //points can be ordered with z by setting fSortTrackPointsWithY
-
- AliTrackPoint point;
- Int_t nPointsIn = pTrackIn->GetNPoints();
- if (nPointsIn<TMath::Min(fMinPointsVol1,fMinPointsVol2)) return kFALSE;
- Int_t iPointArr[1000];
- Int_t VolIDArr[1000];
- Float_t yArr[1000];
- Int_t iOuter=-1;
- Int_t OuterLayerID=0;
- Int_t nGood=0;
-
- //loop over trackpoints and record the good ones
- for (Int_t i=0; i<nPointsIn; i++)
+ //find matching in TPC
+ if (nTPCtracks>1) //if there is something to be matched, try and match it
+ {
+ Float_t min = 10000000.;
+ for (Int_t itr1=0; itr1<nTPCtracks; itr1++)
{
- UShort_t VolIDshort = pTrackIn->GetVolumeID()[i];
- Int_t layerID = AliGeomManager::VolUIDToLayer(VolIDshort);
- //some points are very dirty: have nan's in coordinates or are otherwise sick
- {
- Float_t x = pTrackIn->GetX()[i];
- Float_t y = pTrackIn->GetY()[i];
- Float_t z = pTrackIn->GetZ()[i];
- if ( ((TMath::Abs(x)<1.)||(TMath::Abs(x)>1000.))&&
- ((TMath::Abs(y)<1.)||(TMath::Abs(y)>1000.))||
- ((TMath::Abs(z)>1000.))
- )
- continue;
- }
- if ( (layerID >= firstlayer) && (layerID <= lastlayer) )
+ for (Int_t itr2=itr1+1; itr2<nTPCtracks; itr2++)
+ {
+ Float_t deltatheta = TMath::Abs(TMath::Pi()-thetaArr[tracksArrTPC[itr1]]-thetaArr[tracksArrTPC[itr2]]);
+ if (deltatheta > fMaxMatchingAngle) continue;
+ Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[tracksArrTPC[itr1]]-phiArr[tracksArrTPC[itr2]])-TMath::Pi());
+ if (deltaphi > fMaxMatchingAngle) continue;
+ if (deltatheta+deltaphi<min) //only the best matching pair
{
-
- iPointArr[nGood] = i;
- VolIDArr[nGood] = VolIDshort;
- yArr[nGood] = pTrackIn->GetY()[i];
- if (layerID>OuterLayerID)
- {
- OuterLayerID=layerID;
- iOuter = nGood;
- }
- nGood++;
+ min=deltatheta+deltaphi;
+ candidateTPCtracksArr[0] = tracksArrTPC[itr1]; //store the index of track in goodtracksArr[]
+ candidateTPCtracksArr[1] = tracksArrTPC[itr2];
+ nCandidateTPCtracks = 2;
+ foundMatchTPC = kTRUE;
+ //printf("TrackFinder: Matching TPC tracks candidates:\n");
+ //printf("TrackFinder: candidateTPCtracksArr[0]=%d\n",tracksArrTPC[itr1]);
+ //printf("TrackFinder: candidateTPCtracksArr[1]=%d\n",tracksArrTPC[itr2]);
}
- else continue;
- }//for i=0..nPointsIn
- if (nGood<TMath::Min(fMinPointsVol1,fMinPointsVol2)) return kFALSE;
- //Fill the output array of VolID's
- delete pVolIDArrayOut;
- pVolIDArrayOut = new TArrayI( nGood );
-
- //fill the output trackarray
- Int_t* iSortedYArr = new Int_t[nGood];
- if (fSortTrackPointsWithY)
- {
- TMath::Sort( nGood, yArr, iSortedYArr, kFALSE );
- }
- delete pTrackOut;
- pTrackOut = new AliTrackPointArray( nGood );
-
- for ( Int_t i=0; i<nGood; i++)
- {
- pTrackIn->GetPoint( point, iPointArr[(fSortTrackPointsWithY)?iSortedYArr[i]:i] );
- pTrackOut->AddPoint( i, &point );
- pVolIDArrayOut->AddAt( VolIDArr[(fSortTrackPointsWithY)?iSortedYArr[i]:i], i );
+ }
}
- //printf("ExtractSubTrackPointArray END\n");
- return kTRUE;
-}
-
-void AliRelAlignerKalman::SortTrackPointArrayWithY( AliTrackPointArray* pout, const AliTrackPointArray* pinn, const Bool_t descending )
-{
- //sorts a given trackpointarray by y coordinate
+ }//if nTPCtracks>1
+ else //if nTPCtracks==1 - if nothing to match, take the only one we've got
+ {
+ candidateTPCtracksArr[0] = tracksArrTPC[0];
+ nCandidateTPCtracks = 1;
+ foundMatchTPC = kFALSE;
+ }
+ if (foundMatchTPC) fNMatchedTPCtracklets++;
+ //if no match but the requirement is set return kFALSE
+ if (fRequireMatchInTPC && !foundMatchTPC)
+ {
+ delete [] phiArr;
+ delete [] thetaArr;
+ delete [] goodtracksArr;
+ delete [] candidateTPCtracksArr;
+ delete [] matchedITStracksArr;
+ delete [] matchedTPCtracksArr;
+ delete [] tracksArrITS;
+ delete [] tracksArrTPC;
+ delete [] nPointsArr;
+ //printf("TrackFinder: no match in TPC && required\n");
+ return kFALSE;
+ }
- Int_t npoints = pinn->GetNPoints();
- const AliTrackPointArray* pin;
- if (pinn==pout)
- pin = new AliTrackPointArray(*pinn);
- else
+ //if no match and more than one track take all TPC tracks
+ if (!fRequireMatchInTPC && !foundMatchTPC)
+ {
+ for (Int_t i=0;i<nTPCtracks;i++)
{
- pin = pinn;
- if (pout!=NULL) delete pout;
- pout = new AliTrackPointArray(npoints);
+ candidateTPCtracksArr[i] = tracksArrTPC[i];
}
-
- Int_t* iarr = new Int_t[npoints];
-
- TMath::Sort( npoints, pin->GetY(), iarr, descending );
-
- AliTrackPoint p;
- for (Int_t i=0; i<npoints; i++)
+ nCandidateTPCtracks = nTPCtracks;
+ }
+ //printf("TrackFinder: nCandidateTPCtracks: %i\n", nCandidateTPCtracks);
+
+ Double_t* minDifferenceArr = new Double_t[nCandidateTPCtracks];
+
+ //find ITS matches for good TPC tracks
+ Bool_t matchedITStracks=kFALSE;
+ for (Int_t itpc=0;itpc<nCandidateTPCtracks;itpc++)
+ {
+ minDifferenceArr[nMatchedITStracks] = 10000000.;
+ matchedITStracks=kFALSE;
+ for (Int_t iits=0; iits<nITStracks; iits++)
{
- pin->GetPoint( p, iarr[i] );
- pout->AddPoint( i, &p );
+ AliESDtrack* itstrack = pEvent->GetTrack(goodtracksArr[tracksArrITS[iits]]);
+ const AliExternalTrackParam* parits = itstrack->GetOuterParam();
+ AliESDtrack* tpctrack = pEvent->GetTrack(goodtracksArr[candidateTPCtracksArr[itpc]]);
+ const AliExternalTrackParam* tmp = tpctrack->GetInnerParam();
+ AliExternalTrackParam partpc(*tmp); //make a copy to avoid tampering with original params
+ partpc.Rotate(parits->GetAlpha());
+ partpc.PropagateTo(parits->GetX(),fMagField);
+ Float_t dtgl = TMath::Abs(partpc.GetTgl()-parits->GetTgl());
+ if (dtgl > fMaxMatchingAngle) continue;
+ Float_t dsnp = TMath::Abs(partpc.GetSnp()-parits->GetSnp());
+ if (dsnp > fMaxMatchingAngle) continue;
+ Float_t dy = TMath::Abs(partpc.GetY()-parits->GetY());
+ Float_t dz = TMath::Abs(partpc.GetZ()-parits->GetZ());
+ if (TMath::Sqrt(dy*dy+dz*dz) > fMaxMatchingDistance) continue;
+ if (dtgl+dsnp<minDifferenceArr[nMatchedITStracks]) //only the best matching pair
+ {
+ minDifferenceArr[nMatchedITStracks]=dtgl+dsnp;
+ matchedITStracksArr[nMatchedITStracks] = tracksArrITS[iits];
+ matchedTPCtracksArr[nMatchedITStracks] = candidateTPCtracksArr[itpc]; //this tells us minDifferenceArrwhich TPC track this ITS track belongs to
+ //printf("TrackFinder: Matching ITS to TPC:\n");
+ //printf("TrackFinder: minDifferenceArr[%i]=%.2f\n",nMatchedITStracks,minDifferenceArr[nMatchedITStracks]);
+ //printf("TrackFinder: matchedITStracksArr[%i]=%i\n",nMatchedITStracks,matchedITStracksArr[nMatchedITStracks]);
+ //printf("TrackFinder: matchedTPCtracksArr[%i]=%i\n",nMatchedITStracks,matchedTPCtracksArr[nMatchedITStracks]);
+ matchedITStracks=kTRUE;;
+ }
}
- delete [] iarr;
+ if (matchedITStracks) nMatchedITStracks++;
+ }
+
+ if (nMatchedITStracks==0) //no match in ITS
+ {
+ delete [] phiArr;
+ delete [] thetaArr;
+ delete [] minDifferenceArr;
+ delete [] goodtracksArr;
+ delete [] matchedITStracksArr;
+ delete [] candidateTPCtracksArr;
+ delete [] matchedTPCtracksArr;
+ delete [] tracksArrITS;
+ delete [] tracksArrTPC;
+ delete [] nPointsArr;
+ //printf("TrackFinder: No match in ITS\n");
+ return kFALSE;
+ }
+
+ //printf("TrackFinder: nMatchedITStracks: %i\n",nMatchedITStracks);
+ //we found a cosmic
+ fNMatchedCosmics++;
+
+ //Now we may have ended up with more matches than we want in the case there was
+ //no TPC match and there were many TPC tracks
+ //a cosmic in a scenario like this will only have produced 1 pair, the rest is garbage
+ //so take only the best pair.
+ //same applies when there are more matches than ITS tracks - means that one ITS track
+ //matches more TPC tracks.
+ if ((nMatchedITStracks>2 && !foundMatchTPC) || nMatchedITStracks>nITStracks)
+ {
+ Int_t imin = TMath::LocMin(nMatchedITStracks,minDifferenceArr);
+ matchedITStracksArr[0] = matchedITStracksArr[imin];
+ matchedTPCtracksArr[0] = matchedTPCtracksArr[imin];
+ nMatchedITStracks = 1;
+ //printf("TrackFinder: too many matches - take only the best one\n");
+ //printf("TrackFinder: LocMin in matched its tracks: %d\n",imin);
+ //printf("TrackFinder: matchedITStracksArr[0]=%d\n",matchedITStracksArr[0]);
+ //printf("TrackFinder: matchedTPCtracksArr[0]=%d\n",matchedTPCtracksArr[0]);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ outITSindexTArr.Set(nMatchedITStracks);
+ outTPCindexTArr.Set(nMatchedITStracks);
+ for (Int_t i=0;i<nMatchedITStracks;i++)
+ {
+ outITSindexTArr.AddAt( goodtracksArr[matchedITStracksArr[i]], i );
+ outTPCindexTArr.AddAt( goodtracksArr[matchedTPCtracksArr[i]], i );
+ //printf("TrackFinder: Fill the output\n");
+ //printf("TrackFinder: matchedITStracksArr[%d]=%d\n",i,matchedITStracksArr[i]);
+ //printf("TrackFinder: matchedTPCtracksArr[%d]=%d\n",i,matchedTPCtracksArr[i]);
+ }
+ //printf("TrackFinder: Size of outputarrays: %d, %d\n", outITSindexTArr.GetSize(), outTPCindexTArr.GetSize());
+ ///////////////////////////////////////////////////////////////////////////
+
+ delete [] phiArr;
+ delete [] thetaArr;
+ delete [] minDifferenceArr;
+ delete [] goodtracksArr;
+ delete [] candidateTPCtracksArr;
+ delete [] matchedITStracksArr;
+ delete [] matchedTPCtracksArr;
+ delete [] tracksArrITS;
+ delete [] tracksArrTPC;
+ delete [] nPointsArr;
+ return kTRUE;
}
-Bool_t AliRelAlignerKalman::FitTrackPointArrayRieman( TVector3* pPoint, TMatrixDSym* pPointCov, TVector3* pDir, TMatrixDSym* pDirCov, AliTrackPointArray* pTrackPointArray, TArrayI* pVolIDs, AliTrackPoint* pRefPoint )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::CorrectTrack( AliExternalTrackParam* tr, const TVectorD& misal ) const
{
- //printf("FitTrackPointArrayRieman\n");
- //Use AliTrackFitterRieman to fit a track through given point array
-
- AliTrackFitterRieman fitter;
- AliTrackPoint trackPoint;
- const Float_t* pointcov;
- ////here's an ugly hack://///////
- //AliTrackPointArray* pTrackPointArray = const_cast < AliTrackPointArray* > (pTrackPointArrayIn);
- /////////////////////////////////
- fitter.SetTrackPointArray( pTrackPointArray, kFALSE );
- if ( !fitter.Fit( pVolIDs ) ) return kFALSE;
- if ( !fitter.GetPCA( *fPRefAliTrackPoint, trackPoint ) ) return kFALSE;
- Double_t xPoint = trackPoint.GetX();
- pPoint->SetXYZ( xPoint, trackPoint.GetY(), trackPoint.GetZ() );
- pDir->SetXYZ( 1., fitter.GetDYat(xPoint), fitter.GetDZat(xPoint) );
- *pDir = pDir->Unit();
- //TODO cov of dir!
-
- pointcov = trackPoint.GetCov();
- (*pPointCov)(0,0) = pointcov[0];(*pPointCov)(0,1) = pointcov[1];(*pPointCov)(0,2) = pointcov[2];
- (*pPointCov)(1,0) = pointcov[1];(*pPointCov)(1,1) = pointcov[3];(*pPointCov)(1,2) = pointcov[4];
- (*pPointCov)(2,0) = pointcov[2];(*pPointCov)(2,1) = pointcov[4];(*pPointCov)(2,2) = pointcov[5];
-
- //printf("FitTrackPointArrayRieman END\n");
- return kTRUE;
+ //implements the system model -
+ //applies correction for misalignment and calibration to track
+ //track needs to be already propagated to the global reference plane
+
+ Double_t x = tr->GetX();
+ Double_t alpha = tr->GetAlpha();
+ Double_t point[3],dir[3];
+ tr->GetXYZ(point);
+ tr->GetDirection(dir);
+ TVector3 Point(point);
+ TVector3 Dir(dir);
+
+ //Apply corrections to track
+
+ //Shift
+ Point(0) -= misal(3); //add shift in x
+ Point(1) -= misal(4); //add shift in y
+ Point(2) -= misal(5); //add shift in z
+ //Rotation
+ TMatrixD rotmat(3,3);
+ RotMat( rotmat, misal );
+ Point = rotmat.T() * Point;
+ Dir = rotmat * Dir;
+
+ //TPC vdrift and T0 corrections
+ TVector3 Point2; //second point of the track
+ Point2 = Point + Dir;
+ Double_t vdCorr = 1./misal(6);
+ Double_t t0 = misal(7);
+ Double_t vdY = 0.0;
+ if (fgkNSystemParams>8) vdY = misal(8)/100.; //change over 100cm.
+
+ //my model
+ if (Point(2)>0)
+ {
+ //A-Side
+ Point(2) = Point(2) - (fTPCZLengthA-Point(2)) * (vdCorr-1.+vdY*Point(1)/fTPCvd) - (fTPCvd*vdCorr+vdY*Point(1))*t0;
+ Point2(2) = Point2(2) - (fTPCZLengthA-Point2(2)) * (vdCorr-1.+vdY*Point2(1)/fTPCvd) - (fTPCvd*vdCorr+vdY*Point2(1))*t0;
+ }
+ else
+ {
+ //C-side
+ Point(2) = Point(2) - (fTPCZLengthC+Point(2)) * (1.-vdCorr-vdY*Point(1)/fTPCvd) + (fTPCvd*vdCorr+vdY*Point(1))*t0;
+ Point2(2) = Point2(2) - (fTPCZLengthC+Point2(2)) * (1.-vdCorr-vdY*Point2(1)/fTPCvd) + (fTPCvd*vdCorr+vdY*Point2(1))*t0;
+ }
+
+ //Stefan's model
+ //if (Point(2)>0)
+ //{
+ // //A-Side
+ // Point(2) = Point(2) - (fTPCZLengthA-Point(2)) * (1.-vdCorr+vdY*Point(1)/fTPCvd) - (fTPCvd*vdCorr+vdY*Point(1))*t0;
+ // Point2(2) = Point2(2) - (fTPCZLengthA-Point2(2)) * (1.-vdCorr+vdY*Point2(1)/fTPCvd) - (fTPCvd*vdCorr+vdY*Point2(1))*t0;
+ //}
+ //else
+ //{
+ // //C-side
+ // Point(2) = Point(2) + (fTPCZLengthC+Point(2)) * (1.-vdCorr+vdY*Point(1)/fTPCvd) + (fTPCvd*vdCorr+vdY*Point(1))*t0;
+ // Point2(2) = Point2(2) + (fTPCZLengthC+Point2(2)) * (1.-vdCorr+vdY*Point2(1)/fTPCvd) + (fTPCvd*vdCorr+vdY*Point2(1))*t0;
+ //}
+
+ Dir = Point2-Point;
+ Dir=Dir.Unit(); //keep unit length
+
+ //Turn back to local system
+ Dir.GetXYZ(dir);
+ Point.GetXYZ(point);
+ tr->Global2LocalPosition(point,alpha);
+ tr->Global2LocalPosition(dir,alpha);
+
+ //Calculate new intersection point with ref plane
+ Double_t p[5],pcov[15];
+ if (dir[0]==0.0) return kFALSE;
+ Double_t s=(x-point[0])/dir[0];
+ p[0] = point[1]+s*dir[1];
+ p[1] = point[2]+s*dir[2];
+ Double_t pt = TMath::Sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
+ if (pt==0.0) return kFALSE;
+ p[2] = dir[1]/pt;
+ p[3] = dir[2]/pt;
+ //insert everything back into track
+ const Double_t* pcovtmp = tr->GetCovariance();
+ p[4] = tr->GetSigned1Pt(); //copy the momentum
+ memcpy(pcov,pcovtmp,15*sizeof(Double_t));
+ tr->Set(x,alpha,p,pcov);
+ return kTRUE;
+
+ ////put params back into track and propagate to ref
+ //Double_t p[5],pcov[15];
+ //p[0] = point[1];
+ //p[1] = point[2];
+ //Double_t xnew = point[0];
+ //Double_t pt = TMath::Sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
+ //if (pt==0.0) return kFALSE;
+ //p[2] = dir[1]/pt;
+ //p[3] = dir[2]/pt;
+ //p[4] = tr->GetSigned1Pt(); //copy the momentum
+ //const Double_t* pcovtmp = tr->GetCovariance();
+ //memcpy(pcov,pcovtmp,15*sizeof(Double_t));
+ //tr->Set(xnew,alpha,p,pcov);
+ //return tr->PropagateTo(x,fMagField);
}
-Bool_t AliRelAlignerKalman::FitTrackPointArrayKalman( TVector3* pPoint, TMatrixDSym* pPointCov, TVector3* pDir, TMatrixDSym* pDirCov, AliTrackPointArray* pTrackPointArray, TArrayI* pVolIDs, AliTrackPoint* pRefPoint )
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::MisalignTrack( AliExternalTrackParam* tr, const TVectorD& misal ) const
{
- //printf("FitTrackPointArrayKalman\n");
- //Use AliTrackFitterKalman to fit a track through given point array
- //still needs work
-
- AliTrackFitterKalman fitter;
- AliTrackPoint trackPoint, trackPoint2;
-
- pTrackPointArray->GetPoint( trackPoint, 0 );
- pTrackPointArray->GetPoint( trackPoint2, 1 );
- //Make sure all points count
- fitter.SetMaxChi2(100000000.);
- if (!fitter.MakeSeed( &trackPoint, &trackPoint2 )) return kFALSE;
- Int_t npoints = pTrackPointArray->GetNPoints();
- for (Int_t i=2; i<npoints; i++)
- {
- pTrackPointArray->GetPoint( trackPoint, i );
- if (!fitter.AddPoint( &trackPoint )) continue;
- }//for i
- TMatrixDSym fullcov = fitter.GetCovariance();
- printf("FitTrackPointArrayKalman: the covariance matrix of the fit");
- fullcov.Print();
-
- //now propagate to ref plane - its a hack that depends on the implementation of AddPoint()!
- // - first set the maxchi2 to 0 so addpoint returns false, but
- //actually the trackparameters have already been been propagated to the new planei, it's safe
- //because AliTrackFitterKalman::Propagate() is always kTRUE.
- fitter.SetMaxChi2(0.);
- fitter.AddPoint( fPRefAliTrackPoint );
-
- const Double_t* pparams = fitter.GetParam();
- fullcov = fitter.GetCovariance();
-
- pDir->SetXYZ( pparams[3], 1., pparams[4] );
- pPoint->SetXYZ( pparams[0], pparams[1], pparams[2] );
-
- (*pPointCov)(0,0) = fullcov(0,0);(*pPointCov)(0,1) = fullcov(0,1);(*pPointCov)(0,2) = fullcov(0,2);
- (*pPointCov)(1,0) = fullcov(1,0);(*pPointCov)(1,1) = fullcov(1,1);(*pPointCov)(1,2) = fullcov(1,2);
- (*pPointCov)(2,0) = fullcov(2,0);(*pPointCov)(2,1) = fullcov(2,1);(*pPointCov)(2,2) = fullcov(2,2);
-
- (*pDirCov)(0,0)=fullcov(3,3); (*pDirCov)(0,1)=0.; (*pDirCov)(0,2)=fullcov(3,4);
- (*pDirCov)(1,0)=0.; (*pDirCov)(1,1)=0.; (*pDirCov)(1,2)=0.;
- (*pDirCov)(2,0)=fullcov(4,3); (*pDirCov)(2,1)=0.; (*pDirCov)(2,2)=fullcov(4,4);
- return kTRUE;
+ //implements the system model -
+ //applies misalignment and miscalibration to reference track
+ //trackparams have to be at the global reference plane
+
+ Double_t x = tr->GetX();
+ Double_t alpha = tr->GetAlpha();
+ Double_t point[3],dir[3];
+ tr->GetXYZ(point);
+ tr->GetDirection(dir);
+ TVector3 Point(point);
+ TVector3 Dir(dir);
+
+ //Apply misalignment to track
+
+ //TPC vdrift and T0 corrections
+ TVector3 Point2; //second point of the track
+ Point2 = Point + Dir;
+ Double_t vdCorr = 1./misal(6);
+ Double_t t0 = misal(7);
+ Double_t vdY = 0.0;
+ if (fgkNSystemParams>8) vdY = misal(8)/100.; //change over 100cm.
+
+ if (Point(2)>0)
+ {
+ //A-Side
+ Point(2) = Point(2) + ((fTPCZLengthA-Point(2))/(vdCorr*fTPCvd+vdY*Point(1)))
+ * (fTPCvd*(vdCorr-1.)+vdY*Point(1)) + fTPCvd*t0;
+ Point2(2) = Point2(2) + ((fTPCZLengthA-Point2(2))/(vdCorr*fTPCvd+vdY*Point2(1)))
+ * (fTPCvd*(vdCorr-1.)+vdY*Point2(1)) + fTPCvd*t0;
+ }
+ else
+ {
+ //C-side
+ Point(2) = Point(2) + (fTPCZLengthC+Point(2))/(vdCorr*fTPCvd+vdY*Point(1))
+ * (fTPCvd*(1.-vdCorr)-vdY*Point(1)) - fTPCvd*t0;
+ Point2(2) = Point2(2) + (fTPCZLengthC+Point2(2))/(vdCorr*fTPCvd+vdY*Point2(1))
+ * (fTPCvd*(1.-vdCorr)-vdY*Point2(1)) - fTPCvd*t0;
+ }
+ Dir = Point2-Point;
+ Dir=Dir.Unit(); //keep unit length
+
+ //Rotation
+ TMatrixD rotmat(3,3);
+ RotMat( rotmat, misal );
+ Point = rotmat * Point;
+ Dir = rotmat * Dir;
+ //Shift
+ Point(0) += misal(3); //add shift in x
+ Point(1) += misal(4); //add shift in y
+ Point(2) += misal(5); //add shift in z
+
+ //Turn back to local system
+ Dir.GetXYZ(dir);
+ Point.GetXYZ(point);
+ tr->Global2LocalPosition(point,alpha);
+ tr->Global2LocalPosition(dir,alpha);
+
+ //Calculate new intersection point with ref plane
+ Double_t p[5],pcov[15];
+ if (dir[0]==0.0) return kFALSE;
+ Double_t s=(x-point[0])/dir[0];
+ p[0] = point[1]+s*dir[1];
+ p[1] = point[2]+s*dir[2];
+ Double_t pt = TMath::Sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
+ if (pt==0.0) return kFALSE;
+ p[2] = dir[1]/pt;
+ p[3] = dir[2]/pt;
+ //insert everything back into track
+ const Double_t* pcovtmp = tr->GetCovariance();
+ p[4] = tr->GetSigned1Pt(); //copy the momentum
+ memcpy(pcov,pcovtmp,15*sizeof(Double_t));
+ tr->Set(x,alpha,p,pcov);
+ return kTRUE;
+
+ ////put params back into track and propagate to ref
+ //Double_t p[5];
+ //Double_t pcov[15];
+ //p[0] = point[1];
+ //p[1] = point[2];
+ //Double_t xnew = point[0];
+ //Double_t pt = TMath::Sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
+ //if (pt==0.0) return kFALSE;
+ //p[2] = dir[1]/pt;
+ //p[3] = dir[2]/pt;
+ //p[4] = tr->GetSigned1Pt(); //copy the momentum
+ //const Double_t* pcovtmp = tr->GetCovariance();
+ //memcpy(pcov,pcovtmp,15*sizeof(Double_t));
+ //printf("x before: %.5f, after: %.5f\n",x, xnew);
+ //printf("before: %.4f %.4f %.4f %.4f %.4f \n",tr->GetParameter()[0],tr->GetParameter()[1],tr->GetParameter()[2],tr->GetParameter()[3],tr->GetParameter()[4]);
+ //printf("after: %.4f %.4f %.4f %.4f %.4f \n",p[0],p[1],p[2],p[3],p[4]);
+ //tr->Set(xnew,alpha,p,pcov);
+ //return tr->PropagateTo(x,fMagField);
}
-void AliRelAlignerKalman::SanitizeExtendedCovMatrix( TMatrixDSym& covout, const TMatrixDSym& pointcov, const TVector3& dir )
+//______________________________________________________________________________
+void AliRelAlignerKalman::Reset()
{
- //reverse the effect of extending of the covariance matrix along the track
- //direction as done by the AliTrackFitters
-
- //idea is to rotate to a system where track direction is y axis,
- //in that refsystem setting the y related components of covariance
- //then rotate back.
- TVector3 yaxis(0,1,0);
- Double_t angle = dir.Angle(yaxis);
- TVector3 rotaxisvec = dir.Cross(yaxis);
- TVector3 rotaxis = rotaxisvec.Unit();
- TMatrixD R(3,3);
-
- //Fill the rotation matrix.
- Double_t ex=rotaxis(0);
- Double_t ey=rotaxis(1);
- Double_t ez=rotaxis(2);
- Double_t sin = TMath::Sin(angle);
- Double_t cos = TMath::Cos(angle);
- Double_t icos = 1 - cos;
- R(0,0) = cos + (ex*ex)*icos;
- R(0,1) = icos*ex*ey - ez*sin;
- R(0,2) = icos*ex*ez + ey*sin;
- R(1,0) = icos*ey*ex + ez*sin;
- R(1,1) = cos + (ey*ey)*icos;
- R(1,2) = icos*ey*ez - ex*sin;
- R(2,0) = icos*ez*ex - ey*sin;
- R(2,1) = icos*ez*ey + ex*sin;
- R(2,2) = cos + (ez*ez)*icos;
-
- //Transform covariance:
- TMatrixD covR( pointcov, TMatrixD::kMultTranspose, R);
- TMatrixD RcovR( R, TMatrixD::kMult, covR );
- TMatrixD newcov(3,3);
- newcov(0,0)=RcovR(0,0);
- newcov(0,2)=RcovR(0,2);
- newcov(2,0)=RcovR(2,0);
- newcov(2,2)=RcovR(2,2);
- newcov(1,1)=(newcov(0,0)+newcov(2,2))/2.; //this is a bit insane!!
- covR = newcov *R;
- RcovR = R.T() * covR;
- TMatrixDSym_from_TMatrixD( covout, RcovR );
+ //full reset to defaults
+ fPX->Zero();
+ (*fPX)(6)=1.;
+ ResetCovariance();
+
+ //initialize the differentials per parameter
+ for (Int_t i=0;i<fgkNSystemParams;i++) fDelta[i] = 1.e-6;
+
+ fNMatchedCosmics=0;
+ fNMatchedTPCtracklets=0;
+ fNUpdates=0;
+ fNOutliers=0;
+ fNTracks=0;
+ fNProcessedEvents=0;
+ fRunNumber=0;
+ fTimeStamp=0;
}
-void AliRelAlignerKalman::JoinTrackArrays( AliTrackPointArray* pout, const AliTrackPointArray* pin1, const AliTrackPointArray* pin2 )
+//______________________________________________________________________________
+void AliRelAlignerKalman::ResetCovariance( const Double_t number )
{
- //Join two AliTrackPointArrays
-
- Int_t np1 = pin1->GetNPoints();
- Int_t np2 = pin2->GetNPoints();
- if (pout!=NULL) delete pout;
- pout = new AliTrackPointArray(np1+np2);
- AliTrackPoint p;
- for (Int_t i=0;i<np1;i++)
+ //Resets the covariance to the default if arg=0 or resets the off diagonals
+ //to zero and releases the diagonals by factor arg.
+ if (number!=0.)
+ {
+ for (Int_t z=0;z<6;z++)
{
- pin1->GetPoint( p, i );
- pout->AddPoint( i, &p );
- }
- for (Int_t i=0;i<np2;i++)
- {
- pin2->GetPoint( p, i );
- pout->AddPoint( i+np1, &p );
+ for (Int_t zz=0;zz<6;zz++)
+ {
+ if (zz==z) continue; //don't touch diagonals
+ (*fPXcov)(zz,z) = 0.;
+ (*fPXcov)(z,zz) = 0.;
+ }
+ (*fPXcov)(z,z) = (*fPXcov)(z,z) * number;
}
+ }
+ else
+ {
+ //Resets the covariance of the fit to a default value
+ fPXcov->Zero();
+ (*fPXcov)(0,0) = .08*.08; //psi (rad)
+ (*fPXcov)(1,1) = .08*.08; //theta (rad
+ (*fPXcov)(2,2) = .08*.08; //phi (rad)
+ (*fPXcov)(3,3) = .3*.3; //x (cm)
+ (*fPXcov)(4,4) = .3*.3; //y (cm)
+ (*fPXcov)(5,5) = .3*.3; //z (cm)
+ }
+ ResetTPCparamsCovariance(number);
}
-Bool_t AliRelAlignerKalman::ProcessTrackPointArrays()
+//______________________________________________________________________________
+void AliRelAlignerKalman::ResetTPCparamsCovariance( const Double_t number )
{
- //Fit the track point arrays and update some household info
-
- fFitted=kFALSE; //not fitted yet
- if ( !FitTrackPointArrayKalman( fPPoint2, fPPoint2Cov, fPDir2, fPDir2Cov,
- fPTrackPointArray2, fPVolIDArray2, fPRefAliTrackPoint ) )
- {
- fNUnfitted++;
- return kFALSE;
- }
-
- if ( f3TracksMode )
- {
- if ( !FitTrackPointArrayKalman( fPPoint2b, fPPoint2bCov, fPDir2b, fPDir2bCov,
- fPTrackPointArray2b, fPVolIDArray2b, fPRefAliTrackPoint ) )
- {
- fNUnfitted++;
- return kFALSE;
- }
- }
-
- if ( !FitTrackPointArrayKalman( fPPoint1, fPPoint1Cov, fPDir1, fPDir1Cov,
- fPTrackPointArray1, fPVolIDArray1, fPRefAliTrackPoint ) )
+ //Resets the covariance to the default if arg=0 or resets the off diagonals
+ //to zero and releases the diagonals by factor arg.
+
+ //release diagonals
+ if (number==0.)
+ {
+ if (fgkNSystemParams>6) (*fPXcov)(6,6) = .1*.1;
+ if (fgkNSystemParams>7) (*fPXcov)(7,7) = 1.*1.;
+ if (fgkNSystemParams>8) (*fPXcov)(8,8) = .1*.1;
+ }
+ else
+ {
+ if (fgkNSystemParams>6) (*fPXcov)(6,6) = number * (*fPXcov)(6,6);
+ if (fgkNSystemParams>7) (*fPXcov)(7,7) = number * (*fPXcov)(7,7);
+ if (fgkNSystemParams>8) (*fPXcov)(8,8) = number * (*fPXcov)(8,8);
+ }
+
+ //set crossterms to zero
+ for (Int_t i=0;i<fgkNSystemParams;i++)
+ {
+ for (Int_t j=6;j<fgkNSystemParams;j++) //TPC params
{
- fNUnfitted++;
- return kFALSE;
+ if (i==j) continue; //don't touch diagonals
+ (*fPXcov)(i,j) = 0.;
+ (*fPXcov)(j,i) = 0.;
}
-
- fFitted=kTRUE;
- //printf("ProcessTrackPointArrays: fitted!\n");
- return kTRUE;
+ }
}
-Bool_t AliRelAlignerKalman::UpdateCalibration()
+//______________________________________________________________________________
+Bool_t AliRelAlignerKalman::Merge( const AliRelAlignerKalman* al )
{
- //Update the calibration with new data, used in calibration pass
-
- fPThetaMesHist->Fill( (*fPMeasurement)(0) );
- fPPhiMesHist->Fill( (*fPMeasurement)(1) );
- fPXMesHist->Fill( (*fPMeasurement)(2) );
- fPZMesHist->Fill( (*fPMeasurement)(3) );
- if (f3TracksMode)
- {
- fPThetaMesHist2->Fill( (*fPMeasurement)(4) );
- fPPhiMesHist2->Fill( (*fPMeasurement)(5) );
- fPXMesHist2->Fill( (*fPMeasurement)(6) );
- fPZMesHist2->Fill( (*fPMeasurement)(7) );
- }
- fCalibrationUpdated=kTRUE;
- return kTRUE;
+ //Merge two aligners
+
+ if (!al) return kFALSE;
+ if (al==this) return kTRUE;
+ if (al->fgkNSystemParams != fgkNSystemParams) return kFALSE;
+ if (fRunNumber != al->fRunNumber) return kFALSE;
+ if (al->fNUpdates == 0) return kTRUE; //no point in merging with an empty one
+
+ //store the pointers to current stuff
+ TVectorD* pmes = fPMeasurement;
+ TMatrixDSym* pmescov = fPMeasurementCov;
+ TVectorD* pmespred = fPMeasurementPrediction;
+ TMatrixD* ph = fPH;
+
+ //make a unity system matrix
+ TMatrixD tmp(fgkNSystemParams,fgkNSystemParams);
+ fPH = new TMatrixD(TMatrixD::kUnit, tmp);
+
+ //mesurement is the state of the new aligner
+ fPMeasurement = al->fPX;
+ fPMeasurementCov = al->fPXcov;
+
+ //the mesurement prediction is the state
+ fPMeasurementPrediction = fPX; //this is safe as fPX doesn't change until end
+
+ //do the merging
+ Bool_t success = UpdateEstimateKalman();
+
+ //restore pointers to old stuff
+ fPMeasurement = pmes;
+ fPMeasurementCov = pmescov;
+ fPMeasurementPrediction = pmespred;
+ delete fPH;
+ fPH = ph;
+
+ //merge stats
+ fNProcessedEvents += al->fNProcessedEvents;
+ fNUpdates += al->fNUpdates;
+ fNOutliers += al->fNOutliers;
+ fNTracks += al->fNTracks;
+ fNMatchedTPCtracklets += al->fNMatchedTPCtracklets;
+ fNMatchedCosmics += al->fNMatchedCosmics;
+ if (fTimeStamp < al->fTimeStamp) fTimeStamp = al->fTimeStamp; //take the older one
+
+ return success;
}
-Bool_t AliRelAlignerKalman::SetCalibrationPass( Bool_t cp )
+//______________________________________________________________________________
+Int_t AliRelAlignerKalman::Compare(const TObject *obj) const
{
- //sets the calibration mode
- if (cp)
- {
- fCalibrationPass=kTRUE;
- return kTRUE;
- }//if (cp)
- else
- {
- if (!fCalibrationUpdated) return kFALSE;
- if (fCalibrationPass) // do it only after the calibration pass
- {
- Double_t tmp;
- fPMeasurementCov->Zero(); //reset the covariance
-
- fPThetaMesHist->Fit("gaus");
- TF1* fitformula = fPThetaMesHist->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(0,0) = tmp*tmp;
-
- fPPhiMesHist->Fit("gaus");
- fitformula = fPPhiMesHist->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(1,1) = tmp*tmp;
-
- fPXMesHist->Fit("gaus");
- fitformula = fPXMesHist->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(2,2) = tmp*tmp;
-
- fPZMesHist->Fit("gaus");
- fitformula = fPZMesHist->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(3,3) = tmp*tmp;
-
- if (f3TracksMode)
- {
- fPThetaMesHist2->Fit("gaus");
- fitformula = fPThetaMesHist2->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(4,4) = tmp*tmp;
-
- fPPhiMesHist2->Fit("gaus");
- fitformula = fPPhiMesHist2->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(5,5) = tmp*tmp;
-
- fPXMesHist2->Fit("gaus");
- fitformula = fPXMesHist2->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(6,6) = tmp*tmp;
-
- fPZMesHist2->Fit("gaus");
- fitformula = fPZMesHist2->GetFunction("gaus");
- tmp = fitformula->GetParameter(2);
- (*fPMeasurementCov)(7,7) = tmp*tmp;
- }
-
- fCalibrationPass=kFALSE;
- fFixedMeasurementCovariance=kTRUE;
- fPMeasurementCov->Print();
- return kTRUE;
- }//if (fCalibrationPass)
- return kFALSE;
- }//else (cp)
- return kFALSE;
+ if (this == obj) return 0;
+ const AliRelAlignerKalman* aobj = dynamic_cast<const AliRelAlignerKalman*>(obj);
+ if (!aobj) return 0;
+ if (fTimeStamp < aobj->fTimeStamp) return -1;
+ else if (fTimeStamp > aobj->fTimeStamp) return 1;
+ else return 0;
}
-void AliRelAlignerKalman::PrintDebugInfo()
-{
- //prints debug info
- cout<<"AliRelAlignerKalman debug info"<<endl;
- printf("fPTrackPointArray1 y: ");
- for (Int_t i=0; i<fPTrackPointArray1->GetNPoints();i++)
- {
- printf("%.2f ",fPTrackPointArray1->GetY()[i]);
- }
- printf("\n");
- printf("fPTrackPointArray2 y: ");
- for (Int_t i=0; i<fPTrackPointArray2->GetNPoints();i++)
- {
- printf("%.2f ",fPTrackPointArray2->GetY()[i]);
- }
- printf("\n");
- printf("fPTrackPointArray2b y: ");
- for (Int_t i=0; i<fPTrackPointArray2b->GetNPoints();i++)
- {
- printf("%.2f ",fPTrackPointArray2b->GetY()[i]);
- }
- printf("\n");
-
- printf("Measurement covariance");
- fPMeasurementCov->Print();
-}
+//______________________________________________________________________________
+//Int_t AliRelAlignerKalman::Compare(const AliRelAlignerKalman *al) const
+//{
+// if (this == al) return 0;
+// if (fTimeStamp > al->fTimeStamp) return -1;
+// else if (fTimeStamp < al->fTimeStamp) return 1;
+// else return 0;
+//}
+
+//______________________________________________________________________________
+//void AliRelAlignerKalman::PrintCovarianceCorrection()
+//{
+// //Print the measurement covariance correction matrix
+// printf("Covariance correction matrix:\n");
+// for ( Int_t i=0; i<fgkNMeasurementParams; i++ )
+// {
+// for ( Int_t j=0; j<i+1; j++ )
+// {
+// printf("% -2.2f ", (*fPMeasurementCovCorr)(i,j) );
+// }//for i
+// printf("\n");
+// }//for j
+// printf("\n");
+// return;
+//}
+
+//_______________________________________________________________________________
+//Bool_t AliRelAlignerKalman::UpdateCalibration()
+//{
+// //Update the calibration with new data (in calibration mode)
+//
+// fPMes0Hist->Fill( (*fPMeasurement)(0) );
+// fPMes1Hist->Fill( (*fPMeasurement)(1) );
+// fPMes2Hist->Fill( (*fPMeasurement)(2) );
+// fPMes3Hist->Fill( (*fPMeasurement)(3) );
+// fPMesErr0Hist->Fill( TMath::Sqrt((*fPMeasurementCov)(0,0)) );
+// fPMesErr1Hist->Fill( TMath::Sqrt((*fPMeasurementCov)(1,1)) );
+// fPMesErr2Hist->Fill( TMath::Sqrt((*fPMeasurementCov)(2,2)) );
+// fPMesErr3Hist->Fill( TMath::Sqrt((*fPMeasurementCov)(3,3)) );
+// return kTRUE;
+//}
+
+//______________________________________________________________________________
+//Bool_t AliRelAlignerKalman::SetCalibrationMode( const Bool_t cp )
+//{
+// //sets the calibration mode
+// if (cp)
+// {
+// fCalibrationMode=kTRUE;
+// return kTRUE;
+// }//if (cp)
+// else
+// {
+// if (fCalibrationMode) // do it only after the calibration pass
+// {
+// CalculateCovarianceCorrection();
+// SetApplyCovarianceCorrection();
+// fCalibrationMode=kFALSE;
+// return kTRUE;
+// }//if (fCalibrationMode)
+// }//else (cp)
+// return kFALSE;
+//}
+
+//______________________________________________________________________________
+//Bool_t AliRelAlignerKalman::CalculateCovarianceCorrection()
+//{
+// //Calculates the correction to the measurement covariance
+// //using the calibration histograms
+//
+// fPMeasurementCovCorr->Zero(); //reset the correction
+//
+// Double_t s,m,c; //sigma,meansigma,correction
+//
+// //TF1* fitformula;
+// //fPMes0Hist->Fit("gaus");
+// //fitformula = fPMes0Hist->GetFunction("gaus");
+// //s = fitformula->GetParameter(2); //spread of the measurement
+// //fPMesErr0Hist->Fit("gaus");
+// //fitformula = fPMesErr0Hist->GetFunction("gaus"); //average error from cov matrices
+// //m = fitformula->GetParameter(1);
+// s = fPMes0Hist->GetRMS();
+// m = fPMesErr0Hist->GetMean();
+// c = s-m; //the difference between the average error and real spread of the data
+// if (c>0) //only correct is spread bigger than average error
+// (*fPMeasurementCovCorr)(0,0) = c*c;
+//
+// //fPMes1Hist->Fit("gaus");
+// //fitformula = fPMes1Hist->GetFunction("gaus");
+// //s = fitformula->GetParameter(2);
+// //fPMesErr1Hist->Fit("gaus");
+// //fitformula = fPMesErr1Hist->GetFunction("gaus");
+// //m = fitformula->GetParameter(1);
+// s = fPMes1Hist->GetRMS();
+// m = fPMesErr1Hist->GetMean();
+// c = s-m;
+// if (c>0) //only correct is spread bigger than average error
+// (*fPMeasurementCovCorr)(1,1) = c*c;
+//
+// //fPMes2Hist->Fit("gaus");
+// //fitformula = fPMes2Hist->GetFunction("gaus");
+// //s = fitformula->GetParameter(2);
+// //fPMesErr2Hist->Fit("gaus");
+// //fitformula = fPMesErr2Hist->GetFunction("gaus");
+// //m = fitformula->GetParameter(1);
+// s = fPMes2Hist->GetRMS();
+// m = fPMesErr2Hist->GetMean();
+// c = s-m;
+// if (c>0) //only correct is spread bigger than average error
+// (*fPMeasurementCovCorr)(2,2) = c*c;
+//
+// //fPMes3Hist->Fit("gaus");
+// //fitformula = fPMes3Hist->GetFunction("gaus");
+// //s = fitformula->GetParameter(2);
+// //fPMesErr3Hist->Fit("gaus");
+// //fitformula = fPMesErr3Hist->GetFunction("gaus");
+// //m = fitformula->GetParameter(1);
+// s = fPMes3Hist->GetRMS();
+// m = fPMesErr3Hist->GetMean();
+// c = s-m;
+// if (c>0) //only correct is spread bigger than average error
+// (*fPMeasurementCovCorr)(3,3) = c*c;
+//
+// return kTRUE;
+//}