]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliRelAlignerKalman.cxx
ESD QA implemented
[u/mrichter/AliRoot.git] / STEER / AliRelAlignerKalman.cxx
CommitLineData
043badeb 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16///////////////////////////////////////////////////////////////////////////////
17//
18// Kalman filter based aligner:
19// Aligns two tracking volumes (by default ITS and TPC)
20// Determines the transformation of the second volume (TPC) wrt the first (ITS)
21// additionally calculates some callibration parameters for TPC
22// Fit parameters are:
23// - 3 shifts, x,y,z
24// - 3 Cardan angles, psi, theta, phi (see definition in alignment docs),
25// - TPC drift velocity correction (vel_true = vel*(1+correction)),
26// - TPC offset correction.
27//
28// Basic usage:
29// When aligning two volumes at any given time a single instance of
30// the class should be active. The fit of the parameters is updated
31// by adding new data using one of the Add.... methods.
32//
33// User methods:
34// In collision events add an ESD track to update the fit,
35// track will be automatically split in ITS and TPC tracklets
36// and the fit of the alignment constants will be updated:
37//
38// Bool_t AddESDTrack( AliESDtrack* pTrack );
39//
40// You may also give it the AliTrackPointArray,
41// the fit will be updated if there are enough ITS and TPC
42// points in it. Again, all is done automatically:
43//
44// Bool_t AddTrackPointArray( AliTrackPointArray* pTrackPointArr );
45//
46// For cosmic data, the assumption is that the tracking is done separately
47// for ITS and TPC and the tracklets are saved inside one AliESDEvent. The
48// method
49//
50// Bool_t AddCosmicEventSeparateTracking( AliESDEvent* pEvent );
51//
52// then searches the event for matching tracklets and upon succes it updates
53// the fit. For cosmics the fitter switches to a 3 tracks mode, the 3 tracks
54// being: 1 ITS and 2 TPC tracklets (upper and lower).
55//
56// Experts only:
57//
58//
59// Origin: Mikolaj Krzewicki, Nikhef, Mikolaj.Krzewicki@cern.ch
60//
61//////////////////////////////////////////////////////////////////////////////
62
248e9dfd 63#include <Riostream.h>
64
043badeb 65#include "AliRelAlignerKalman.h"
66
67ClassImp(AliRelAlignerKalman)
68
69//########################################################
70//
71// Control section
72//
73//########################################################
74
75AliRelAlignerKalman::AliRelAlignerKalman():
76 fPTrackPointArray1(new AliTrackPointArray(1)),
77 fPTrackPointArray2(new AliTrackPointArray(1)),
78 fPTrackPointArray2b(new AliTrackPointArray(1)),
79 fPVolIDArray1(new TArrayI(1)),
80 fPVolIDArray2(new TArrayI(1)),
81 fPVolIDArray2b(new TArrayI(1)),
82 fQ(1e-10),
83 fNMeasurementParams(fgkNMeasurementParams2TrackMode),
84 fNSystemParams(fgkNSystemParams),
85 fOutRejSigmas(2.),
86 f3TracksMode(kFALSE),
87 fSortTrackPointsWithY(kTRUE),
88 fFixedMeasurementCovariance(kTRUE),
89 fCalibrationPass(kFALSE),
90 fCalibrationUpdated(kFALSE),
91 fFitted(kFALSE),
92 fCuts(kFALSE),
93 fNTracks(0),
94 fNUpdates(0),
95 fNOutliers(0),
96 fNUnfitted(0),
97 fNMatchedCosmics(0),
98 fMinPointsVol1(2),
99 fMinPointsVol2(10),
100 fMinMom(0.),
101 fMaxMom(1e100),
102 fMinAbsSinPhi(0.),
103 fMaxAbsSinPhi(1.),
104 fMinSinTheta(-1.),
105 fMaxSinTheta(1.),
106 fMaxMatchingAngle(0.1),
107 fMaxMatchingDistance(1.), //in cm
108 fFirstLayerVol1(1),
109 fLastLayerVol1(6),
110 fFirstLayerVol2(7),
111 fLastLayerVol2(8)
112{
113 //Default constructor
114
115 fPDir1 = new TVector3; //Direction
116 fPDir2 = new TVector3;
117 fPDir2b = new TVector3;
118 fPDir1Cov = new TMatrixDSym(3);
119 fPDir2Cov = new TMatrixDSym(3);
120 fPDir2bCov = new TMatrixDSym(3);
121 fPDir1ThetaPhiCov = new TMatrixDSym(2); //Direction vectors are unit vectors, therefore 2 independent components!
122 fPDir2ThetaPhiCov = new TMatrixDSym(2);
123 fPDir2bThetaPhiCov = new TMatrixDSym(2);
124 fPPoint1 = new TVector3;
125 fPPoint2 = new TVector3;
126 fPPoint2b = new TVector3;
127 fPPoint1Cov = new TMatrixDSym(3);
128 fPPoint2Cov = new TMatrixDSym(3);
129 fPPoint2bCov = new TMatrixDSym(3);
130 fPRefPoint = new TVector3(0.,0.,0.);
131 fPRefPointDir = new TVector3(0.,1.,0.);
132 Float_t refpointcov[6] = { 1., 0., 0.,
133 0., 0.,
134 1. };
135 fPRefAliTrackPoint = new AliTrackPoint( 0.,0.,0.,refpointcov,0 );
136 fPMeasurement = new TVectorD( fNMeasurementParams );
137 fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
138 fPX = new TVectorD( fNSystemParams );
139 fPXcov = new TMatrixDSym( fNSystemParams );
140 fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
141 fPRotMat = new TMatrixD(3,3);
142 fPVec010 = new TVector3(0,1,0);
143
144 //default seed: zero, unit(large) errors
145 fPXcov->UnitMatrix();
146 (*fPXcov) *= 1.;
147
148 fPPhiMesHist = new TH1D("phi","phi", 50, 0, 0);
149 fPThetaMesHist = new TH1D("theta","theta", 50, 0, 0);
150 fPXMesHist = new TH1D("x","x", 50, 0, 0);
151 fPZMesHist = new TH1D("z","z", 50, 0, 0);
152 fPPhiMesHist2 = new TH1D("phi_","phi_", 50, 0, 0);
153 fPThetaMesHist2 = new TH1D("theta_","theta_", 50, 0, 0);
154 fPXMesHist2 = new TH1D("x_","x_", 50, 0, 0);
155 fPZMesHist2 = new TH1D("z_","z_", 50, 0, 0);
156}
157
158Bool_t AliRelAlignerKalman::AddESDTrack( AliESDtrack* pTrack )
159{
160 //Add an ESD track from a central event
161 //from the ESDtrack extract the pointarray
162
163 SetCosmicEvent(kFALSE);
164
165 const AliTrackPointArray *pTrackPointArrayConst = pTrack->GetTrackPointArray();
166 AliTrackPointArray* pTrackPointArray = const_cast < AliTrackPointArray* > (pTrackPointArrayConst);
167 if (pTrackPointArray == 0) return kFALSE;
168
169 if (!AddTrackPointArray( pTrackPointArray )) return kFALSE;
170 return kTRUE;
171}
172
173Bool_t AliRelAlignerKalman::AddTrackPointArray( AliTrackPointArray* pTrackPointArray )
174{
175 //Add a trackpointarray from a central event
176
177 SetCosmicEvent(kFALSE);
178 fNTracks++;
179
180 if (!ExtractSubTrackPointArray( fPTrackPointArray1, fPVolIDArray1, pTrackPointArray, 1,6 ))
181 return kFALSE;
182 if (!ExtractSubTrackPointArray( fPTrackPointArray2, fPVolIDArray2, pTrackPointArray, 7,8 ))
183 return kFALSE;
184
185 if (!ProcessTrackPointArrays()) return kFALSE;
186 if (!PrepareUpdate()) return kFALSE;
187 if (!Update()) return kFALSE;
188
189 return kTRUE;
190}
191
192Bool_t AliRelAlignerKalman::AddCosmicEventSeparateTracking( AliESDEvent* pEvent )
193{
194 //Add an cosmic with separately tracked ITS and TPC parts, do trackmatching
195
196 SetCosmicEvent(kTRUE); //set the cosmic flag
197 fNTracks++;
198
199 if (!FindCosmicInEvent( pEvent )) return kFALSE;
200 if (!ProcessTrackPointArrays()) return kFALSE;
201 //PrintDebugInfo();
202 if (!PrepareUpdate()) return kFALSE;
203 if (!Update()) return kFALSE;
204 printf("fpMeasurementCov:\n");
205 fPMeasurementCov->Print();
206
207 return kTRUE;
208}
209
210void AliRelAlignerKalman::Print()
211{
212 //Print some useful info
213 printf("\nAliRelAlignerKalman:\n");
214 printf(" %i tracks, %i updates, %i outliers, ", fNTracks, fNUpdates, fNOutliers );
215 printf("%i not fitted, %i matched cosmic tracklets\n", fNUnfitted, fNMatchedCosmics );
216 printf(" psi(x): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(0),1e3*TMath::Sqrt((*fPXcov)(0,0)));
217 printf(" theta(y): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(1),1e3*TMath::Sqrt((*fPXcov)(1,1)));
218 printf(" phi(z): %.1f ± (%.1f) mrad\n", 1e3*(*fPX)(2),1e3*TMath::Sqrt((*fPXcov)(2,2)));
219 printf(" x: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(3),1e4*TMath::Sqrt((*fPXcov)(3,3)));
220 printf(" y: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(4),1e4*TMath::Sqrt((*fPXcov)(4,4)));
221 printf(" z: %.1f ± (%.1f) micron\n", 1e4*(*fPX)(5),1e4*TMath::Sqrt((*fPXcov)(5,5)));
222 printf(" TPC(drift corr) %.1f ± (%.1f) percent\n", 1e2*(*fPX)(6),1e2*TMath::Sqrt((*fPXcov)(6,6)));
223 printf(" TPC(offset) %.1f ± (%.1f) micron\n", 1e4*(*fPX)(7),1e4*TMath::Sqrt((*fPXcov)(7,7)));
224 return;
225}
226
227void AliRelAlignerKalman::SetTrackParams1( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
228{
229 //Set the trackparameters for track in the first volume at reference
230 *fPPoint1 = point;
231 *fPPoint1Cov = pointcov;
232 *fPDir1 = dir;
233 *fPDir1Cov = dircov;
234}
235
236void AliRelAlignerKalman::SetTrackParams2( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
237{
238 //Set the trackparameters for track in the second volume at reference
239 *fPPoint2 = point;
240 *fPPoint2Cov = pointcov;
241 *fPDir2 = dir;
242 *fPDir2Cov = dircov;
243}
244
245void AliRelAlignerKalman::SetTrackParams2b( const TVector3& point, const TMatrixDSym& pointcov, const TVector3& dir, const TMatrixDSym& dircov )
246{
247 //Set the trackparameters for second track in the second volume at reference
248 *fPPoint2b = point;
249 *fPPoint2bCov = pointcov;
250 *fPDir2b = dir;
251 *fPDir2bCov = dircov;
252}
253
254void AliRelAlignerKalman::SetRefSurface( const Double_t yref )
255{
256 //set the reference surface
257 fPRefPoint->SetXYZ( 0., 1.*yref, 0. );
258 fPRefPointDir->SetXYZ( 0., 1., 0. );
259 Float_t refpointcov[6] = { 1., 0., 0.,
260 0., 0.,
261 1. };
262 fPRefAliTrackPoint->SetXYZ( 0., 1.*yref, 0., refpointcov );
263}
264
265void AliRelAlignerKalman::SetRefSurface( const TVector3& point, const TVector3& dir )
266{
267 //set the reference surface
268 *fPRefPoint = point;
269 *fPRefPointDir = dir;
270}
271
272void AliRelAlignerKalman::SetRefSurface( const AliTrackPoint& point, const Bool_t horizontal )
273{
274 //set the reference surface
275 (*fPRefAliTrackPoint) = point;
276
277 (*fPRefPoint)(0) = point.GetX();
278 (*fPRefPoint)(1) = point.GetY();
279 (*fPRefPoint)(2) = point.GetZ();
280
281 if (horizontal)
282 {
283 (*fPRefPointDir)(0) = 0.;
284 (*fPRefPointDir)(1) = 1.;
285 (*fPRefPointDir)(2) = 0.;
286
287 Float_t refpointcov[6] = { 1., 0., 0.,
288 0., 0.,
289 1. };
290 fPRefAliTrackPoint->SetXYZ( point.GetX(), point.GetY() , point.GetZ(), refpointcov );
291
292 }
293 else
294 {
295 Double_t angle = point.GetAngle();
296 (*fPRefPointDir)(0) = TMath::Cos(angle);
297 (*fPRefPointDir)(1) = TMath::Sin(angle);
298 (*fPRefPointDir)(2) = 0.;
299 *fPRefPointDir = fPRefPointDir->Unit();
300 }
301}
302
303void AliRelAlignerKalman::Set3TracksMode( Bool_t mode )
304{
305 //set the mode where 2 tracklets are allowed in volume 2 (default:TPC)
306 //used for alignment with cosmics
307
308 f3TracksMode = mode;
309 if (mode)
310 {
311 if (fNMeasurementParams!=fgkNMeasurementParams3TrackMode) //do something only if necessary
312 {
313 fNMeasurementParams = fgkNMeasurementParams3TrackMode;
314 delete fPMeasurement;
315 delete fPMeasurementCov;
316 delete fPH;
317 fPMeasurement = new TVectorD( fNMeasurementParams );
318 fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
319 fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
320 }
321 }
322 else
323 {
324 if (fNMeasurementParams!=fgkNMeasurementParams2TrackMode)
325 {
326 fNMeasurementParams = fgkNMeasurementParams2TrackMode;
327 delete fPMeasurement;
328 delete fPMeasurementCov;
329 delete fPH;
330 fPMeasurement = new TVectorD( fNMeasurementParams );
331 fPMeasurementCov = new TMatrixDSym( fNMeasurementParams );
332 fPH = new TMatrixD( fNMeasurementParams, fNSystemParams );
333 }
334 }
335}
336
337Bool_t AliRelAlignerKalman::PrepareUpdate()
338{
339 //Cast the extrapolated data (points and directions) into
340 //the internal Kalman filter data representation.
341 //takes the 3d coordinates of the points of intersection with
342 //the reference surface and projects them onto a 2D plane.
343 //does the same for angles, combines the result in one vector
344
345 if (!FillMeasurement()) return kFALSE;
346 if (!FillMeasurementMatrix()) return kFALSE;
347 return kTRUE;
348}
349
350Bool_t AliRelAlignerKalman::Update()
351{
352 //perform the update - either kalman or calibration
353 if (fCalibrationPass) return UpdateCalibration();
354 else return UpdateEstimateKalman();
355}
356
357void AliRelAlignerKalman::RotMat( TMatrixD &R, const TVectorD& angles )
358{
359//Get Rotation matrix R given the Cardan angles psi, theta, phi (around x, y, z).
360 Double_t sinpsi = TMath::Sin(angles(0));
361 Double_t sintheta = TMath::Sin(angles(1));
362 Double_t sinphi = TMath::Sin(angles(2));
363 Double_t cospsi = TMath::Cos(angles(0));
364 Double_t costheta = TMath::Cos(angles(1));
365 Double_t cosphi = TMath::Cos(angles(2));
366
367 R(0,0) = costheta*cosphi;
368 R(0,1) = -costheta*sinphi;
369 R(0,2) = sintheta;
370 R(1,0) = sinpsi*sintheta*cosphi + cospsi*sinphi;
371 R(1,1) = -sinpsi*sintheta*sinphi + cospsi*cosphi;
372 R(1,2) = -costheta*sinpsi;
373 R(2,0) = -cospsi*sintheta*cosphi + sinpsi*sinphi;
374 R(2,1) = cospsi*sintheta*sinphi + sinpsi*cosphi;
375 R(2,2) = costheta*cospsi;
376 return;
377}
378
379Bool_t AliRelAlignerKalman::FillMeasurement()
380{
381 //Take the track parameters and calculate the input to the Kalman filter
382
383 //Direction vectors
384 //Measured is the difference between the polar angles - convert to that
385 (*fPMeasurement)(0) = fPDir2->Theta() - fPDir1->Theta();
386 (*fPMeasurement)(1) = fPDir2->Phi() - fPDir1->Phi();
387
388 //Points
389 //Measured is the distance in XZ plane at Y of the reference point
390 (*fPMeasurement)(2) = fPPoint2->X() - fPPoint1->X();
391 (*fPMeasurement)(3) = fPPoint2->Z() - fPPoint1->Z();
392
393 //if 3 track mode set, set also the stuff for 2nd TPC track
394 if (f3TracksMode)
395 {
396 (*fPMeasurement)(4) = fPDir2b->Theta() - fPDir1->Theta();
397 (*fPMeasurement)(5) = fPDir2b->Phi() - fPDir1->Phi();
398 (*fPMeasurement)(6) = fPPoint2b->X() - fPPoint1->X();
399 (*fPMeasurement)(7) = fPPoint2b->Z() - fPPoint1->Z();
400 }
401
402 //Fill the covariance
403 if (fFixedMeasurementCovariance) return kTRUE;
404 //the dirs
405 GetThetaPhiCov( *fPDir1ThetaPhiCov, *fPDir1, *fPDir1Cov );
406 GetThetaPhiCov( *fPDir2ThetaPhiCov, *fPDir2, *fPDir2Cov );
407 fPMeasurementCov->SetSub( 0, (*fPDir1ThetaPhiCov) + (*fPDir2ThetaPhiCov) );
408
409 //the points
410 (*fPMeasurementCov)(2,2) = (*fPPoint1Cov)(0,0)+(*fPPoint2Cov)(0,0);
411 (*fPMeasurementCov)(2,3) = (*fPPoint1Cov)(0,2)+(*fPPoint2Cov)(0,2);
412 (*fPMeasurementCov)(3,2) = (*fPPoint1Cov)(2,0)+(*fPPoint2Cov)(2,0);
413 (*fPMeasurementCov)(3,3) = (*fPPoint1Cov)(2,2)+(*fPPoint2Cov)(2,2);
414
415 //if 3 track mode set, set also the stuff for 2nd TPC track
416 if (f3TracksMode)
417 {
418 GetThetaPhiCov( *fPDir2bThetaPhiCov, *fPDir2b, *fPDir2bCov );
419 fPMeasurementCov->SetSub( 4, (*fPDir1ThetaPhiCov) + (*fPDir2bThetaPhiCov) );
420 (*fPMeasurementCov)(6,6) = (*fPPoint1Cov)(0,0)+(*fPPoint2bCov)(0,0);
421 (*fPMeasurementCov)(6,7) = (*fPPoint1Cov)(0,2)+(*fPPoint2bCov)(0,2);
422 (*fPMeasurementCov)(7,6) = (*fPPoint1Cov)(2,0)+(*fPPoint2bCov)(2,0);
423 (*fPMeasurementCov)(7,7) = (*fPPoint1Cov)(2,2)+(*fPPoint2bCov)(2,2);
424 }
425 return kTRUE;
426}
427
428Bool_t AliRelAlignerKalman::FillMeasurementMatrix()
429{
430 //Calculate the system matrix for the Kalman filter
431 //approximate the system using as reference the track in the first volume
432
433 Double_t delta = 1.e-8;
434 TVectorD z1( fNMeasurementParams );
435 TVectorD z2( fNMeasurementParams );
436 TVectorD x1( *fPX );
437 TVectorD x2( *fPX );
438 TMatrixD D( fNMeasurementParams, 1 );
439 for ( Int_t i=0; i<fNSystemParams; i++ )
440 {
441 x1 = *fPX;
442 x2 = *fPX;
443 x1(i) -= delta;
444 x2(i) += delta;
445 if (!PredictMeasurement( z1, x1 )) return kFALSE;
446 if (!PredictMeasurement( z2, x2 )) return kFALSE;
447 for (Int_t j=0; j<fNMeasurementParams; j++ )
448 D.GetMatrixArray()[j] = (z2.GetMatrixArray()[j]-z1.GetMatrixArray()[j])/(2.*delta);
449 fPH->SetSub( 0, i, D );
450 }
451 return kTRUE;
452}
453
454Bool_t AliRelAlignerKalman::PredictMeasurement( TVectorD& pred, const TVectorD& state )
455{
456 // Implements a system model for the Kalman fit
457 // pred is [dtheta, dphi, dx, dz, [dtheta', dphi', dx', dz'] ] - second part is for 2nd TPC track in cosmics
458 // state is [psi,theta,phi,x,y,z,driftTPC,offsetTPC]
459
460 TVector3 newPoint = *fPPoint1;
461 TVector3 newDir = *fPDir1;
462 TVector3 shift;
463 //TPC drift correction
464 newDir(2) *= (1.+state(6));
465 newPoint(2) *= (1.+state(6));
466 //TPC offset
467 if (newPoint(2)>0) newPoint(2) += state(7);
468 else newPoint(2) -= state(7);
469 //rotate
470 TMatrixD rotmat(3,3);
471 RotMat( rotmat, state );
472 newDir = rotmat * newDir;
473 newPoint = rotmat * newPoint;
474 //shift
475 shift(0) = state(3);
476 shift(1) = state(4);
477 shift(2) = state(5);
478 newPoint += shift;
479 //Predicted measurement
480 if (!IntersectionLinePlane( newPoint, newPoint, newDir, *fPRefPoint, *fPVec010 )) return kFALSE;
481 pred(0) = newDir.Theta() - fPDir1->Theta();
482 pred(1) = newDir.Phi() - fPDir1->Phi();
483 pred(2) = newPoint(0) - fPPoint1->X();
484 pred(3) = newPoint(2) - fPPoint1->Z();
485
486 if (f3TracksMode)
487 {
488 //Do the same for second TPC track
489 //should be the same as the first TPC track
490 pred(4) = pred(0);
491 pred(5) = pred(1);
492 pred(6) = pred(2);
493 pred(7) = pred(3);
494 }
495 return kTRUE;
496}
497
498Bool_t AliRelAlignerKalman::UpdateEstimateKalman()
499{
500 //Kalman estimation of noisy constants: in the model A=1
501 //The arguments are (following the usual convention):
502 // x - the state vector (parameters)
503 // P - the state covariance matrix (parameter errors)
504 // z - measurement vector
505 // R - measurement covariance matrix
506 // H - measurement model matrix ( z = Hx + v ) v being measurement noise (error fR)
507 TVectorD *x = fPX;
508 TMatrixDSym *P = fPXcov;
509 TVectorD *z = fPMeasurement;
510 TMatrixDSym *R = fPMeasurementCov;
511 TMatrixD *H = fPH;
512
513 TMatrixDSym I(TMatrixDSym::kUnit, *P); //unit matrix
514
515 //predict the state
516 *P = *P + fQ*I; //add some process noise (diagonal)
517
518 // update prediction with measurement
519 // calculate Kalman gain
520 // K = PH/(HPH+R)
521 TMatrixD PHT( *P, TMatrixD::kMultTranspose, *H ); //common factor (used twice)
522 TMatrixD HPHT( *H, TMatrixD::kMult, PHT );
523 HPHT += *R;
524 TMatrixD K(PHT, TMatrixD::kMult, HPHT.Invert()); //compute K
525
526 // update the state and its covariance matrix
527 TVectorD xupdate(*x);
528 TVectorD Hx(*z);
529 PredictMeasurement( Hx, *x );
530 xupdate = K*((*z)-Hx);
531
532 //SIMPLE OUTLIER REJECTION
533 if (
534 (TMath::Abs(xupdate(0)) > fOutRejSigmas*TMath::Sqrt((*P)(0,0))) ||
535 (TMath::Abs(xupdate(1)) > fOutRejSigmas*TMath::Sqrt((*P)(1,1))) ||
536 (TMath::Abs(xupdate(2)) > fOutRejSigmas*TMath::Sqrt((*P)(2,2))) ||
537 (TMath::Abs(xupdate(3)) > fOutRejSigmas*TMath::Sqrt((*P)(3,3))) ||
538 (TMath::Abs(xupdate(4)) > fOutRejSigmas*TMath::Sqrt((*P)(4,4))) ||
539 (TMath::Abs(xupdate(5)) > fOutRejSigmas*TMath::Sqrt((*P)(5,5))) ||
540 (TMath::Abs(xupdate(6)) > fOutRejSigmas*TMath::Sqrt((*P)(6,6))) ||
541 (TMath::Abs(xupdate(7)) > fOutRejSigmas*TMath::Sqrt((*P)(7,7)))
542 )
543 {
544 fNOutliers++;
545 return kFALSE;
546 }
547
548 *x += xupdate;
549 TMatrixD KH( K, TMatrixD::kMult, *H );
550 TMatrixD IKH(I);
551 IKH = I - KH;
552 TMatrixD IKHP( IKH, TMatrixD::kMult, *P ); // (I-KH)P
553 TMatrixDSym_from_TMatrixD( *P, IKHP );
554 fNUpdates++;
555 return kTRUE;
556}
557
558void AliRelAlignerKalman::TMatrixDSym_from_TMatrixD( TMatrixDSym& matsym, const TMatrixD& mat )
559{
560 //Produce a valid symmetric matrix out of a TMatrixD
561
562 //not very efficient, diagonals are computer twice, but who cares
563 for (Int_t i=0; i<mat.GetNcols(); i++)
564 {
565 for (Int_t j=i; j<mat.GetNcols(); j++)
566 {
567 Double_t average = (mat(i,j)+mat(j,i))/2.;
568 matsym(i,j)=average;
569 matsym(j,i)=average;
570 }
571 }
572 return;
573}
574
575void AliRelAlignerKalman::GetThetaPhiCov( TMatrixDSym& cov, const TVector3& vec, const TMatrixDSym& vecCov )
576{
577 //Given the covariance matrix of a vector in euclid.space
578 //give cov matrix of the 2 spherical angles
579 const Double_t delta = 1e-8;
580 TVector3 vec1;
581 TVector3 vec2;
582 TMatrixD T(2,3);
583 for (Int_t i=0; i<3; i++)
584 {
585 vec1 = vec;
586 vec2 = vec;
587 vec1(i) -= delta/2.;
588 vec2(i) += delta/2.;
589 T(0,i) = (vec2.Theta() - vec1.Theta())/delta;
590 T(1,i) = (vec2.Phi() - vec1.Phi())/delta;
591 }
592 TMatrixD tmp( T, TMatrixD::kMult, vecCov );
593 TMatrixD nscov( tmp, TMatrixD::kMultTranspose, T );
594 cov(0,0) = nscov(0,0); cov(0,1) = nscov(0,1);
595 cov(1,0) = nscov(0,1); cov(1,1) = nscov(1,1);
596 return;
597}
598
599Bool_t AliRelAlignerKalman::IntersectionLinePlane( TVector3& intersection, const TVector3& linebase, const TVector3& linedir, const TVector3& planepoint, const TVector3& planenormal )
600{
601 //calculate the intersection point between a straight line and a plane
602 //plane is defined with a point in it and a normal, line has a point and direction
603 if (planenormal==TVector3(0,1,0))
604 {
605 if (linedir(1)==0) return kFALSE;
606 Double_t t = ( planepoint(1) - linebase(1) ) / linedir(1);
607 intersection = linebase + t*linedir;
608 return kTRUE;
609 }
610 else
611 {
612 Double_t dirdotn = linedir.Dot(planenormal);
613 if (dirdotn==0) return kFALSE;
614 Double_t t = ( planepoint.Dot(planenormal) - linebase.Dot(planenormal) ) / dirdotn;
615 intersection = linebase + t*linedir;
616 return kTRUE;
617 }
618}
619
620void AliRelAlignerKalman::Angles( TVectorD &angles, const TMatrixD &rotmat )
621{
622//Calculate the Cardan angles (psi,theta,phi) from rotation matrix
623//b = R*a
624//
625 angles(0) = TMath::ATan2( -rotmat(1,2), rotmat(2,2) );
626 angles(1) = TMath::ASin( rotmat(0,2) );
627 angles(2) = TMath::ATan2( -rotmat(0,1), rotmat(0,0) );
628 return;
629}
630
631void AliRelAlignerKalman::PrintCorrelationMatrix()
632{
633 //Print the correlation matrix for the fitted parameters
634
635 for ( Int_t j=0; j<fNSystemParams; j++ )
636 {
637 for ( Int_t i=0; i<fNSystemParams; i++ )
638 {
639 printf("%1.2f ", (*fPXcov)(i,j)/TMath::Sqrt( (*fPXcov)(i,i) * (*fPXcov)(j,j) ) );
640 }//for i
641 printf("\n");
642 }//for j
643 printf("\n");
644 return;
645}
646
647Bool_t AliRelAlignerKalman::FindCosmicInEvent( AliESDEvent* pEvent )
648{
649 //Find track point arrays belonging to one cosmic in a separately tracked ESD
650 //and put them in the apropriate data members
651
652 //Sanity cuts on tracks + check which tracks are ITS which are TPC
653 Int_t ntracks = pEvent->GetNumberOfTracks(); //printf("number of tracks in event: %i\n", ntracks);
654 if(ntracks<2) return kFALSE;
655 Float_t* phiArr = new Float_t[ntracks];
656 Float_t* thetaArr = new Float_t[ntracks];
657 Double_t* distanceFromVertexArr = new Double_t[ntracks];
658 Int_t* goodtracksArr = new Int_t[ntracks];
659 Int_t* ITStracksArr = new Int_t[ntracks];
660 Int_t* TPCtracksArr = new Int_t[ntracks];
661 Int_t* nPointsArr = new Int_t[ntracks];
662 Int_t nITStracks = 0;
663 Int_t nTPCtracks = 0;
664 Int_t nGoodTracks = 0;
665 AliESDtrack* pTrack = NULL;
666
667 const AliESDVertex* pVertex = pEvent->GetVertex();
668 Double_t vertexposition[3];
669 pVertex->GetXYZ(vertexposition);
670
671 Double_t magfield = pEvent->GetMagneticField();
672
673 //select sane tracks
674 for (Int_t itrack=0; itrack < ntracks; itrack++)
675 {
676 pTrack = pEvent->GetTrack(itrack);
677 if (!pTrack) {cout<<"no track!"<<endl;continue;}
678 if(pTrack->GetNcls(0)+pTrack->GetNcls(1) < fMinPointsVol1) continue;
679 Float_t phi = pTrack->GetAlpha()+TMath::ASin(pTrack->GetSnp());
680 Float_t theta = 0.5*TMath::Pi()-TMath::ATan(pTrack->GetTgl());
681 //printf("phi: %4.2f theta: %4.2f\n", phi, theta);
682 if(fCuts)
683 {
684 if(pTrack->GetP()<fMinMom || pTrack->GetP()>fMaxMom) continue;
685 Float_t abssinphi = TMath::Abs(TMath::Sin(phi));
686 if(abssinphi<fMinAbsSinPhi || abssinphi>fMaxAbsSinPhi) continue;
687 Float_t sintheta = TMath::Sin(theta);
688 if(sintheta<fMinSinTheta || sintheta>fMaxSinTheta) continue;
689 }
690 goodtracksArr[nGoodTracks]=itrack;
691 phiArr[nGoodTracks]=phi;
692 thetaArr[nGoodTracks]=theta;
693
694 pTrack->RelateToVertex( pVertex, magfield, 10000. );
695 Double_t trackposition[3];
696 pTrack->GetXYZ( trackposition );
697 distanceFromVertexArr[nGoodTracks] =
698 TMath::Sqrt((trackposition[0]-vertexposition[0])*(trackposition[0]-vertexposition[0])
699 + (trackposition[1]-vertexposition[1])*(trackposition[1]-vertexposition[1])
700 + (trackposition[2]-vertexposition[2])*(trackposition[2]-vertexposition[2]));
701
702 //check if track is ITS or TPC
703 if ( ((pTrack->GetStatus()&AliESDtrack::kITSin)>0)&&
704 !((pTrack->GetStatus()&AliESDtrack::kTPCin)>0) )
705 {
706 ITStracksArr[nITStracks] = nGoodTracks;
707 nITStracks++;
708 }
709
710 if ( ((pTrack->GetStatus()&AliESDtrack::kTPCin)>0)&&
711 !((pTrack->GetStatus()&AliESDtrack::kITSin)>0) )
712 {
713 TPCtracksArr[nTPCtracks] = nGoodTracks;
714 nTPCtracks++;
715 }
716
717 nGoodTracks++;
718 }//for itrack - sanity cuts
719
720 //printf("there are good tracks, %d in ITS and %d TPC.\n", nITStracks, nTPCtracks);
721
722 if( nITStracks < 2 || nTPCtracks < 2 )
723 {
724 delete [] goodtracksArr; goodtracksArr=0;
725 delete [] ITStracksArr; ITStracksArr=0;
726 delete [] TPCtracksArr; TPCtracksArr=0;
727 delete [] nPointsArr; nPointsArr=0;
728 delete [] phiArr; phiArr=0;
729 delete [] thetaArr; thetaArr=0;
730 delete [] distanceFromVertexArr; distanceFromVertexArr=0;
731 return kFALSE;
732 }
733
734 //find matching in TPC
735 Float_t min = 10000000.;
736 Int_t TPCgood1 = -1, TPCgood2 = -1;
737 for(Int_t itr1=0; itr1<nTPCtracks; itr1++)
738 {
739 for(Int_t itr2=itr1+1; itr2<nTPCtracks; itr2++)
740 {
741 Float_t deltatheta = TMath::Abs(TMath::Pi()-thetaArr[TPCtracksArr[itr1]]-thetaArr[TPCtracksArr[itr2]]);
742 if(deltatheta > fMaxMatchingAngle) continue;
743 Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[TPCtracksArr[itr1]]-phiArr[TPCtracksArr[itr2]])-TMath::Pi());
744 if(deltaphi > fMaxMatchingAngle) continue;
745 //printf("TPC: %f %f %f %f\n",deltaphi,deltatheta,thetaArr[TPCtracksArr[itr1]],thetaArr[TPCtracksArr[itr2]]);
746 if(deltatheta+deltaphi<min) //only the best matching pair
747 {
748 min=deltatheta+deltaphi;
749 TPCgood1 = TPCtracksArr[itr1]; //store the index of track in goodtracksArr[]
750 TPCgood2 = TPCtracksArr[itr2];
751 }
752 }
753 }
754 if (TPCgood1 < 0) //no dubble cosmic track
755 {
756 delete [] goodtracksArr; goodtracksArr=0;
757 delete [] ITStracksArr; ITStracksArr=0;
758 delete [] TPCtracksArr; TPCtracksArr=0;
759 delete [] nPointsArr; nPointsArr=0;
760 delete [] phiArr; phiArr=0;
761 delete [] thetaArr; thetaArr=0;
762 delete [] distanceFromVertexArr; distanceFromVertexArr=0;
763 return kFALSE;
764 }
765
766 //in ITS find 2 tracks that best match the found TPC cosmic
767 Double_t min1 = 10000000.;
768 Double_t min2 = 10000000.;
769 Int_t ITSgood1 = -1, ITSgood2 = -1;
770 for(Int_t itr1=0; itr1<nITStracks; itr1++)
771 {
772 if(distanceFromVertexArr[ITStracksArr[itr1]]>fMaxMatchingDistance) continue;
773 Float_t deltatheta = TMath::Abs(TMath::Pi()-thetaArr[ITStracksArr[itr1]]-thetaArr[TPCgood1]);
774 if(deltatheta > fMaxMatchingAngle) deltatheta = TMath::Abs( deltatheta - TMath::Pi() );
775 if(deltatheta > fMaxMatchingAngle) continue;
776 Float_t deltaphi = TMath::Abs(TMath::Abs(phiArr[ITStracksArr[itr1]]-phiArr[TPCgood1])-TMath::Pi());
777 if(deltaphi > fMaxMatchingAngle) deltaphi = TMath::Abs( deltaphi - TMath::Pi() );
778 if(deltaphi > fMaxMatchingAngle) continue;
779 //printf("ITS %i dtheta, dphi, vrtx: %.4f, %.4f, %.4f\n",ITStracksArr[itr1], deltatheta, deltaphi,distanceFromVertexArr[ITStracksArr[itr1]]);
780 if(deltatheta+deltaphi<min1) //only the best one
781 {
782 min1=deltatheta+deltaphi;
783 //ITSgood2 = ITSgood1;
784 ITSgood1 = ITStracksArr[itr1];
785 continue;
786 }
787 if(deltatheta+deltaphi<min2) //the second best
788 {
789 min2=deltatheta+deltaphi;
790 ITSgood2 = ITStracksArr[itr1];
791 continue;
792 }
793 }
794 if (ITSgood2 < 0) //no ITS cosmic track
795 {
796 delete [] goodtracksArr; goodtracksArr=0;
797 delete [] ITStracksArr; ITStracksArr=0;
798 delete [] TPCtracksArr; TPCtracksArr=0;
799 delete [] nPointsArr; nPointsArr=0;
800 delete [] phiArr; phiArr=0;
801 delete [] thetaArr; thetaArr=0;
802 delete [] distanceFromVertexArr; distanceFromVertexArr=0;
803 return kFALSE;
804 }
805
806 //we found a cosmic
807 fNMatchedCosmics++;
808
809 //////////////////////////////////////////////////////////////////////////////////////
810 // convert indexes from local goodtrackarrays to global track index
811 TPCgood1 = goodtracksArr[TPCgood1];
812 TPCgood2 = goodtracksArr[TPCgood2];
813 ITSgood1 = goodtracksArr[ITSgood1];
814 ITSgood2 = goodtracksArr[ITSgood2];
815 /////////////////////////////////////////////////////////////////////////////////////
816
817 AliESDtrack * pTPCtrack1 = pEvent->GetTrack(TPCgood1);
818 AliESDtrack * pTPCtrack2 = pEvent->GetTrack(TPCgood2);
819 AliESDtrack * pITStrack1 = pEvent->GetTrack(ITSgood1);
820 AliESDtrack * pITStrack2 = pEvent->GetTrack(ITSgood2);
821 const AliTrackPointArray* pTPCArray1 = pTPCtrack1->GetTrackPointArray();
822 const AliTrackPointArray* pTPCArray2 = pTPCtrack2->GetTrackPointArray();
823 const AliTrackPointArray* pITSArray1 = pITStrack1->GetTrackPointArray();
824 const AliTrackPointArray* pITSArray2 = pITStrack2->GetTrackPointArray();
825
826 AliTrackPointArray* pfullITStrackArray = new AliTrackPointArray(1);
827 JoinTrackArrays( pfullITStrackArray, pITSArray1, pITSArray2 );
828
829 //cout<<"selected tracks: TPC: "<<TPCgood1<<" "<<TPCgood2<<" ITS: "<<ITSgood1<<" "<<ITSgood2<<endl;
830
831 //Fill the final trackpointarrays
832 if (!ExtractSubTrackPointArray( fPTrackPointArray1, fPVolIDArray1, pfullITStrackArray, 1, 6 )) return kFALSE;
833 if (!ExtractSubTrackPointArray( fPTrackPointArray2, fPVolIDArray2, pTPCArray1, 7, 8 )) return kFALSE;
834 if (!ExtractSubTrackPointArray( fPTrackPointArray2b, fPVolIDArray2b, pTPCArray2, 7, 8 )) return kFALSE;
835
836 delete pfullITStrackArray; pfullITStrackArray=NULL;
837 delete [] goodtracksArr; goodtracksArr=NULL;
838 delete [] ITStracksArr; ITStracksArr=NULL;
839 delete [] TPCtracksArr; TPCtracksArr=NULL;
840 delete [] nPointsArr; nPointsArr=NULL;
841 delete [] phiArr; phiArr=NULL;
842 delete [] thetaArr; thetaArr=NULL;
843 delete [] distanceFromVertexArr; distanceFromVertexArr=NULL;
844 //printf("FindCosmicInEvent END\n");
845 return kTRUE;
846}
847
848Bool_t AliRelAlignerKalman::ExtractSubTrackPointArray( AliTrackPointArray* pTrackOut, TArrayI* pVolIDArrayOut, const AliTrackPointArray* pTrackIn, const Int_t firstlayer, const Int_t lastlayer )
849{
850 //printf("ExtractSubTrackPointArray\n");
851 //From pTrackIn select points between firstlayer and lastlayer and put the result in pTrackOut.
852 //VolID's of selected points go in pVolIDArrayOut
853 //only good points selected.
854 //points can be ordered with z by setting fSortTrackPointsWithY
855
856 AliTrackPoint point;
857 Int_t nPointsIn = pTrackIn->GetNPoints();
858 if (nPointsIn<TMath::Min(fMinPointsVol1,fMinPointsVol2)) return kFALSE;
859 Int_t iPointArr[1000];
860 Int_t VolIDArr[1000];
861 Float_t yArr[1000];
862 Int_t iOuter=-1;
863 Int_t OuterLayerID=0;
864 Int_t nGood=0;
865
866 //loop over trackpoints and record the good ones
867 for (Int_t i=0; i<nPointsIn; i++)
868 {
869 UShort_t VolIDshort = pTrackIn->GetVolumeID()[i];
870 Int_t layerID = AliGeomManager::VolUIDToLayer(VolIDshort);
871 //some points are very dirty: have nan's in coordinates or are otherwise sick
872 {
873 Float_t x = pTrackIn->GetX()[i];
874 Float_t y = pTrackIn->GetY()[i];
875 Float_t z = pTrackIn->GetZ()[i];
876 if ( ((TMath::Abs(x)<1.)||(TMath::Abs(x)>1000.))&&
877 ((TMath::Abs(y)<1.)||(TMath::Abs(y)>1000.))||
878 ((TMath::Abs(z)>1000.))
879 )
880 continue;
881 }
882 if ( (layerID >= firstlayer) && (layerID <= lastlayer) )
883 {
884
885 iPointArr[nGood] = i;
886 VolIDArr[nGood] = VolIDshort;
887 yArr[nGood] = pTrackIn->GetY()[i];
888 if (layerID>OuterLayerID)
889 {
890 OuterLayerID=layerID;
891 iOuter = nGood;
892 }
893 nGood++;
894 }
895 else continue;
896 }//for i=0..nPointsIn
897 if (nGood<TMath::Min(fMinPointsVol1,fMinPointsVol2)) return kFALSE;
898 //Fill the output array of VolID's
899 delete pVolIDArrayOut;
900 pVolIDArrayOut = new TArrayI( nGood );
901
902 //fill the output trackarray
903 Int_t* iSortedYArr = new Int_t[nGood];
904 if (fSortTrackPointsWithY)
905 {
906 TMath::Sort( nGood, yArr, iSortedYArr, kFALSE );
907 }
908 delete pTrackOut;
909 pTrackOut = new AliTrackPointArray( nGood );
910
911 for ( Int_t i=0; i<nGood; i++)
912 {
913 pTrackIn->GetPoint( point, iPointArr[(fSortTrackPointsWithY)?iSortedYArr[i]:i] );
914 pTrackOut->AddPoint( i, &point );
915 pVolIDArrayOut->AddAt( VolIDArr[(fSortTrackPointsWithY)?iSortedYArr[i]:i], i );
916 }
917 //printf("ExtractSubTrackPointArray END\n");
918 return kTRUE;
919}
920
921void AliRelAlignerKalman::SortTrackPointArrayWithY( AliTrackPointArray* pout, const AliTrackPointArray* pinn, const Bool_t descending )
922{
923 //sorts a given trackpointarray by y coordinate
924
925 Int_t npoints = pinn->GetNPoints();
926 const AliTrackPointArray* pin;
927 if (pinn==pout)
928 pin = new AliTrackPointArray(*pinn);
929 else
930 {
931 pin = pinn;
932 if (pout!=NULL) delete pout;
933 pout = new AliTrackPointArray(npoints);
934 }
935
936 Int_t* iarr = new Int_t[npoints];
937
938 TMath::Sort( npoints, pin->GetY(), iarr, descending );
939
940 AliTrackPoint p;
941 for (Int_t i=0; i<npoints; i++)
942 {
943 pin->GetPoint( p, iarr[i] );
944 pout->AddPoint( i, &p );
945 }
946 delete [] iarr;
947}
948
949Bool_t AliRelAlignerKalman::FitTrackPointArrayRieman( TVector3* pPoint, TMatrixDSym* pPointCov, TVector3* pDir, TMatrixDSym* pDirCov, AliTrackPointArray* pTrackPointArray, TArrayI* pVolIDs, AliTrackPoint* pRefPoint )
950{
951 //printf("FitTrackPointArrayRieman\n");
952 //Use AliTrackFitterRieman to fit a track through given point array
953
954 AliTrackFitterRieman fitter;
955 AliTrackPoint trackPoint;
956 const Float_t* pointcov;
957 ////here's an ugly hack://///////
958 //AliTrackPointArray* pTrackPointArray = const_cast < AliTrackPointArray* > (pTrackPointArrayIn);
959 /////////////////////////////////
960 fitter.SetTrackPointArray( pTrackPointArray, kFALSE );
961 if ( !fitter.Fit( pVolIDs ) ) return kFALSE;
962 if ( !fitter.GetPCA( *fPRefAliTrackPoint, trackPoint ) ) return kFALSE;
963 Double_t xPoint = trackPoint.GetX();
964 pPoint->SetXYZ( xPoint, trackPoint.GetY(), trackPoint.GetZ() );
965 pDir->SetXYZ( 1., fitter.GetDYat(xPoint), fitter.GetDZat(xPoint) );
966 *pDir = pDir->Unit();
967 //TODO cov of dir!
968
969 pointcov = trackPoint.GetCov();
970 (*pPointCov)(0,0) = pointcov[0];(*pPointCov)(0,1) = pointcov[1];(*pPointCov)(0,2) = pointcov[2];
971 (*pPointCov)(1,0) = pointcov[1];(*pPointCov)(1,1) = pointcov[3];(*pPointCov)(1,2) = pointcov[4];
972 (*pPointCov)(2,0) = pointcov[2];(*pPointCov)(2,1) = pointcov[4];(*pPointCov)(2,2) = pointcov[5];
973
974 //printf("FitTrackPointArrayRieman END\n");
975 return kTRUE;
976}
977
978Bool_t AliRelAlignerKalman::FitTrackPointArrayKalman( TVector3* pPoint, TMatrixDSym* pPointCov, TVector3* pDir, TMatrixDSym* pDirCov, AliTrackPointArray* pTrackPointArray, TArrayI* pVolIDs, AliTrackPoint* pRefPoint )
979{
980 //printf("FitTrackPointArrayKalman\n");
981 //Use AliTrackFitterKalman to fit a track through given point array
982 //still needs work
983
984 AliTrackFitterKalman fitter;
985 AliTrackPoint trackPoint, trackPoint2;
986
987 pTrackPointArray->GetPoint( trackPoint, 0 );
988 pTrackPointArray->GetPoint( trackPoint2, 1 );
989 //Make sure all points count
990 fitter.SetMaxChi2(100000000.);
991 if (!fitter.MakeSeed( &trackPoint, &trackPoint2 )) return kFALSE;
992 Int_t npoints = pTrackPointArray->GetNPoints();
993 for (Int_t i=2; i<npoints; i++)
994 {
995 pTrackPointArray->GetPoint( trackPoint, i );
996 if (!fitter.AddPoint( &trackPoint )) continue;
997 }//for i
998 TMatrixDSym fullcov = fitter.GetCovariance();
999 printf("FitTrackPointArrayKalman: the covariance matrix of the fit");
1000 fullcov.Print();
1001
1002 //now propagate to ref plane - its a hack that depends on the implementation of AddPoint()!
1003 // - first set the maxchi2 to 0 so addpoint returns false, but
1004 //actually the trackparameters have already been been propagated to the new planei, it's safe
1005 //because AliTrackFitterKalman::Propagate() is always kTRUE.
1006 fitter.SetMaxChi2(0.);
1007 fitter.AddPoint( fPRefAliTrackPoint );
1008
1009 const Double_t* pparams = fitter.GetParam();
1010 fullcov = fitter.GetCovariance();
1011
1012 pDir->SetXYZ( pparams[3], 1., pparams[4] );
1013 pPoint->SetXYZ( pparams[0], pparams[1], pparams[2] );
1014
1015 (*pPointCov)(0,0) = fullcov(0,0);(*pPointCov)(0,1) = fullcov(0,1);(*pPointCov)(0,2) = fullcov(0,2);
1016 (*pPointCov)(1,0) = fullcov(1,0);(*pPointCov)(1,1) = fullcov(1,1);(*pPointCov)(1,2) = fullcov(1,2);
1017 (*pPointCov)(2,0) = fullcov(2,0);(*pPointCov)(2,1) = fullcov(2,1);(*pPointCov)(2,2) = fullcov(2,2);
1018
1019 (*pDirCov)(0,0)=fullcov(3,3); (*pDirCov)(0,1)=0.; (*pDirCov)(0,2)=fullcov(3,4);
1020 (*pDirCov)(1,0)=0.; (*pDirCov)(1,1)=0.; (*pDirCov)(1,2)=0.;
1021 (*pDirCov)(2,0)=fullcov(4,3); (*pDirCov)(2,1)=0.; (*pDirCov)(2,2)=fullcov(4,4);
1022 return kTRUE;
1023}
1024
1025void AliRelAlignerKalman::SanitizeExtendedCovMatrix( TMatrixDSym& covout, const TMatrixDSym& pointcov, const TVector3& dir )
1026{
1027 //reverse the effect of extending of the covariance matrix along the track
1028 //direction as done by the AliTrackFitters
1029
1030 //idea is to rotate to a system where track direction is y axis,
1031 //in that refsystem setting the y related components of covariance
1032 //then rotate back.
1033 TVector3 yaxis(0,1,0);
1034 Double_t angle = dir.Angle(yaxis);
1035 TVector3 rotaxisvec = dir.Cross(yaxis);
1036 TVector3 rotaxis = rotaxisvec.Unit();
1037 TMatrixD R(3,3);
1038
1039 //Fill the rotation matrix.
1040 Double_t ex=rotaxis(0);
1041 Double_t ey=rotaxis(1);
1042 Double_t ez=rotaxis(2);
1043 Double_t sin = TMath::Sin(angle);
1044 Double_t cos = TMath::Cos(angle);
1045 Double_t icos = 1 - cos;
1046 R(0,0) = cos + (ex*ex)*icos;
1047 R(0,1) = icos*ex*ey - ez*sin;
1048 R(0,2) = icos*ex*ez + ey*sin;
1049 R(1,0) = icos*ey*ex + ez*sin;
1050 R(1,1) = cos + (ey*ey)*icos;
1051 R(1,2) = icos*ey*ez - ex*sin;
1052 R(2,0) = icos*ez*ex - ey*sin;
1053 R(2,1) = icos*ez*ey + ex*sin;
1054 R(2,2) = cos + (ez*ez)*icos;
1055
1056 //Transform covariance:
1057 TMatrixD covR( pointcov, TMatrixD::kMultTranspose, R);
1058 TMatrixD RcovR( R, TMatrixD::kMult, covR );
1059 TMatrixD newcov(3,3);
1060 newcov(0,0)=RcovR(0,0);
1061 newcov(0,2)=RcovR(0,2);
1062 newcov(2,0)=RcovR(2,0);
1063 newcov(2,2)=RcovR(2,2);
1064 newcov(1,1)=(newcov(0,0)+newcov(2,2))/2.; //this is a bit insane!!
1065 covR = newcov *R;
1066 RcovR = R.T() * covR;
1067 TMatrixDSym_from_TMatrixD( covout, RcovR );
1068}
1069
1070void AliRelAlignerKalman::JoinTrackArrays( AliTrackPointArray* pout, const AliTrackPointArray* pin1, const AliTrackPointArray* pin2 )
1071{
1072 //Join two AliTrackPointArrays
1073
1074 Int_t np1 = pin1->GetNPoints();
1075 Int_t np2 = pin2->GetNPoints();
1076 if (pout!=NULL) delete pout;
1077 pout = new AliTrackPointArray(np1+np2);
1078 AliTrackPoint p;
1079 for (Int_t i=0;i<np1;i++)
1080 {
1081 pin1->GetPoint( p, i );
1082 pout->AddPoint( i, &p );
1083 }
1084 for (Int_t i=0;i<np2;i++)
1085 {
1086 pin2->GetPoint( p, i );
1087 pout->AddPoint( i+np1, &p );
1088 }
1089}
1090
1091Bool_t AliRelAlignerKalman::ProcessTrackPointArrays()
1092{
1093 //Fit the track point arrays and update some household info
1094
1095 fFitted=kFALSE; //not fitted yet
1096 if ( !FitTrackPointArrayKalman( fPPoint2, fPPoint2Cov, fPDir2, fPDir2Cov,
1097 fPTrackPointArray2, fPVolIDArray2, fPRefAliTrackPoint ) )
1098 {
1099 fNUnfitted++;
1100 return kFALSE;
1101 }
1102
1103 if ( f3TracksMode )
1104 {
1105 if ( !FitTrackPointArrayKalman( fPPoint2b, fPPoint2bCov, fPDir2b, fPDir2bCov,
1106 fPTrackPointArray2b, fPVolIDArray2b, fPRefAliTrackPoint ) )
1107 {
1108 fNUnfitted++;
1109 return kFALSE;
1110 }
1111 }
1112
1113 if ( !FitTrackPointArrayKalman( fPPoint1, fPPoint1Cov, fPDir1, fPDir1Cov,
1114 fPTrackPointArray1, fPVolIDArray1, fPRefAliTrackPoint ) )
1115 {
1116 fNUnfitted++;
1117 return kFALSE;
1118 }
1119
1120 fFitted=kTRUE;
1121 //printf("ProcessTrackPointArrays: fitted!\n");
1122 return kTRUE;
1123}
1124
1125Bool_t AliRelAlignerKalman::UpdateCalibration()
1126{
1127 //Update the calibration with new data, used in calibration pass
1128
1129 fPThetaMesHist->Fill( (*fPMeasurement)(0) );
1130 fPPhiMesHist->Fill( (*fPMeasurement)(1) );
1131 fPXMesHist->Fill( (*fPMeasurement)(2) );
1132 fPZMesHist->Fill( (*fPMeasurement)(3) );
1133 if (f3TracksMode)
1134 {
1135 fPThetaMesHist2->Fill( (*fPMeasurement)(4) );
1136 fPPhiMesHist2->Fill( (*fPMeasurement)(5) );
1137 fPXMesHist2->Fill( (*fPMeasurement)(6) );
1138 fPZMesHist2->Fill( (*fPMeasurement)(7) );
1139 }
1140 fCalibrationUpdated=kTRUE;
1141 return kTRUE;
1142}
1143
1144Bool_t AliRelAlignerKalman::SetCalibrationPass( Bool_t cp )
1145{
1146 //sets the calibration mode
1147 if (cp)
1148 {
1149 fCalibrationPass=kTRUE;
1150 return kTRUE;
1151 }//if (cp)
1152 else
1153 {
1154 if (!fCalibrationUpdated) return kFALSE;
1155 if (fCalibrationPass) // do it only after the calibration pass
1156 {
1157 Double_t tmp;
1158 fPMeasurementCov->Zero(); //reset the covariance
1159
1160 fPThetaMesHist->Fit("gaus");
1161 TF1* fitformula = fPThetaMesHist->GetFunction("gaus");
1162 tmp = fitformula->GetParameter(2);
1163 (*fPMeasurementCov)(0,0) = tmp*tmp;
1164
1165 fPPhiMesHist->Fit("gaus");
1166 fitformula = fPPhiMesHist->GetFunction("gaus");
1167 tmp = fitformula->GetParameter(2);
1168 (*fPMeasurementCov)(1,1) = tmp*tmp;
1169
1170 fPXMesHist->Fit("gaus");
1171 fitformula = fPXMesHist->GetFunction("gaus");
1172 tmp = fitformula->GetParameter(2);
1173 (*fPMeasurementCov)(2,2) = tmp*tmp;
1174
1175 fPZMesHist->Fit("gaus");
1176 fitformula = fPZMesHist->GetFunction("gaus");
1177 tmp = fitformula->GetParameter(2);
1178 (*fPMeasurementCov)(3,3) = tmp*tmp;
1179
1180 if (f3TracksMode)
1181 {
1182 fPThetaMesHist2->Fit("gaus");
1183 fitformula = fPThetaMesHist2->GetFunction("gaus");
1184 tmp = fitformula->GetParameter(2);
1185 (*fPMeasurementCov)(4,4) = tmp*tmp;
1186
1187 fPPhiMesHist2->Fit("gaus");
1188 fitformula = fPPhiMesHist2->GetFunction("gaus");
1189 tmp = fitformula->GetParameter(2);
1190 (*fPMeasurementCov)(5,5) = tmp*tmp;
1191
1192 fPXMesHist2->Fit("gaus");
1193 fitformula = fPXMesHist2->GetFunction("gaus");
1194 tmp = fitformula->GetParameter(2);
1195 (*fPMeasurementCov)(6,6) = tmp*tmp;
1196
1197 fPZMesHist2->Fit("gaus");
1198 fitformula = fPZMesHist2->GetFunction("gaus");
1199 tmp = fitformula->GetParameter(2);
1200 (*fPMeasurementCov)(7,7) = tmp*tmp;
1201 }
1202
1203 fCalibrationPass=kFALSE;
1204 fFixedMeasurementCovariance=kTRUE;
1205 fPMeasurementCov->Print();
1206 return kTRUE;
1207 }//if (fCalibrationPass)
1208 return kFALSE;
1209 }//else (cp)
1210 return kFALSE;
1211}
1212
1213void AliRelAlignerKalman::PrintDebugInfo()
1214{
1215 //prints debug info
1216 cout<<"AliRelAlignerKalman debug info"<<endl;
1217 printf("fPTrackPointArray1 y: ");
1218 for (Int_t i=0; i<fPTrackPointArray1->GetNPoints();i++)
1219 {
1220 printf("%.2f ",fPTrackPointArray1->GetY()[i]);
1221 }
1222 printf("\n");
1223 printf("fPTrackPointArray2 y: ");
1224 for (Int_t i=0; i<fPTrackPointArray2->GetNPoints();i++)
1225 {
1226 printf("%.2f ",fPTrackPointArray2->GetY()[i]);
1227 }
1228 printf("\n");
1229 printf("fPTrackPointArray2b y: ");
1230 for (Int_t i=0; i<fPTrackPointArray2b->GetNPoints();i++)
1231 {
1232 printf("%.2f ",fPTrackPointArray2b->GetY()[i]);
1233 }
1234 printf("\n");
1235
1236 printf("Measurement covariance");
1237 fPMeasurementCov->Print();
1238}
1239