/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // Kalman filter based aligner: // 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, // - TPC y dependence of vdrift // - TPC time offset correction. // // Basic usage: // When aligning two volumesi, 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: // // In collision events add an ESD track to update the fit, // // Bool_t 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) // // _________________________________________________________________________ // Expert options: // look at AddCosmicEvent() to get the idea of how the // aligner works, it's safe to repeat the steps outside of the class, only // public methods are used. // // The following is dangerous!! Cripples the outlier rejection! Don't use it! // In the calibration mode set by // // void SetCalibrationMode( const Bool_t cal=kTRUE ); // // a correction for the covariance matrix of the measurement can be calculated // in case the errors estimated by the track fit do not correspond to the // actual spread of the residuals. // In calibration mode the aligner fills histograms of the residuals and of // the errors of the residuals. // Setting the calibration mode to false: // void SetCalibrationMode( const Bool_t cal=kFALSE ); // automatically enables the correction. // // Pointers to the histograms are available with apropriate getters for // plotting and analysis. // // // Origin: Mikolaj Krzewicki, Nikhef, Mikolaj.Krzewicki@cern.ch // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #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) //______________________________________________________________________________ AliRelAlignerKalman::AliRelAlignerKalman(): fAlpha(0.), fLocalX(80.), fkPTrackParam1(NULL), fkPTrackParam2(NULL), 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 )), fOutRejSigmas(1.), fRejectOutliers(kTRUE), fCalibrationMode(kFALSE), fFillHistograms(kTRUE), fRequireMatchInTPC(kFALSE), fApplyCovarianceCorrection(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), fNMatchedCosmics(0), fNMatchedTPCtracklets(0), fNProcessedEvents(0), fNHistogramBins(200), fPMes0Hist(new TH1D("res y","res y", fNHistogramBins, 0, 0)), fPMes1Hist(new TH1D("res z","res z", fNHistogramBins, 0, 0)), fPMes2Hist(new TH1D("res sinphi","res sinphi", fNHistogramBins, 0, 0)), fPMes3Hist(new TH1D("res tgl","res tgl", fNHistogramBins, 0, 0)), fPMesErr0Hist(new TH1D("mescov11","mescov11", fNHistogramBins, 0, 0)), fPMesErr1Hist(new TH1D("mescov22","mescov22", fNHistogramBins, 0, 0)), fPMesErr2Hist(new TH1D("mescov33","mescov33", fNHistogramBins, 0, 0)), fPMesErr3Hist(new TH1D("mescov44","mescov44", fNHistogramBins, 0, 0)), fPMeasurementCovCorr(new TMatrixDSym(fgkNMeasurementParams)), fTPCvd(2.64), fTPCZLengthA(2.49725006103515625e+02), fTPCZLengthC(2.49697998046875000e+02) { //Default constructor //default seed: zero, reset errors to large default Reset(); //initialize the differentials per parameter for (Int_t i=0;iGetInnerParam(); return kFALSE; } //______________________________________________________________________________ Bool_t AliRelAlignerKalman::AddCosmicEvent( const AliESDEvent* pEvent ) { //Add an cosmic with separately tracked ITS and TPC parts, do trackmatching Bool_t success=kFALSE; TArrayI trackTArrITS(1); TArrayI trackTArrTPC(1); if (!FindCosmicTrackletNumbersInEvent( trackTArrITS, trackTArrTPC, pEvent )) return kFALSE; Double_t field = pEvent->GetMagneticField(); AliESDtrack* ptrack; const AliExternalTrackParam* pconstparams; AliExternalTrackParam params; //////////////////////////////// for (Int_t i=0;iGetTrack(trackTArrITS[i]); pconstparams = ptrack->GetOuterParam(); if (!pconstparams) continue; SetRefSurface( pconstparams->GetX(), pconstparams->GetAlpha() ); SetTrackParams1(pconstparams); //TPC track ptrack = pEvent->GetTrack(trackTArrTPC[i]); pconstparams = ptrack->GetInnerParam(); if (!pconstparams) continue; params = (*pconstparams); params.Rotate(fAlpha); params.PropagateTo(fLocalX, field); SetTrackParams2(¶ms); //do some accounting and update if (!PrepareUpdate()) continue; if (Update()) success = kTRUE; else continue; } return success; } //______________________________________________________________________________ void AliRelAlignerKalman::Print(Option_t*) const { //Print some useful info Double_t rad2deg = 180./TMath::Pi(); printf("\nAliRelAlignerKalman:\n"); printf(" %i pairs, %i updates, %i outliers,\n", fNTracks, fNUpdates, fNOutliers ); printf(" %i TPC matches, %i good cosmics 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))); printf(" vd corr % .3g ± (%.2g) \n", (*fPX)(6), TMath::Sqrt((*fPXcov)(6,6))); printf(" vdY % .3f ± (%.2f) vd/cm\n", (*fPX)(7), TMath::Sqrt((*fPXcov)(7,7))); printf(" t0 % .3g ± (%.2g) muSec\n\n",(*fPX)(8), TMath::Sqrt((*fPXcov)(8,8))); return; } //______________________________________________________________________________ void AliRelAlignerKalman::PrintCovarianceCorrection() { //Print the measurement covariance correction matrix printf("Covariance correction matrix:\n"); for ( Int_t i=0; iGetParameter(); const Double_t* pararr2 = fkPTrackParam2->GetParameter(); //Take the track parameters and calculate the input to the Kalman filter (*fPMeasurement)(0) = pararr2[0]-pararr1[0]; (*fPMeasurement)(1) = pararr2[1]-pararr1[1]; (*fPMeasurement)(2) = pararr2[2]-pararr1[2]; (*fPMeasurement)(3) = pararr2[3]-pararr1[3]; fNTracks++; //count added track sets //the covariance const Double_t* parcovarr1 = fkPTrackParam1->GetCovariance(); const Double_t* parcovarr2 = fkPTrackParam2->GetCovariance(); (*fPMeasurementCov)(0,0)=parcovarr1[0]; (*fPMeasurementCov)(0,1)=parcovarr1[1]; (*fPMeasurementCov)(0,2)=parcovarr1[3]; (*fPMeasurementCov)(0,3)=parcovarr1[6]; (*fPMeasurementCov)(1,0)=parcovarr1[1]; (*fPMeasurementCov)(1,1)=parcovarr1[2]; (*fPMeasurementCov)(1,2)=parcovarr1[4]; (*fPMeasurementCov)(1,3)=parcovarr1[7]; (*fPMeasurementCov)(2,0)=parcovarr1[3]; (*fPMeasurementCov)(2,1)=parcovarr1[4]; (*fPMeasurementCov)(2,2)=parcovarr1[5]; (*fPMeasurementCov)(2,3)=parcovarr1[8]; (*fPMeasurementCov)(3,0)=parcovarr1[6]; (*fPMeasurementCov)(3,1)=parcovarr1[7]; (*fPMeasurementCov)(3,2)=parcovarr1[8]; (*fPMeasurementCov)(3,3)=parcovarr1[9]; (*fPMeasurementCov)(0,0)+=parcovarr2[0]; (*fPMeasurementCov)(0,1)+=parcovarr2[1]; (*fPMeasurementCov)(0,2)+=parcovarr2[3]; (*fPMeasurementCov)(0,3)+=parcovarr2[6]; (*fPMeasurementCov)(1,0)+=parcovarr2[1]; (*fPMeasurementCov)(1,1)+=parcovarr2[2]; (*fPMeasurementCov)(1,2)+=parcovarr2[4]; (*fPMeasurementCov)(1,3)+=parcovarr2[7]; (*fPMeasurementCov)(2,0)+=parcovarr2[3]; (*fPMeasurementCov)(2,1)+=parcovarr2[4]; (*fPMeasurementCov)(2,2)+=parcovarr2[5]; (*fPMeasurementCov)(2,3)+=parcovarr2[8]; (*fPMeasurementCov)(3,0)+=parcovarr2[6]; (*fPMeasurementCov)(3,1)+=parcovarr2[7]; (*fPMeasurementCov)(3,2)+=parcovarr2[8]; (*fPMeasurementCov)(3,3)+=parcovarr2[9]; if (fApplyCovarianceCorrection) *fPMeasurementCov += *fPMeasurementCovCorr; return kTRUE; } //______________________________________________________________________________ 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 ); TMatrixD d( fgkNMeasurementParams, 1 ); //get the derivatives for ( Int_t i=0; iSetSub( 0, i, d ); } return kTRUE; } //______________________________________________________________________________ Bool_t AliRelAlignerKalman::PredictMeasurement( TVectorD& pred, const TVectorD& state ) { // 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 //AliExternalTrackParam track(*fkPTrackParam1); //make a copy track //if (!CorrectTrack( &track, state )) return kFALSE; //predict what the misaligned track would be by applying misalignment //const Double_t* oldparam = fkPTrackParam1->GetParameter(); //const Double_t* newparam = track.GetParameter(); ////calculate the predicted residual //pred(0) = newparam[0] - oldparam[0]; //pred(1) = newparam[1] - oldparam[1]; //pred(2) = newparam[2] - oldparam[2]; //pred(3) = newparam[3] - oldparam[3]; //return kTRUE; if (fCorrectionMode) { AliExternalTrackParam track(*fkPTrackParam2); //make a copy track if (!CorrectTrack( &track, state )) return kFALSE; //predict what the ideal track would be by applying correction const Double_t* oldparam = fkPTrackParam2->GetParameter(); const Double_t* newparam = track.GetParameter(); //calculate the predicted residual pred(0) = oldparam[0] - newparam[0]; pred(1) = oldparam[1] - newparam[1]; pred(2) = oldparam[2] - newparam[2]; pred(3) = oldparam[3] - newparam[3]; return kTRUE; } else { AliExternalTrackParam track(*fkPTrackParam1); //make a copy track if (!MisalignTrack( &track, state )) return kFALSE; //predict what the measured track would be by applying misalignment const Double_t* oldparam = fkPTrackParam1->GetParameter(); const Double_t* newparam = track.GetParameter(); //calculate the predicted residual pred(0) = newparam[0] - oldparam[0]; pred(1) = newparam[1] - oldparam[1]; pred(2) = newparam[2] - oldparam[2]; pred(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): // 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 (hpht.Determinant() < 1.e-10) return kFALSE; TMatrixD k(pht, TMatrixD::kMult, hpht.Invert()); //compute K // update the state and its covariance matrix TVectorD xupdate(fgkNSystemParams); TVectorD hx(fgkNMeasurementParams); PredictMeasurement( hx, (*fPX) ); xupdate = k*((*fPMeasurement)-hx); //SIMPLE OUTLIER REJECTION if ( IsOutlier( xupdate, (*fPXcov) ) && fRejectOutliers ) { fNOutliers++; return kFALSE; } (*fPX) += xupdate; 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 TMatrixDSymFromTMatrixD( (*fPXcov), ikhp ); fNUpdates++; return kTRUE; } //______________________________________________________________________________ Bool_t AliRelAlignerKalman::IsOutlier( const TVectorD& update, const TMatrixDSym& covmatrix ) { //check whether an update is an outlier given the covariance matrix of the fit Bool_t is=kFALSE; for (Int_t i=0;i fOutRejSigmas*TMath::Sqrt((covmatrix)(i,i))); } return is; } //______________________________________________________________________________ void AliRelAlignerKalman::TMatrixDSymFromTMatrixD( TMatrixDSym& matsym, const TMatrixD& mat ) { //Produce a valid symmetric matrix out of an almost symmetric TMatrixD for (Int_t i=0; iGetNumberOfTracks(); ////printf("number of tracks in event: %i\n", ntracks); Double_t field = 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) { std::cout<<"no track!"<GetP()GetP()>fMaxMom) continue; } 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)&& !(nClsITSGetStatus()&AliESDtrack::kTPCin)>0)&& !(nClsTPC1) //if there is something to be matched, try and match it { Float_t min = 10000000.; for (Int_t itr1=0; itr1 fMaxMatchingAngle) continue; Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[tracksArrTPC[itr1]]-phiArr[tracksArrTPC[itr2]])-TMath::Pi()); if (deltaphi > fMaxMatchingAngle) continue; if (deltatheta+deltaphi1 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; } //if no match and more than one track take all TPC tracks if (!fRequireMatchInTPC && !foundMatchTPC) { for (Int_t i=0;iGetTrack(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(),field); 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+dsnp2 && !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;iFill( (*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; } //______________________________________________________________________________ void AliRelAlignerKalman::PrintDebugInfo() { //prints some debug info Print(); std::cout<<"AliRelAlignerKalman debug info"<Print(); printf("TrackParams2:"); fkPTrackParam2->Print(); printf("Measurement:"); fPMeasurement->Print(); printf("Measurement covariance:"); fPMeasurementCov->Print(); } //______________________________________________________________________________ Bool_t AliRelAlignerKalman::CorrectTrack( AliExternalTrackParam* tr, const TVectorD& misal ) { //implements the system model - //applies correction for misalignment and calibration to track 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 * Point; Dir = rotmat * Dir; //TPC vdrift and T0 corrections TVector3 Point2(Point); //second point of the track Point2 += Dir; Double_t vdCorr = misal(6); Double_t vdY = misal(7); Double_t t0 = misal(8); 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; } 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(); memcpy(pcov,pcovtmp,15*sizeof(Double_t)); tr->Set(x,alpha,p,pcov); return kTRUE; } //______________________________________________________________________________ Bool_t AliRelAlignerKalman::MisalignTrack( AliExternalTrackParam* tr, const TVectorD& misal ) { //implements the system model - //applies misalignment and miscalibration to reference track 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(Point); //second point of the track Point2 += Dir; Double_t vdCorr = misal(6); Double_t vdY = misal(7); Double_t t0 = misal(8); 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) 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) return kFALSE; p[2] = dir[1]/pt; p[3] = dir[2]/pt; //insert everything back into track const Double_t* pcovtmp = tr->GetCovariance(); memcpy(pcov,pcovtmp,15*sizeof(Double_t)); tr->Set(x,alpha,p,pcov); return kTRUE; } //______________________________________________________________________________ void AliRelAlignerKalman::Reset() { fPX->Zero(); (*fPX)(6)=1.; ResetCovariance(); } //______________________________________________________________________________ void AliRelAlignerKalman::ResetCovariance( const Double_t number ) { //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;zZero(); (*fPXcov)(0,0) = .01*.01; //psi (rad) (*fPXcov)(1,1) = .01*.01; //theta (rad (*fPXcov)(2,2) = .01*.01; //phi (rad) (*fPXcov)(3,3) = .5*.5; //x (cm) (*fPXcov)(4,4) = .5*.5; //y (cm) (*fPXcov)(5,5) = 2.*2.; //z (cm) (*fPXcov)(6,6) = .1*.1;//drift velocity correction (*fPXcov)(7,7) = 1.*1.; //vdY - slope of vd in y (*fPXcov)(8,8) = 10.*10.; //t0 in muSec } } //______________________________________________________________________________ void AliRelAlignerKalman::ResetTPCparamsCovariance( const Double_t number ) { //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.) { (*fPXcov)(6,6) = .1*.1; (*fPXcov)(7,7) = 1.*1.; (*fPXcov)(8,8) = 10.*10.; } else { (*fPXcov)(6,6) = number * (*fPXcov)(6,6); (*fPXcov)(7,7) = number * (*fPXcov)(7,7); (*fPXcov)(8,8) = number * (*fPXcov)(8,8); } //set crossterms to zero for (Int_t i=0;i