1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 ///////////////////////////////////////////////////////////////////////////////
19 // Class to make a internal alignemnt of TPC chambers //
21 // Requierements - Warnings:
22 // 1. Before using this componenent the magnetic filed has to be set properly //
23 // 2. The systematic effects - unlinearities has to be understood
25 // If systematic and unlinearities are not under control
26 // the alignment is just effective alignment. Not second order corrction
29 // The histograming of the edge effects and unlineratities integral part
30 // of the component (currently only in debug stream)
32 // 3 general type of linear transformation investigated (see bellow)
34 // By default only 6 parameter alignment to be used - other just for QA purposes
36 // Different linear tranformation investigated
37 // 12 parameters - arbitrary linear transformation
38 // a00 a01 a02 a03 p[0] p[1] p[2] p[9]
39 // a10 a11 a12 a13 ==> p[3] p[4] p[5] p[10]
40 // a20 a21 a22 a23 p[6] p[7] p[8] p[11]
42 // 9 parameters - scaling fixed to 1
43 // a00 a01 a02 a03 1 p[0] p[1] p[6]
44 // a10 a11 a12 a13 ==> p[2] 1 p[3] p[7]
45 // a20 a21 a22 a23 p[4] p[5] 1 p[8]
47 // 6 parameters - x-y rotation x-z, y-z tiliting
48 // a00 a01 a02 a03 1 -p[0] 0 p[3]
49 // a10 a11 a12 a13 ==> p[0] 1 0 p[4]
50 // a20 a21 a22 a23 p[1] p[2] 1 p[5]
53 // Debug stream supported
54 // 0. Align - The main output of the Alignment component
55 // - Used for visualization of the misalignment between sectors
56 // - Results of the missalignment fit and the mean and sigmas of histograms
58 // 1. Tracklet - StreamLevel >1
59 // - Dump all information about tracklet match from sector1 to sector 2
60 // - Default histogram residulas created in parallel
61 // - Check this streamer in case of suspicious content of these histograms
62 // 2. Track - StreamLevel>5
63 // - For debugging of the edge effects
64 // - All information - extrapolation inside of one sectors
65 // - Created in order to distinguish between unlinearities inside of o
66 // sector and missalignment
71 gSystem->AddIncludePath("-I$ALICE_ROOT/TPC/macros");
72 gROOT->LoadMacro("$ALICE_ROOT/TPC/macros/AliXRDPROOFtoolkit.cxx+")
73 AliXRDPROOFtoolkit tool;
74 TChain * chain = tool.MakeChain("align.txt","Track",0,10200);
76 TCut cutA("abs(tp1.fP[1]-tp2.fP[1])<0.3&&abs(tp1.fP[0]-tp2.fP[0])<0.15&&abs(tp1.fP[3]-tp2.fP[3])<0.01&&abs(tp1.fP[2]-tp2.fP[2])<0.01");
77 TCut cutS("s1%36==s2%36");
80 .x $ALICE_ROOT/macros/loadlibsREC.C
82 gSystem->Load("$ROOTSYS/lib/libXrdClient.so");
83 gSystem->Load("libProof");
84 gSystem->Load("libANALYSIS");
85 gSystem->Load("libSTAT");
86 gSystem->Load("libTPCcalib");
89 TFile fcalib("CalibObjects.root");
90 TObjArray * array = (TObjArray*)fcalib.Get("TPCCalib");
92 AliTPCcalibAlign * align = ( AliTPCcalibAlign *)array->FindObject("alignTPC");
96 align->MakeTree("alignTree.root");
97 TFile falignTree("alignTree.root");
98 TTree * treeAlign = (TTree*)falignTree.Get("Align");
106 #include "TLinearFitter.h"
107 #include "AliTPCcalibAlign.h"
108 #include "AliTPCROC.h"
109 #include "AliTPCPointCorrection.h"
110 #include "AliTrackPointArray.h"
112 #include "AliExternalTrackParam.h"
113 #include "AliESDEvent.h"
114 #include "AliESDfriend.h"
115 #include "AliESDtrack.h"
117 #include "AliTPCTracklet.h"
120 #include "THnSparse.h"
121 #include "TVectorD.h"
122 #include "TTreeStream.h"
126 #include "TGraphErrors.h"
127 #include "AliTPCclusterMI.h"
128 #include "AliTPCseed.h"
129 #include "AliTracker.h"
130 #include "TClonesArray.h"
131 #include "AliExternalComparison.h"
134 #include "TProfile.h"
138 #include "TTreeStream.h"
139 #include "Riostream.h"
143 AliTPCcalibAlign* AliTPCcalibAlign::fgInstance = 0;
144 ClassImp(AliTPCcalibAlign)
149 AliTPCcalibAlign* AliTPCcalibAlign::Instance()
152 // Singleton implementation
153 // Returns an instance of this class, it is created if neccessary
155 if (fgInstance == 0){
156 fgInstance = new AliTPCcalibAlign();
164 AliTPCcalibAlign::AliTPCcalibAlign()
166 fDphiHistArray(72*72),
167 fDthetaHistArray(72*72),
171 fDyPhiHistArray(72*72), // array of residual histograms y -kYPhi
172 fDzThetaHistArray(72*72), // array of residual histograms z-z -kZTheta
173 fDphiZHistArray(72*72), // array of residual histograms phi -kPhiz
174 fDthetaZHistArray(72*72), // array of residual histograms theta -kThetaz
175 fDyZHistArray(72*72), // array of residual histograms y -kYz
176 fDzZHistArray(72*72), // array of residual histograms z -kZz
177 fFitterArray12(72*72),
178 fFitterArray9(72*72),
179 fFitterArray6(72*72),
180 fMatrixArray12(72*72),
181 fMatrixArray9(72*72),
182 fMatrixArray6(72*72),
183 fCombinedMatrixArray6(72),
184 fCompTracklet(0), // tracklet comparison
189 fArraySectorIntParam(36), // array of sector alignment parameters
190 fArraySectorIntCovar(36), // array of sector alignment covariances
192 // Kalman filter for global alignment
194 fSectorParamA(0), // Kalman parameter for A side
195 fSectorCovarA(0), // Kalman covariance for A side
196 fSectorParamC(0), // Kalman parameter for A side
197 fSectorCovarC(0), // Kalman covariance for A side
198 fUseInnerOuter(kTRUE)// flag- use Inner Outer sector for left righ alignment
203 for (Int_t i=0;i<72*72;++i) {
206 AliTPCROC * roc = AliTPCROC::Instance();
207 fXquadrant = roc->GetPadRowRadii(36,53);
208 fXmiddle = ( roc->GetPadRowRadii(0,0)+roc->GetPadRowRadii(36,roc->GetNRows(36)-1))*0.5;
209 fXIO = ( roc->GetPadRowRadii(0,roc->GetNRows(0)-1)+roc->GetPadRowRadii(36,0))*0.5;
210 fClusterDelta[0]=0; // cluster residuals
211 fClusterDelta[1]=0; // cluster residuals
212 fClusterDelta[2]=0; // cluster residuals - vertex constrained
213 fClusterDelta[3]=0; // cluster residuals
214 fClusterDelta[4]=0; // cluster residuals - ITS constrained
215 fClusterDelta[5]=0; // cluster residuals
218 AliTPCcalibAlign::AliTPCcalibAlign(const Text_t *name, const Text_t *title)
220 fDphiHistArray(72*72),
221 fDthetaHistArray(72*72),
224 fDyPhiHistArray(72*72), // array of residual histograms y -kYPhi
225 fDzThetaHistArray(72*72), // array of residual histograms z-z -kZTheta
226 fDphiZHistArray(72*72), // array of residual histograms phi -kPhiz
227 fDthetaZHistArray(72*72), // array of residual histograms theta -kThetaz
228 fDyZHistArray(72*72), // array of residual histograms y -kYz
229 fDzZHistArray(72*72), // array of residual histograms z -kZz //
230 fFitterArray12(72*72),
231 fFitterArray9(72*72),
232 fFitterArray6(72*72),
233 fMatrixArray12(72*72),
234 fMatrixArray9(72*72),
235 fMatrixArray6(72*72),
236 fCombinedMatrixArray6(72),
237 fCompTracklet(0), // tracklet comparison
242 fArraySectorIntParam(36), // array of sector alignment parameters
243 fArraySectorIntCovar(36), // array of sector alignment covariances
245 // Kalman filter for global alignment
247 fSectorParamA(0), // Kalman parameter for A side
248 fSectorCovarA(0), // Kalman covariance for A side
249 fSectorParamC(0), // Kalman parameter for A side
250 fSectorCovarC(0), // Kalman covariance for A side
251 fUseInnerOuter(kTRUE)// flag- use Inner Outer sector for left righ alignment
259 for (Int_t i=0;i<72*72;++i) {
262 AliTPCROC * roc = AliTPCROC::Instance();
263 fXquadrant = roc->GetPadRowRadii(36,53);
264 fXmiddle = ( roc->GetPadRowRadii(0,0)+roc->GetPadRowRadii(36,roc->GetNRows(36)-1))*0.5;
265 fXIO = ( roc->GetPadRowRadii(0,roc->GetNRows(0)-1)+roc->GetPadRowRadii(36,0))*0.5;
266 fClusterDelta[0]=0; // cluster residuals
267 fClusterDelta[1]=0; // cluster residuals
268 fClusterDelta[2]=0; // cluster residuals - vertex constrained
269 fClusterDelta[3]=0; // cluster residuals
270 fClusterDelta[4]=0; // cluster residuals - ITS constrained
271 fClusterDelta[5]=0; // cluster residuals
278 AliTPCcalibAlign::AliTPCcalibAlign(const AliTPCcalibAlign &align)
279 :AliTPCcalibBase(align),
280 fDphiHistArray(align.fDphiHistArray),
281 fDthetaHistArray(align.fDthetaHistArray),
282 fDyHistArray(align.fDyHistArray),
283 fDzHistArray(align.fDzHistArray),
284 fDyPhiHistArray(align.fDyPhiHistArray), // array of residual histograms y -kYPhi
285 fDzThetaHistArray(align.fDzThetaHistArray), // array of residual histograms z-z -kZTheta
286 fDphiZHistArray(align.fDphiZHistArray), // array of residual histograms phi -kPhiz
287 fDthetaZHistArray(align.fDthetaZHistArray), // array of residual histograms theta -kThetaz
288 fDyZHistArray(align.fDyZHistArray), // array of residual histograms y -kYz
289 fDzZHistArray(align.fDzZHistArray), // array of residual histograms z -kZz
291 fFitterArray12(align.fFitterArray12),
292 fFitterArray9(align.fFitterArray9),
293 fFitterArray6(align.fFitterArray6),
295 fMatrixArray12(align.fMatrixArray12),
296 fMatrixArray9(align.fMatrixArray9),
297 fMatrixArray6(align.fMatrixArray6),
298 fCombinedMatrixArray6(align.fCombinedMatrixArray6),
299 fCompTracklet(align.fCompTracklet), // tracklet comparison
300 fNoField(align.fNoField),
302 fXmiddle(align.fXmiddle),
303 fXquadrant(align.fXquadrant),
304 fArraySectorIntParam(align.fArraySectorIntParam), // array of sector alignment parameters
305 fArraySectorIntCovar(align.fArraySectorIntCovar), // array of sector alignment covariances
306 fSectorParamA(0), // Kalman parameter for A side
307 fSectorCovarA(0), // Kalman covariance for A side
308 fSectorParamC(0), // Kalman parameter for A side
309 fSectorCovarC(0), // Kalman covariance for A side
310 fUseInnerOuter(kTRUE)// flag- use Inner Outer sector for left righ alignment
314 // copy constructor - copy also the content
318 const TObjArray *arr1=0;
319 for (Int_t index =0; index<72*72; index++){
320 for (Int_t iarray=0;iarray<10; iarray++){
322 arr0 = &fDyHistArray;
323 arr1 = &align.fDyHistArray;
326 arr0 = &fDzHistArray;
327 arr1 = &align.fDzHistArray;
330 arr0 = &fDphiHistArray;
331 arr1 = &align.fDphiHistArray;
334 arr0 = &fDthetaHistArray;
335 arr1 = &align.fDthetaHistArray;
338 arr0 = &fDyZHistArray;
339 arr1 = &align.fDyZHistArray;
342 arr0 = &fDzZHistArray;
343 arr1 = &align.fDzZHistArray;
346 arr0 = &fDphiZHistArray;
347 arr1 = &align.fDphiZHistArray;
349 if (iarray==kThetaZ){
350 arr0 = &fDthetaZHistArray;
351 arr1 = &align.fDthetaZHistArray;
355 arr0 = &fDyPhiHistArray;
356 arr1 = &align.fDyPhiHistArray;
358 if (iarray==kZTheta){
359 arr0 = &fDzThetaHistArray;
360 arr1 = &align.fDzThetaHistArray;
363 if (arr1->At(index)) {
364 his = (TH1*)arr1->At(index)->Clone();
365 his->SetDirectory(0);
366 arr0->AddAt(his,index);
373 if (align.fSectorParamA){
374 fSectorParamA = (TMatrixD*)align.fSectorParamA->Clone();
375 fSectorParamA = (TMatrixD*)align.fSectorCovarA->Clone();
376 fSectorParamC = (TMatrixD*)align.fSectorParamA->Clone();
377 fSectorParamC = (TMatrixD*)align.fSectorCovarA->Clone();
379 fClusterDelta[0]=0; // cluster residuals
380 fClusterDelta[1]=0; // cluster residuals
381 fClusterDelta[2]=0; // cluster residuals - vertex constrained
382 fClusterDelta[3]=0; // cluster residuals
383 fClusterDelta[4]=0; // cluster residuals - ITS constrained
384 fClusterDelta[5]=0; // cluster residuals
389 AliTPCcalibAlign::~AliTPCcalibAlign() {
393 fDphiHistArray.SetOwner(kTRUE); // array of residual histograms phi -kPhi
394 fDthetaHistArray.SetOwner(kTRUE); // array of residual histograms theta -kTheta
395 fDyHistArray.SetOwner(kTRUE); // array of residual histograms y -kY
396 fDzHistArray.SetOwner(kTRUE); // array of residual histograms z -kZ
398 fDyPhiHistArray.SetOwner(kTRUE); // array of residual histograms y -kYPhi
399 fDzThetaHistArray.SetOwner(kTRUE); // array of residual histograms z-z -kZTheta
401 fDphiZHistArray.SetOwner(kTRUE); // array of residual histograms phi -kPhiz
402 fDthetaZHistArray.SetOwner(kTRUE); // array of residual histograms theta -kThetaz
403 fDyZHistArray.SetOwner(kTRUE); // array of residual histograms y -kYz
404 fDzZHistArray.SetOwner(kTRUE); // array of residual histograms z -kZz
406 fDphiHistArray.Delete(); // array of residual histograms phi -kPhi
407 fDthetaHistArray.Delete(); // array of residual histograms theta -kTheta
408 fDyHistArray.Delete(); // array of residual histograms y -kY
409 fDzHistArray.Delete(); // array of residual histograms z -kZ
411 fDyPhiHistArray.Delete(); // array of residual histograms y -kYPhi
412 fDzThetaHistArray.Delete(); // array of residual histograms z-z -kZTheta
414 fDphiZHistArray.Delete(); // array of residual histograms phi -kPhiz
415 fDthetaZHistArray.Delete(); // array of residual histograms theta -kThetaz
416 fDyZHistArray.Delete(); // array of residual histograms y -kYz
417 fDzZHistArray.Delete(); // array of residual histograms z -kZz
419 fFitterArray12.SetOwner(kTRUE); // array of fitters
420 fFitterArray9.SetOwner(kTRUE); // array of fitters
421 fFitterArray6.SetOwner(kTRUE); // array of fitters
423 fMatrixArray12.SetOwner(kTRUE); // array of transnformtation matrix
424 fMatrixArray9.SetOwner(kTRUE); // array of transnformtation matrix
425 fMatrixArray6.SetOwner(kTRUE); // array of transnformtation matrix
427 fFitterArray12.Delete(); // array of fitters
428 fFitterArray9.Delete(); // array of fitters
429 fFitterArray6.Delete(); // array of fitters
431 fMatrixArray12.Delete(); // array of transnformtation matrix
432 fMatrixArray9.Delete(); // array of transnformtation matrix
433 fMatrixArray6.Delete(); // array of transnformtation matrix
435 if (fCompTracklet) delete fCompTracklet;
437 fArraySectorIntParam.SetOwner(kTRUE); // array of sector alignment parameters
438 fArraySectorIntCovar.SetOwner(kTRUE); // array of sector alignment covariances
439 fArraySectorIntParam.Delete(); // array of sector alignment parameters
440 fArraySectorIntCovar.Delete(); // array of sector alignment covariances
441 for (Int_t i=0; i<6; i++){
442 delete fClusterDelta[i]; // cluster residuals
446 void AliTPCcalibAlign::Process(AliESDEvent *event) {
448 // Process pairs of cosmic tracks
450 if (!fClusterDelta[0]) MakeResidualHistos();
453 ExportTrackPoints(event); // export track points for external calibration
454 const Int_t kMaxTracks =6;
455 const Int_t kminCl = 40;
456 AliESDfriend *eESDfriend=static_cast<AliESDfriend*>(event->FindListObject("AliESDfriend"));
457 if (!eESDfriend) return;
458 Int_t ntracks=event->GetNumberOfTracks();
465 for (Int_t i0=0;i0<ntracks;++i0) {
466 AliESDtrack *track0 = event->GetTrack(i0);
467 AliESDfriendTrack *friendTrack = 0;
468 TObject *calibObject=0;
469 AliTPCseed *seed0 = 0;
471 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i0);;
472 if (!friendTrack) continue;
473 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
474 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
476 if (!seed0) continue;
477 fCurrentTrack=track0;
483 // process cosmic pairs
485 if (ntracks>kMaxTracks) return;
487 //select pairs - for alignment
488 for (Int_t i0=0;i0<ntracks;++i0) {
489 AliESDtrack *track0 = event->GetTrack(i0);
490 // if (track0->GetTPCNcls()<kminCl) continue;
491 track0->GetImpactParameters(dca0[0],dca0[1]);
492 // if (TMath::Abs(dca0[0])>30) continue;
494 for (Int_t i1=0;i1<ntracks;++i1) {
495 if (i0==i1) continue;
496 AliESDtrack *track1 = event->GetTrack(i1);
497 // if (track1->GetTPCNcls()<kminCl) continue;
498 track1->GetImpactParameters(dca1[0],dca1[1]);
499 // fast cuts on dca and theta
500 // if (TMath::Abs(dca1[0]+dca0[0])>15) continue;
501 // if (TMath::Abs(dca1[1]-dca0[1])>15) continue;
502 if (TMath::Abs(track0->GetParameter()[3]+track1->GetParameter()[3])>0.1) continue;
504 AliESDfriendTrack *friendTrack = 0;
505 TObject *calibObject=0;
506 AliTPCseed *seed0 = 0,*seed1=0;
508 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i0);;
509 if (!friendTrack) continue;
510 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
511 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
513 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i1);;
514 if (!friendTrack) continue;
515 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
516 if ((seed1=dynamic_cast<AliTPCseed*>(calibObject))) break;
518 if (!seed0) continue;
521 if (!seed1) continue;
522 Int_t nclsectors0[72], nclsectors1[72];
523 for (Int_t isec=0;isec<72;isec++){
527 for (Int_t i=0;i<160;i++){
528 AliTPCclusterMI *c0=seed0->GetClusterPointer(i);
529 AliTPCclusterMI *c1=seed1->GetClusterPointer(i);
530 if (c0) nclsectors0[c0->GetDetector()]+=1;
531 if (c1) nclsectors1[c1->GetDetector()]+=1;
534 for (Int_t isec0=0; isec0<72;isec0++){
535 if (nclsectors0[isec0]<kminCl) continue;
536 for (Int_t isec1=0; isec1<72;isec1++){
537 if (nclsectors1[isec1]<kminCl) continue;
540 Double_t parLine0[10];
541 Double_t parLine1[10];
542 TMatrixD par0(4,1),cov0(4,4),par1(4,1),cov1(4,4);
543 Bool_t useInnerOuter = kFALSE;
544 if (s1%36!=s0%36) useInnerOuter = fUseInnerOuter; // for left - right alignment both sectors refit can be used if specified
545 Int_t nl0 = RefitLinear(seed0,s0, parLine0, s0,par0,cov0,fXIO,useInnerOuter);
546 Int_t nl1 = RefitLinear(seed1,s1, parLine1, s0,par1,cov1,fXIO,useInnerOuter);
547 parLine0[0]=0; // reference frame in IO boundary
549 // if (nl0<kminCl || nl1<kminCl) continue;
553 if (TMath::Min(nl0,nl1)<kminCl) isOK=kFALSE;
554 // apply selection criteria
558 dp0=par0(0,0)-par1(0,0);
559 dp1=par0(1,0)-par1(1,0);
560 dp3=par0(3,0)-par1(3,0);
561 pp0=dp0/TMath::Sqrt(cov0(0,0)+cov1(0,0)+0.1*0.1);
562 pp1=dp1/TMath::Sqrt(cov0(1,1)+cov1(1,1)+0.0015*0.0015);
563 pp3=dp3/TMath::Sqrt(cov0(3,3)+cov1(3,3)+0.0015*0.0015);
565 if (TMath::Abs(dp0)>1.0) isOK=kFALSE;
566 if (TMath::Abs(dp1)>0.02) isOK=kFALSE;
567 if (TMath::Abs(dp3)>0.02) isOK=kFALSE;
568 if (TMath::Abs(pp0)>6) isOK=kFALSE;
569 if (TMath::Abs(pp1)>6) isOK=kFALSE;
570 if (TMath::Abs(pp3)>6) isOK=kFALSE;
573 FillHisto(parLine0,parLine1,s0,s1);
574 ProcessAlign(parLine0,parLine1,s0,s1);
575 UpdateKalman(s0,s1,par0, cov0, par1, cov1);
578 TTreeSRedirector *cstream = GetDebugStreamer();
580 (*cstream)<<"cosmic"<<
599 void AliTPCcalibAlign::ExportTrackPoints(AliESDEvent *event){
601 // Export track points for alignment - calibration
602 // export space points for pairs of tracks if possible
604 AliESDfriend *eESDfriend=static_cast<AliESDfriend*>(event->FindListObject("AliESDfriend"));
605 if (!eESDfriend) return;
606 Int_t ntracks=event->GetNumberOfTracks();
607 Int_t kMaxTracks=4; // maximal number of tracks for cosmic pairs
608 Int_t kMinVertexTracks=5; // maximal number of tracks for vertex mesurement
611 const Int_t kminCl = 60;
612 const Int_t kminClSum = 120;
613 //const Double_t kDistY = 5;
614 // const Double_t kDistZ = 40;
615 const Double_t kDistTh = 0.05;
616 const Double_t kDistThS = 0.002;
617 const Double_t kDist1Pt = 0.1;
618 const Double_t kMaxD0 =3; // max distance to the primary vertex
619 const Double_t kMaxD1 =5; // max distance to the primary vertex
620 const AliESDVertex *tpcVertex = 0;
621 // get the primary vertex TPC
622 if (ntracks>kMinVertexTracks) {
623 tpcVertex = event->GetPrimaryVertexSPD();
624 if (tpcVertex->GetNContributors()<kMinVertexTracks) tpcVertex=0;
629 Int_t index0=0,index1=0;
631 for (Int_t i0=0;i0<ntracks;++i0) {
632 AliESDtrack *track0 = event->GetTrack(i0);
633 if (!track0) continue;
634 if ((track0->GetStatus() & AliESDtrack::kTPCrefit)==0) continue;
635 if (track0->GetOuterParam()==0) continue;
636 if (track0->GetInnerParam()==0) continue;
637 if (TMath::Abs(track0->GetInnerParam()->GetSigned1Pt()-track0->GetOuterParam()->GetSigned1Pt())>kDist1Pt) continue;
638 if (TMath::Abs(track0->GetInnerParam()->GetSigned1Pt())>kDist1Pt) continue;
639 if (TMath::Abs(track0->GetInnerParam()->GetTgl()-track0->GetOuterParam()->GetTgl())>kDistThS) continue;
640 AliESDtrack *track1P = 0;
641 if (track0->GetTPCNcls()<kminCl) continue;
642 track0->GetImpactParameters(dca0[0],dca0[1]);
646 if (ntracks<kMaxTracks) for (Int_t i1=i0+1;i1<ntracks;++i1) {
647 if (i0==i1) continue;
648 AliESDtrack *track1 = event->GetTrack(i1);
649 if (!track1) continue;
650 if ((track1->GetStatus() & AliESDtrack::kTPCrefit)==0) continue;
651 if (track1->GetOuterParam()==0) continue;
652 if (track1->GetInnerParam()==0) continue;
653 if (track1->GetTPCNcls()<kminCl) continue;
654 if (TMath::Abs(track1->GetInnerParam()->GetSigned1Pt()-track1->GetOuterParam()->GetSigned1Pt())>kDist1Pt) continue;
655 if (TMath::Abs(track1->GetInnerParam()->GetTgl()-track1->GetOuterParam()->GetTgl())>kDistThS) continue;
656 if (TMath::Abs(track1->GetInnerParam()->GetSigned1Pt())>kDist1Pt) continue;
657 //track1->GetImpactParameters(dca1[0],dca1[1]);
658 //if (TMath::Abs(dca1[0]-dca0[0])>kDistY) continue;
659 //if (TMath::Abs(dca1[1]-dca0[1])>kDistZ) continue;
660 if (TMath::Abs(track0->GetTgl()+track1->GetTgl())>kDistTh) continue;
661 if (TMath::Abs(track0->GetSigned1Pt()+track1->GetSigned1Pt())>kDist1Pt) continue;
665 AliESDfriendTrack *friendTrack = 0;
666 TObject *calibObject=0;
667 AliTPCseed *seed0 = 0,*seed1=0;
669 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(index0);;
670 if (!friendTrack) continue;
671 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
672 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
675 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(index1);;
676 if (!friendTrack) continue;
677 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
678 if ((seed1=dynamic_cast<AliTPCseed*>(calibObject))) break;
682 Int_t npoints=0, ncont=0;
683 if (seed0) {npoints+=seed0->GetNumberOfClusters(); ncont++;}
684 if (seed1) {npoints+=seed1->GetNumberOfClusters(); ncont++;}
685 if (npoints<kminClSum) continue;
687 AliTrackPointArray array(npoints);
689 Double_t dxyz[3]={0,0,0};
690 Double_t dc[6]={0,0,0};
691 tpcVertex->GetXYZ(dxyz);
692 tpcVertex->GetCovarianceMatrix(dc);
693 Float_t xyz[3]={dxyz[0],dxyz[1],dxyz[2]};
694 Float_t cov[6]={dc[0]+1,dc[1],dc[2]+1,dc[3],dc[4],dc[5]+100.};
695 AliTrackPoint point(xyz,cov,73); // add point to not existing volume
696 Float_t dtpc[2],dcov[3];
697 track0->GetImpactParametersTPC(dtpc,dcov);
698 if (TMath::Abs(dtpc[0])>kMaxD0) continue;
699 if (TMath::Abs(dtpc[1])>kMaxD1) continue;
702 if (seed0) for (Int_t icl = 0; icl<160; icl++){
703 AliTPCclusterMI *cluster=seed0->GetClusterPointer(icl);
704 if (!cluster) continue;
707 cluster->GetGlobalXYZ(xyz);
708 cluster->GetGlobalCov(cov);
709 AliTrackPoint point(xyz,cov,cluster->GetDetector());
710 array.AddPoint(npoints, &point);
711 if (cpoint>=npoints) continue; //shoul not happen
712 array.AddPoint(cpoint, &point);
715 if (seed1) for (Int_t icl = 0; icl<160; icl++){
716 AliTPCclusterMI *cluster=seed1->GetClusterPointer(icl);
717 if (!cluster) continue;
720 cluster->GetGlobalXYZ(xyz);
721 cluster->GetGlobalCov(cov);
722 AliTrackPoint point(xyz,cov,cluster->GetDetector());
723 array.AddPoint(npoints, &point);
724 if (cpoint>=npoints) continue; //shoul not happen
725 array.AddPoint(cpoint, &point);
731 TTreeSRedirector *cstream = GetDebugStreamer();
733 Bool_t isVertex=(tpcVertex)? kTRUE:kFALSE;
734 Double_t tof0=track0->GetTOFsignal();
735 Double_t tof1=(track1P) ? track1P->GetTOFsignal(): 0;
736 static AliExternalTrackParam dummy;
737 AliExternalTrackParam *p0In = &dummy;
738 AliExternalTrackParam *p1In = &dummy;
739 AliExternalTrackParam *p0Out = &dummy;
740 AliExternalTrackParam *p1Out = &dummy;
742 AliESDVertex *pvertex= (tpcVertex)? (AliESDVertex *)tpcVertex: &vdummy;
744 p0In= new AliExternalTrackParam(*track0);
745 p0Out=new AliExternalTrackParam(*(track0->GetOuterParam()));
748 p1In= new AliExternalTrackParam(*track1P);
749 p1Out=new AliExternalTrackParam(*(track1P->GetOuterParam()));
752 (*cstream)<<"trackPoints"<<
753 "run="<<fRun<< // run number
754 "event="<<fEvent<< // event number
755 "time="<<fTime<< // time stamp of event
756 "trigger="<<fTrigger<< // trigger
757 "triggerClass="<<&fTriggerClass<< // trigger
758 "mag="<<fMagF<< // magnetic field
759 "pvertex.="<<pvertex<< // vertex
761 "isVertex="<<isVertex<< // flag is with prim vertex
762 "tof0="<<tof0<< // tof signal 0
763 "tof1="<<tof1<< // tof signal 1
764 "seed0.="<<seed0<< // track info
765 "ntracks="<<ntracks<< // number of tracks
766 "ncont="<<ncont<< // number of contributors
767 "p0In.="<<p0In<< // track parameters0
768 "p1In.="<<p1In<< // track parameters1
769 "p0Out.="<<p0Out<< // track parameters0
770 "p1Out.="<<p1Out<< // track parameters0
780 void AliTPCcalibAlign::ProcessSeed(AliTPCseed *seed) {
784 // make a kalman tracklets out of seed
787 AliTPCTracklet::CreateTracklets(seed,AliTPCTracklet::kKalman,
789 tracklets.SetOwner();
790 Int_t ntracklets = tracklets.GetEntries();
791 if (ntracklets<2) return;
794 for (Int_t i1=0;i1<ntracklets;i1++)
795 for (Int_t i2=0;i2<ntracklets;i2++){
796 if (i1==i2) continue;
797 AliTPCTracklet *t1=static_cast<AliTPCTracklet*>(tracklets[i1]);
798 AliTPCTracklet *t2=static_cast<AliTPCTracklet*>(tracklets[i2]);
799 AliExternalTrackParam *common1=0,*common2=0;
800 if (AliTPCTracklet::PropagateToMeanX(*t1,*t2,common1,common2)){
801 ProcessTracklets(*common1,*common2,seed, t1->GetSector(),t2->GetSector());
802 UpdateAlignSector(seed,t1->GetSector());
809 void AliTPCcalibAlign::Analyze(){
817 void AliTPCcalibAlign::Terminate(){
819 // Terminate function
820 // call base terminate + Eval of fitters
822 Info("AliTPCcalibAlign","Terminate");
824 AliTPCcalibBase::Terminate();
828 void AliTPCcalibAlign::UpdatePointCorrection(AliTPCPointCorrection * correction){
830 // Update point correction with alignment coefficients
832 for (Int_t isec=0;isec<36;isec++){
833 TMatrixD * matCorr = (TMatrixD*)(correction->fArraySectorIntParam.At(isec));
834 TMatrixD * matAlign = (TMatrixD*)(fArraySectorIntParam.At(isec));
835 TMatrixD * matAlignCovar = (TMatrixD*)(fArraySectorIntCovar.At(isec));
836 if (!matAlign) continue;
838 correction->fArraySectorIntParam.AddAt(matAlign->Clone(),isec);
839 correction->fArraySectorIntCovar.AddAt(matAlignCovar->Clone(),isec);
842 (*matCorr)+=(*matAlign);
843 correction->fArraySectorIntCovar.AddAt(matAlignCovar->Clone(),isec);
850 void AliTPCcalibAlign::ProcessTracklets(const AliExternalTrackParam &tp1,
851 const AliExternalTrackParam &tp2,
852 const AliTPCseed * seed,
855 // Process function to fill fitters
857 Double_t t1[10],t2[10];
858 Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
859 Double_t &x2=t2[0], &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
863 Double_t snp1=tp1.GetSnp();
864 dydx1=snp1/TMath::Sqrt((1.-snp1)*(1.+snp1));
865 Double_t tgl1=tp1.GetTgl();
866 // dz/dx = 1/(cos(theta)*cos(phi))
867 dzdx1=tgl1/TMath::Sqrt((1.-snp1)*(1.+snp1));
871 Double_t snp2=tp2.GetSnp();
872 dydx2=snp2/TMath::Sqrt((1.-snp2)*(1.+snp2));
873 Double_t tgl2=tp2.GetTgl();
874 dzdx2=tgl2/TMath::Sqrt((1.-snp2)*(1.+snp2));
883 t1[6]=TMath::Sqrt(tp1.GetSigmaY2());
884 t1[7]=TMath::Sqrt(tp1.GetSigmaSnp2());
885 t1[8]=TMath::Sqrt(tp1.GetSigmaZ2());
886 t1[9]=TMath::Sqrt(tp1.GetSigmaTgl2());
888 t2[6]=TMath::Sqrt(tp2.GetSigmaY2());
889 t2[7]=TMath::Sqrt(tp2.GetSigmaSnp2());
890 t2[8]=TMath::Sqrt(tp2.GetSigmaZ2());
891 t2[9]=TMath::Sqrt(tp2.GetSigmaTgl2());
895 Double_t parLine1[10];
896 Double_t parLine2[10];
897 TMatrixD par1(4,1),cov1(4,4),par2(4,1),cov2(4,4);
898 Bool_t useInnerOuter = kFALSE;
899 if (s1%36!=s2%36) useInnerOuter = fUseInnerOuter; // for left - right alignment bot sectors refit can be used if specified
900 Int_t nl1 = RefitLinear(seed,s1, parLine1, s1,par1,cov1,tp1.GetX(), useInnerOuter);
901 Int_t nl2 = RefitLinear(seed,s2, parLine2, s1,par2,cov2,tp1.GetX(), useInnerOuter);
902 parLine1[0]=tp1.GetX()-fXIO; // parameters in IROC-OROC boundary
903 parLine2[0]=tp1.GetX()-fXIO; // parameters in IROC-OROC boundary
907 Int_t accept = AcceptTracklet(tp1,tp2);
908 Int_t acceptLinear = AcceptTracklet(parLine1,parLine2);
910 if (fStreamLevel>1 && seed){
911 TTreeSRedirector *cstream = GetDebugStreamer();
913 static TVectorD vec1(5);
914 static TVectorD vec2(5);
915 static TVectorD vecL1(9);
916 static TVectorD vecL2(9);
917 vec1.SetElements(t1);
918 vec2.SetElements(t2);
919 vecL1.SetElements(parLine1);
920 vecL2.SetElements(parLine2);
921 AliExternalTrackParam *p1 = &((AliExternalTrackParam&)tp1);
922 AliExternalTrackParam *p2 = &((AliExternalTrackParam&)tp2);
923 (*cstream)<<"Tracklet"<<
925 "acceptLinear="<<acceptLinear<< // accept linear tracklets
926 "run="<<fRun<< // run number
927 "event="<<fEvent<< // event number
928 "time="<<fTime<< // time stamp of event
929 "trigger="<<fTrigger<< // trigger
930 "triggerClass="<<&fTriggerClass<< // trigger
931 "mag="<<fMagF<< // magnetic field
932 "isOK="<<accept<< // flag - used for alignment
939 "nl1="<<nl1<< // linear fit - n points
940 "nl2="<<nl2<< // linear fit - n points
941 "vl1.="<<&vecL1<< // linear fits
942 "vl2.="<<&vecL2<< // linear fits
946 if (TMath::Abs(fMagF)<0.005){
950 if (nl1>10 && nl2>10 &&(acceptLinear==0)){
951 if (seed) ProcessDiff(tp1,tp2, seed,s1,s2);
952 if (TMath::Abs(parLine1[2])<0.8 &&TMath::Abs(parLine1[2])<0.8 ){ //angular cut
953 FillHisto(parLine1,parLine2,s1,s2);
954 ProcessAlign(parLine1,parLine2,s1,s2);
955 //UpdateKalman(s1,s2,par1, cov1, par2, cov2); - OBSOLETE to be removed - 50 % of time here
959 if (accept>0) return;
961 // fill resolution histograms - previous cut included
962 if (TMath::Abs(fMagF)>0.005){
964 // use Kalman if mag field
966 if (seed) ProcessDiff(tp1,tp2, seed,s1,s2);
967 FillHisto(t1,t2,s1,s2);
968 ProcessAlign(t1,t2,s1,s2);
972 void AliTPCcalibAlign::ProcessAlign(Double_t * t1,
976 // Do intersector alignment
978 //Process12(t1,t2,GetOrMakeFitter12(s1,s2));
979 //Process9(t1,t2,GetOrMakeFitter9(s1,s2));
980 Process6(t1,t2,GetOrMakeFitter6(s1,s2));
981 ++fPoints[GetIndex(s1,s2)];
984 void AliTPCcalibAlign::ProcessTree(TTree * chainTracklet, AliExternalComparison *comp){
986 // Process the debug streamer tree
987 // Possible to modify selection criteria
988 // Used with entry list
990 TTreeSRedirector * cstream = new TTreeSRedirector("aligndump.root");
992 AliTPCcalibAlign *align = this;
996 AliExternalTrackParam * tp1 = 0;
997 AliExternalTrackParam * tp2 = 0;
1002 Int_t entries=chainTracklet->GetEntries();
1003 for (Int_t i=0; i< entries; i++){
1004 chainTracklet->GetBranch("tp1.")->SetAddress(&tp1);
1005 chainTracklet->GetBranch("tp2.")->SetAddress(&tp2);
1006 chainTracklet->GetBranch("v1.")->SetAddress(&vec1);
1007 chainTracklet->GetBranch("v2.")->SetAddress(&vec2);
1008 chainTracklet->GetBranch("s1")->SetAddress(&s1);
1009 chainTracklet->GetBranch("s2")->SetAddress(&s2);
1010 chainTracklet->GetEntry(i);
1011 if (!vec1) continue;
1012 if (!vec2) continue;
1015 if (!vec1->GetMatrixArray()) continue;
1016 if (!vec2->GetMatrixArray()) continue;
1017 // make a local copy
1018 AliExternalTrackParam par1(*tp1);
1019 AliExternalTrackParam par2(*tp2);
1020 TVectorD svec1(*vec1);
1021 TVectorD svec2(*vec2);
1023 if (s1==s2) continue;
1024 if (i%100==0) printf("%d\t%d\t%d\t%d\t\n",i, npoints,s1,s2);
1025 AliExternalTrackParam cpar1(par1);
1026 AliExternalTrackParam cpar2(par2);
1027 Constrain1Pt(cpar1,par2,fNoField);
1028 Constrain1Pt(cpar2,par1,fNoField);
1029 Bool_t acceptComp = kFALSE;
1030 if (comp) acceptComp=comp->AcceptPair(&par1,&par2);
1031 if (comp) acceptComp&=comp->AcceptPair(&cpar1,&cpar2);
1033 Int_t reject = align->AcceptTracklet(par1,par2);
1034 Int_t rejectC =align->AcceptTracklet(cpar1,cpar2);
1036 if (1||fStreamLevel>0){
1037 (*cstream)<<"Tracklet"<<
1041 "rejectC="<<rejectC<<
1042 "acceptComp="<<acceptComp<<
1056 if (acceptComp) comp->Process(&cpar1,&cpar2);
1058 if (reject>0 || rejectC>0) continue;
1060 align->ProcessTracklets(cpar1,cpar2,0,s1,s2);
1061 align->ProcessTracklets(cpar2,cpar1,0,s2,s1);
1068 Int_t AliTPCcalibAlign::AcceptTracklet(const AliExternalTrackParam &p1,
1069 const AliExternalTrackParam &p2) const
1073 // Accept pair of tracklets?
1077 TCut cutS0("sqrt(tp2.fC[0]+tp1.fC[0])<0.2");
1078 TCut cutS1("sqrt(tp2.fC[2]+tp1.fC[2])<0.2");
1079 TCut cutS2("sqrt(tp2.fC[5]+tp1.fC[5])<0.01");
1080 TCut cutS3("sqrt(tp2.fC[9]+tp1.fC[9])<0.01");
1081 TCut cutS4("sqrt(tp2.fC[14]+tp1.fC[14])<0.25");
1082 TCut cutS=cutS0+cutS1+cutS2+cutS3+cutS4;
1084 // parameters matching cuts
1085 TCut cutP0("abs(tp1.fP[0]-tp2.fP[0])<0.6");
1086 TCut cutP1("abs(tp1.fP[1]-tp2.fP[1])<0.6");
1087 TCut cutP2("abs(tp1.fP[2]-tp2.fP[2])<0.03");
1088 TCut cutP3("abs(tp1.fP[3]-tp2.fP[3])<0.03");
1089 TCut cutP4("abs(tp1.fP[4]-tp2.fP[4])<0.5");
1090 TCut cutPP4("abs(tp1.fP[4]-tp2.fP[4])/sqrt(tp2.fC[14]+tp1.fC[14])<3");
1091 TCut cutP=cutP0+cutP1+cutP2+cutP3+cutP4+cutPP4;
1096 const Double_t *cp1 = p1.GetCovariance();
1097 const Double_t *cp2 = p2.GetCovariance();
1098 if (TMath::Sqrt(cp1[0]+cp2[0])>0.2) reject|=1;;
1099 if (TMath::Sqrt(cp1[2]+cp2[2])>0.2) reject|=2;
1100 if (TMath::Sqrt(cp1[5]+cp2[5])>0.01) reject|=4;
1101 if (TMath::Sqrt(cp1[9]+cp2[9])>0.01) reject|=8;
1102 if (TMath::Sqrt(cp1[14]+cp2[14])>0.2) reject|=16;
1104 //parameters difference
1105 const Double_t *tp1 = p1.GetParameter();
1106 const Double_t *tp2 = p2.GetParameter();
1107 if (TMath::Abs(tp1[0]-tp2[0])>0.6) reject|=32;
1108 if (TMath::Abs(tp1[1]-tp2[1])>0.6) reject|=64;
1109 if (TMath::Abs(tp1[2]-tp2[2])>0.03) reject|=128;
1110 if (TMath::Abs(tp1[3]-tp2[3])>0.03) reject|=526;
1111 if (TMath::Abs(tp1[4]-tp2[4])>0.4) reject|=1024;
1112 if (TMath::Abs(tp1[4]-tp2[4])/TMath::Sqrt(cp1[14]+cp2[14])>4) reject|=2048;
1115 if (TMath::Abs(tp2[1])>235) reject|=2*4096;
1125 Int_t AliTPCcalibAlign::AcceptTracklet(const Double_t *t1, const Double_t *t2) const
1128 // accept tracklet -
1129 // dist cut + 6 sigma cut
1131 Double_t dy = t2[1]-t1[1];
1132 Double_t dphi = t2[2]-t1[2];
1133 Double_t dz = t2[3]-t1[3];
1134 Double_t dtheta = t2[4]-t1[4];
1136 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]+0.05*0.05);
1137 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]+0.001*0.001);
1138 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]+0.05*0.05);
1139 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]+0.001*0.001);
1142 if (TMath::Abs(dy)>1.) reject|=2;
1143 if (TMath::Abs(dphi)>0.1) reject|=4;
1144 if (TMath::Abs(dz)>1.) reject|=8;
1145 if (TMath::Abs(dtheta)>0.1) reject|=16;
1147 if (TMath::Abs(dy/sy)>6) reject|=32;
1148 if (TMath::Abs(dphi/sdydx)>6) reject|=64;
1149 if (TMath::Abs(dz/sz)>6) reject|=128;
1150 if (TMath::Abs(dtheta/sdzdx)>6) reject|=256;
1155 void AliTPCcalibAlign::ProcessDiff(const AliExternalTrackParam &t1,
1156 const AliExternalTrackParam &t2,
1157 const AliTPCseed *seed,
1161 // Process local residuals function
1166 TVectorD vecClY(160);
1167 TVectorD vecClZ(160);
1168 TClonesArray arrCl("AliTPCclusterMI",160);
1169 arrCl.ExpandCreateFast(160);
1170 Int_t count1=0, count2=0;
1172 for (Int_t i=0;i<160;++i) {
1173 AliTPCclusterMI *c=seed->GetClusterPointer(i);
1178 AliTPCclusterMI & cl = (AliTPCclusterMI&) (*arrCl[i]);
1179 if (c->GetDetector()!=s1 && c->GetDetector()!=s2) continue;
1180 vecClY[i] = c->GetY();
1181 vecClZ[i] = c->GetZ();
1183 const AliExternalTrackParam *par = (c->GetDetector()==s1)? &t1:&t2;
1184 if (c->GetDetector()==s1) ++count1;
1185 if (c->GetDetector()==s2) ++count2;
1186 Double_t gxyz[3],xyz[3];
1188 Float_t bz = AliTracker::GetBz(gxyz);
1189 par->GetYAt(c->GetX(), bz, xyz[1]);
1190 par->GetZAt(c->GetX(), bz, xyz[2]);
1191 vecX[i] = c->GetX();
1197 if (fStreamLevel>5 && count1>10 && count2>10){
1199 // huge output - cluster residuals to be investigated
1201 TTreeSRedirector *cstream = GetDebugStreamer();
1202 AliExternalTrackParam *p1 = &((AliExternalTrackParam&)t1);
1203 AliExternalTrackParam *p2 = &((AliExternalTrackParam&)t2);
1206 Track->Draw("Cl[].fY-vtY.fElements:vtY.fElements-vtX.fElements*tan(pi/18.)>>his(100,-10,0)","Cl.fY!=0&&abs(Cl.fY-vtY.fElements)<1","prof");
1211 (*cstream)<<"Track"<<
1212 "run="<<fRun<< // run number
1213 "event="<<fEvent<< // event number
1214 "time="<<fTime<< // time stamp of event
1215 "trigger="<<fTrigger<< // trigger
1216 "triggerClass="<<&fTriggerClass<< // trigger
1217 "mag="<<fMagF<< // magnetic field
1239 void AliTPCcalibAlign::Process12(const Double_t *t1,
1241 TLinearFitter *fitter) const
1243 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1244 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1245 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1246 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1247 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1249 // a00 a01 a02 a03 p[0] p[1] p[2] p[9]
1250 // a10 a11 a12 a13 ==> p[3] p[4] p[5] p[10]
1251 // a20 a21 a22 a23 p[6] p[7] p[8] p[11]
1255 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1256 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1259 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1260 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1261 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1262 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1267 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1268 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1269 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1270 for (Int_t i=0; i<12;i++) p[i]=0.;
1275 p[0+1] = y1*dydx2; // a01
1276 p[0+2] = z1*dydx2; // a02
1277 p[9+0] = dydx2; // a03
1279 fitter->AddPoint(p,value,sy);
1281 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1282 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1283 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1284 for (Int_t i=0; i<12;i++) p[i]=0.;
1289 p[0+1] = y1*dzdx2; // a01
1290 p[0+2] = z1*dzdx2; // a02
1291 p[9+0] = dzdx2; // a03
1293 fitter->AddPoint(p,value,sz);
1295 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1296 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1297 for (Int_t i=0; i<12;i++) p[i]=0.;
1299 p[3+1] = dydx1; // a11
1300 p[3+2] = dzdx1; // a12
1301 p[0+0] = -dydx2; // a00
1302 p[0+1] = -dydx1*dydx2; // a01
1303 p[0+2] = -dzdx1*dydx2; // a02
1305 fitter->AddPoint(p,value,sdydx);
1307 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1308 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1309 for (Int_t i=0; i<12;i++) p[i]=0.;
1311 p[6+1] = dydx1; // a21
1312 p[6+2] = dzdx1; // a22
1313 p[0+0] = -dzdx2; // a00
1314 p[0+1] = -dydx1*dzdx2; // a01
1315 p[0+2] = -dzdx1*dzdx2; // a02
1317 fitter->AddPoint(p,value,sdzdx);
1320 void AliTPCcalibAlign::Process9(const Double_t * const t1,
1321 const Double_t * const t2,
1322 TLinearFitter *fitter) const
1324 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1325 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1326 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1327 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1328 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1330 // a00 a01 a02 a03 1 p[0] p[1] p[6]
1331 // a10 a11 a12 a13 ==> p[2] 1 p[3] p[7]
1332 // a20 a21 a21 a23 p[4] p[5] 1 p[8]
1335 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1336 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1338 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1339 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1340 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1341 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1347 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1348 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1349 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1350 for (Int_t i=0; i<12;i++) p[i]=0.;
1355 p[0] += y1*dydx2; // a01
1356 p[1] += z1*dydx2; // a02
1357 p[6] += dydx2; // a03
1358 value = y2-y1; //-a11
1359 fitter->AddPoint(p,value,sy);
1361 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1362 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1363 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1364 for (Int_t i=0; i<12;i++) p[i]=0.;
1369 p[0] += y1*dzdx2; // a01
1370 p[1] += z1*dzdx2; // a02
1371 p[6] += dzdx2; // a03
1372 value = z2-z1; //-a22
1373 fitter->AddPoint(p,value,sz);
1375 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1376 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1377 for (Int_t i=0; i<12;i++) p[i]=0.;
1379 //p[] += dydx1; // a11
1380 p[3] += dzdx1; // a12
1381 //p[] += -dydx2; // a00
1382 p[0] += -dydx1*dydx2; // a01
1383 p[1] += -dzdx1*dydx2; // a02
1384 value = -dydx1+dydx2; // -a11 + a00
1385 fitter->AddPoint(p,value,sdydx);
1387 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1388 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1389 for (Int_t i=0; i<12;i++) p[i]=0.;
1391 p[5] += dydx1; // a21
1392 //p[] += dzdx1; // a22
1393 //p[] += -dzdx2; // a00
1394 p[0] += -dydx1*dzdx2; // a01
1395 p[1] += -dzdx1*dzdx2; // a02
1396 value = -dzdx1+dzdx2; // -a22 + a00
1397 fitter->AddPoint(p,value,sdzdx);
1400 void AliTPCcalibAlign::Process6(const Double_t *const t1,
1401 const Double_t *const t2,
1402 TLinearFitter *fitter) const
1404 // x2 = 1 *x1 +-a01*y1 + 0 +a03
1405 // y2 = a01*x1 + 1 *y1 + 0 +a13
1406 // z2 = a20*x1 + a21*y1 + 1 *z1 +a23
1407 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1408 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1410 // a00 a01 a02 a03 1 -p[0] 0 p[3]
1411 // a10 a11 a12 a13 ==> p[0] 1 0 p[4]
1412 // a20 a21 a21 a23 p[1] p[2] 1 p[5]
1414 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1415 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1418 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1419 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1420 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1421 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1426 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1427 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1428 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1429 for (Int_t i=0; i<12;i++) p[i]=0.;
1434 p[0] += -y1*dydx2; // a01
1435 //p[] += z1*dydx2; // a02
1436 p[3] += dydx2; // a03
1437 value = y2-y1; //-a11
1438 fitter->AddPoint(p,value,sy);
1440 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1441 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1442 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1443 for (Int_t i=0; i<12;i++) p[i]=0.;
1448 p[0] += -y1*dzdx2; // a01
1449 //p[] += z1*dzdx2; // a02
1450 p[3] += dzdx2; // a03
1451 value = z2-z1; //-a22
1452 fitter->AddPoint(p,value,sz);
1454 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1455 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1456 for (Int_t i=0; i<12;i++) p[i]=0.;
1458 //p[] += dydx1; // a11
1459 //p[] += dzdx1; // a12
1460 //p[] += -dydx2; // a00
1461 //p[0] += dydx1*dydx2; // a01 FIXME- 0912 MI
1462 //p[] += -dzdx1*dydx2; // a02
1463 value = -dydx1+dydx2; // -a11 + a00
1464 fitter->AddPoint(p,value,sdydx);
1466 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1467 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1468 for (Int_t i=0; i<12;i++) p[i]=0.;
1470 // p[2] += dydx1; // a21 FIXME- 0912 MI
1471 //p[] += dzdx1; // a22
1472 //p[] += -dzdx2; // a00
1473 //p[0] += dydx1*dzdx2; // a01 FIXME- 0912 MI
1474 //p[] += -dzdx1*dzdx2; // a02
1475 value = -dzdx1+dzdx2; // -a22 + a00
1476 fitter->AddPoint(p,value,sdzdx);
1482 void AliTPCcalibAlign::EvalFitters(Int_t minPoints) {
1486 // Perform the fitting using linear fitters
1489 TFile fff("alignDebug.root","recreate");
1490 for (Int_t s1=0;s1<72;++s1)
1491 for (Int_t s2=0;s2<72;++s2){
1492 if ((f=GetFitter12(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1493 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1495 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1496 f->Write(Form("f12_%d_%d",s1,s2));
1498 f->Write(Form("f12_%d_%d",s1,s2));
1501 if ((f=GetFitter9(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1502 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1504 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1506 f->Write(Form("f9_%d_%d",s1,s2));
1509 if ((f=GetFitter6(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1510 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1512 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1514 f->Write(Form("f6_%d_%d",s1,s2));
1519 for (Int_t s1=0;s1<72;++s1)
1520 for (Int_t s2=0;s2<72;++s2){
1521 if (GetTransformation12(s1,s2,mat)){
1522 fMatrixArray12.AddAt(mat.Clone(), GetIndex(s1,s2));
1524 if (GetTransformation9(s1,s2,mat)){
1525 fMatrixArray9.AddAt(mat.Clone(), GetIndex(s1,s2));
1527 if (GetTransformation6(s1,s2,mat)){
1528 fMatrixArray6.AddAt(mat.Clone(), GetIndex(s1,s2));
1531 //this->Write("align");
1535 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter12(Int_t s1,Int_t s2) {
1537 // get or make fitter - general linear transformation
1539 static Int_t counter12=0;
1540 static TF1 f12("f12","x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]++x[9]++x[10]++x[11]");
1541 TLinearFitter * fitter = GetFitter12(s1,s2);
1542 if (fitter) return fitter;
1543 // fitter =new TLinearFitter(12,"x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]++x[9]++x[10]++x[11]");
1544 fitter =new TLinearFitter(&f12,"");
1545 fitter->StoreData(kFALSE);
1546 fFitterArray12.AddAt(fitter,GetIndex(s1,s2));
1548 // if (GetDebugLevel()>0) cerr<<"Creating fitter12 "<<s1<<","<<s2<<" : "<<counter12<<endl;
1552 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter9(Int_t s1,Int_t s2) {
1554 //get or make fitter - general linear transformation - no scaling
1556 static Int_t counter9=0;
1557 static TF1 f9("f9","x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]");
1558 TLinearFitter * fitter = GetFitter9(s1,s2);
1559 if (fitter) return fitter;
1560 // fitter =new TLinearFitter(9,"x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]");
1561 fitter =new TLinearFitter(&f9,"");
1562 fitter->StoreData(kFALSE);
1563 fFitterArray9.AddAt(fitter,GetIndex(s1,s2));
1565 // if (GetDebugLevel()>0) cerr<<"Creating fitter12 "<<s1<<","<<s2<<" : "<<counter9<<endl;
1569 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter6(Int_t s1,Int_t s2) {
1571 // get or make fitter - 6 paramater linear tranformation
1574 // - tilting x-z, y-z
1575 static Int_t counter6=0;
1576 static TF1 f6("f6","x[0]++x[1]++x[2]++x[3]++x[4]++x[5]");
1577 TLinearFitter * fitter = GetFitter6(s1,s2);
1578 if (fitter) return fitter;
1579 // fitter=new TLinearFitter(6,"x[0]++x[1]++x[2]++x[3]++x[4]++x[5]");
1580 fitter=new TLinearFitter(&f6,"");
1581 fitter->StoreData(kFALSE);
1582 fFitterArray6.AddAt(fitter,GetIndex(s1,s2));
1584 // if (GetDebugLevel()>0) cerr<<"Creating fitter6 "<<s1<<","<<s2<<" : "<<counter6<<endl;
1592 Bool_t AliTPCcalibAlign::GetTransformation12(Int_t s1,Int_t s2,TMatrixD &a) {
1594 // GetTransformation matrix - 12 paramaters - generael linear transformation
1596 if (!GetFitter12(s1,s2))
1600 GetFitter12(s1,s2)->GetParameters(p);
1602 a[0][0]=p[0]; a[0][1]=p[1]; a[0][2]=p[2]; a[0][3]=p[9];
1603 a[1][0]=p[3]; a[1][1]=p[4]; a[1][2]=p[5]; a[1][3]=p[10];
1604 a[2][0]=p[6]; a[2][1]=p[7]; a[2][2]=p[8]; a[2][3]=p[11];
1605 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1610 Bool_t AliTPCcalibAlign::GetTransformation9(Int_t s1,Int_t s2,TMatrixD &a) {
1612 // GetTransformation matrix - 9 paramaters - general linear transformation
1615 if (!GetFitter9(s1,s2))
1619 GetFitter9(s1,s2)->GetParameters(p);
1621 a[0][0]=1; a[0][1]=p[0]; a[0][2]=p[1]; a[0][3]=p[6];
1622 a[1][0]=p[2]; a[1][1]=1; a[1][2]=p[3]; a[1][3]=p[7];
1623 a[2][0]=p[4]; a[2][1]=p[5]; a[2][2]=1; a[2][3]=p[8];
1624 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1629 Bool_t AliTPCcalibAlign::GetTransformation6(Int_t s1,Int_t s2,TMatrixD &a) {
1631 // GetTransformation matrix - 6 paramaters
1634 // 2 tilting x-z y-z
1635 if (!GetFitter6(s1,s2))
1639 GetFitter6(s1,s2)->GetParameters(p);
1641 a[0][0]=1; a[0][1]=-p[0];a[0][2]=0; a[0][3]=p[3];
1642 a[1][0]=p[0]; a[1][1]=1; a[1][2]=0; a[1][3]=p[4];
1643 a[2][0]=p[1]; a[2][1]=p[2]; a[2][2]=1; a[2][3]=p[5];
1644 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1649 void AliTPCcalibAlign::MakeResidualHistos(){
1651 // Make cluster residual histograms
1653 Double_t xminTrack[9], xmaxTrack[9];
1655 TString axisName[9],axisTitle[9];
1657 // 0 - delta of interest
1658 // 1 - global phi in sector number as float
1663 axisName[0]="delta"; axisTitle[0]="#Delta (cm)";
1664 binsTrack[0]=60; xminTrack[0]=-0.6; xmaxTrack[0]=0.6;
1666 axisName[1]="sector"; axisTitle[1]="Sector Number";
1667 binsTrack[1]=180; xminTrack[1]=0; xmaxTrack[1]=18;
1669 axisName[2]="localX"; axisTitle[2]="x (cm)";
1670 binsTrack[2]=53; xminTrack[2]=85.; xmaxTrack[2]=245.;
1672 axisName[3]="kY"; axisTitle[3]="dy/dx";
1673 binsTrack[3]=1; xminTrack[3]=-0.16; xmaxTrack[3]=0.16;
1675 axisName[4]="kZ"; axisTitle[4]="dz/dx";
1676 binsTrack[4]=22; xminTrack[4]=-1.1; xmaxTrack[4]=1.1;
1678 fClusterDelta[0] = new THnSparseF("#Delta_{Y} (cm)","#Delta_{Y} (cm)", 5, binsTrack,xminTrack, xmaxTrack);
1679 fClusterDelta[1] = new THnSparseF("#Delta_{Z} (cm)","#Delta_{Z} (cm)", 5, binsTrack,xminTrack, xmaxTrack);
1680 fClusterDelta[2] = new THnSparseF("#Delta_{Y} (cm) const","#Delta_{Y} (cm) const ", 5, binsTrack,xminTrack, xmaxTrack);
1681 fClusterDelta[3] = new THnSparseF("#Delta_{Z} (cm) const","#Delta_{Z} (cm) const", 5, binsTrack,xminTrack, xmaxTrack);
1682 fClusterDelta[4] = new THnSparseF("#Delta_{Y} (cm) ITS","#Delta_{Y} (cm) ITS", 5, binsTrack,xminTrack, xmaxTrack);
1683 fClusterDelta[5] = new THnSparseF("#Delta_{Z} (cm) ITS","#Delta_{Z} (cm) ITS", 5, binsTrack,xminTrack, xmaxTrack);
1687 for (Int_t ivar=0;ivar<6;ivar++){
1688 for (Int_t ivar2=0;ivar2<5;ivar2++){
1689 fClusterDelta[ivar]->GetAxis(ivar2)->SetName(axisName[ivar2].Data());
1690 fClusterDelta[ivar]->GetAxis(ivar2)->SetTitle(axisName[ivar2].Data());
1696 void AliTPCcalibAlign::FillHisto(const Double_t *t1,
1698 Int_t s1,Int_t s2) {
1700 // Fill residual histograms
1706 Double_t dy = t2[1]-t1[1];
1707 Double_t dphi = t2[2]-t1[2];
1708 Double_t dz = t2[3]-t1[3];
1709 Double_t dtheta = t2[4]-t1[4];
1710 Double_t zmean = (t2[3]+t1[3])*0.5;
1712 GetHisto(kPhi,s1,s2,kTRUE)->Fill(dphi);
1713 GetHisto(kTheta,s1,s2,kTRUE)->Fill(dtheta);
1714 GetHisto(kY,s1,s2,kTRUE)->Fill(dy);
1715 GetHisto(kZ,s1,s2,kTRUE)->Fill(dz);
1717 GetHisto(kPhiZ,s1,s2,kTRUE)->Fill(zmean,dphi);
1718 GetHisto(kThetaZ,s1,s2,kTRUE)->Fill(zmean,dtheta);
1719 GetHisto(kYz,s1,s2,kTRUE)->Fill(zmean,dy);
1720 GetHisto(kZz,s1,s2,kTRUE)->Fill(zmean,dz);
1722 GetHisto(kYPhi,s1,s2,kTRUE)->Fill(t2[2],dy);
1723 GetHisto(kZTheta,s1,s2,kTRUE)->Fill(t2[4],dz);
1729 TH1 * AliTPCcalibAlign::GetHisto(HistoType type, Int_t s1, Int_t s2, Bool_t force)
1732 // return specified residual histogram - it is only QA
1733 // if force specified the histogram and given histogram is not existing
1734 // new histogram is created
1736 if (GetIndex(s1,s2)>=72*72) return 0;
1737 TObjArray *histoArray=0;
1740 histoArray = &fDyHistArray; break;
1742 histoArray = &fDzHistArray; break;
1744 histoArray = &fDphiHistArray; break;
1746 histoArray = &fDthetaHistArray; break;
1748 histoArray = &fDyPhiHistArray; break;
1750 histoArray = &fDzThetaHistArray; break;
1752 histoArray = &fDyZHistArray; break;
1754 histoArray = &fDzZHistArray; break;
1756 histoArray = &fDphiZHistArray; break;
1758 histoArray = &fDthetaZHistArray; break;
1760 TH1 * histo= (TH1*)histoArray->At(GetIndex(s1,s2));
1761 if (histo) return histo;
1762 if (force==kFALSE) return 0;
1768 name<<"hist_y_"<<s1<<"_"<<s2;
1769 title<<"Y Missalignment for sectors "<<s1<<" and "<<s2;
1770 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.5,0.5); // +/- 5 mm
1773 name<<"hist_z_"<<s1<<"_"<<s2;
1774 title<<"Z Missalignment for sectors "<<s1<<" and "<<s2;
1775 histo = new TH1D(name.str().c_str(),title.str().c_str(),100,-0.3,0.3); // +/- 3 mm
1778 name<<"hist_phi_"<<s1<<"_"<<s2;
1779 title<<"Phi Missalignment for sectors "<<s1<<" and "<<s2;
1780 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.01,0.01); // +/- 10 mrad
1783 name<<"hist_theta_"<<s1<<"_"<<s2;
1784 title<<"Theta Missalignment for sectors "<<s1<<" and "<<s2;
1785 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.01,0.01); // +/- 10 mrad
1790 name<<"hist_yphi_"<<s1<<"_"<<s2;
1791 title<<"Y Missalignment for sectors Phi"<<s1<<" and "<<s2;
1792 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-1,1,100,-0.5,0.5); // +/- 5 mm
1795 name<<"hist_ztheta_"<<s1<<"_"<<s2;
1796 title<<"Z Missalignment for sectors Theta"<<s1<<" and "<<s2;
1797 histo = new TH2F(name.str().c_str(),title.str().c_str(),20,-1,1,100,-0.3,0.3); // +/- 3 mm
1803 name<<"hist_yz_"<<s1<<"_"<<s2;
1804 title<<"Y Missalignment for sectors Z"<<s1<<" and "<<s2;
1805 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.5,0.5); // +/- 5 mm
1808 name<<"hist_zz_"<<s1<<"_"<<s2;
1809 title<<"Z Missalignment for sectors Z"<<s1<<" and "<<s2;
1810 histo = new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.3,0.3); // +/- 3 mm
1813 name<<"hist_phiz_"<<s1<<"_"<<s2;
1814 title<<"Phi Missalignment for sectors Z"<<s1<<" and "<<s2;
1815 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.01,0.01); // +/- 10 mrad
1818 name<<"hist_thetaz_"<<s1<<"_"<<s2;
1819 title<<"Theta Missalignment for sectors Z"<<s1<<" and "<<s2;
1820 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.01,0.01); // +/- 10 mrad
1825 histo->SetDirectory(0);
1826 histoArray->AddAt(histo,GetIndex(s1,s2));
1830 TGraphErrors * AliTPCcalibAlign::MakeGraph(Int_t sec0, Int_t sec1, Int_t dsec,
1831 Int_t i0, Int_t i1, FitType type)
1837 //TObjArray *fitArray=0;
1838 Double_t xsec[1000];
1839 Double_t ysec[1000];
1841 for (Int_t isec = sec0; isec<=sec1; isec++){
1842 Int_t isec2 = (isec+dsec)%72;
1845 GetTransformation6(isec,isec2,mat);break;
1847 GetTransformation9(isec,isec2,mat);break;
1849 GetTransformation12(isec,isec2,mat);break;
1852 ysec[npoints]=mat(i0,i1);
1855 TGraphErrors *gr = new TGraphErrors(npoints,xsec,ysec,0,0);
1857 sprintf(name,"Mat[%d,%d] Type=%d",i0,i1,type);
1862 void AliTPCcalibAlign::MakeTree(const char *fname, Int_t minPoints){
1864 // make tree with alignment cosntant -
1865 // For QA visualization
1868 TFile fcalib("CalibObjects.root");
1869 TObjArray * array = (TObjArray*)fcalib.Get("TPCCalib");
1870 AliTPCcalibAlign * align = ( AliTPCcalibAlign *)array->FindObject("alignTPC");
1871 align->EvalFitters();
1872 align->MakeTree("alignTree.root");
1873 TFile falignTree("alignTree.root");
1874 TTree * treeAlign = (TTree*)falignTree.Get("Align");
1876 TTreeSRedirector cstream(fname);
1877 for (Int_t s1=0;s1<72;++s1)
1878 for (Int_t s2=0;s2<72;++s2){
1883 TVectorD param6Diff; // align parameters diff
1884 TVectorD param6s1(6); // align parameters sector1
1885 TVectorD param6s2(6); // align parameters sector2
1889 TMatrixD * kpar = fSectorParamA;
1890 TMatrixD * kcov = fSectorCovarA;
1892 kpar = fSectorParamC;
1893 kcov = fSectorCovarC;
1895 for (Int_t ipar=0;ipar<6;ipar++){
1896 Int_t isec1 = s1%18;
1897 Int_t isec2 = s2%18;
1898 if (s1>35) isec1+=18;
1899 if (s2>35) isec2+=18;
1900 param6s1(ipar)=(*kpar)(6*isec1+ipar,0);
1901 param6s2(ipar)=(*kpar)(6*isec2+ipar,0);
1905 Double_t dy=0, dz=0, dphi=0,dtheta=0;
1906 Double_t sy=0, sz=0, sphi=0,stheta=0;
1907 Double_t ny=0, nz=0, nphi=0,ntheta=0;
1908 Double_t chi2v12=0, chi2v9=0, chi2v6=0;
1910 // TLinearFitter * fitter = 0;
1911 if (fPoints[GetIndex(s1,s2)]>minPoints){
1915 // fitter = GetFitter12(s1,s2);
1916 // npoints = fitter->GetNpoints();
1917 // chi2v12 = TMath::Sqrt(fitter->GetChisquare()/npoints);
1920 // fitter = GetFitter9(s1,s2);
1921 // npoints = fitter->GetNpoints();
1922 // chi2v9 = TMath::Sqrt(fitter->GetChisquare()/npoints);
1924 // fitter = GetFitter6(s1,s2);
1925 // npoints = fitter->GetNpoints();
1926 // chi2v6 = TMath::Sqrt(fitter->GetChisquare()/npoints);
1927 // fitter->GetParameters(param6Diff);
1929 // GetTransformation6(s1,s2,m6);
1930 // GetTransformation9(s1,s2,m9);
1931 // GetTransformation12(s1,s2,m12);
1933 // fitter = GetFitter6(s1,s2);
1934 // //fitter->FixParameter(3,0);
1935 // //fitter->Eval();
1936 // GetTransformation6(s1,s2,m6FX);
1939 his = GetHisto(kY,s1,s2);
1940 if (his) { dy = his->GetMean(); sy = his->GetRMS(); ny = his->GetEntries();}
1941 his = GetHisto(kZ,s1,s2);
1942 if (his) { dz = his->GetMean(); sz = his->GetRMS(); nz = his->GetEntries();}
1943 his = GetHisto(kPhi,s1,s2);
1944 if (his) { dphi = his->GetMean(); sphi = his->GetRMS(); nphi = his->GetEntries();}
1945 his = GetHisto(kTheta,s1,s2);
1946 if (his) { dtheta = his->GetMean(); stheta = his->GetRMS(); ntheta = his->GetEntries();}
1950 AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
1951 if (!magF) AliError("Magneticd field - not initialized");
1952 Double_t bz = magF->SolenoidField()/10.; //field in T
1955 "run="<<fRun<< // run
1957 "s1="<<s1<< // reference sector
1958 "s2="<<s2<< // sector to align
1959 "m6FX.="<<&m6FX<< // tranformation matrix
1960 "m6.="<<&m6<< // tranformation matrix
1963 "chi2v12="<<chi2v12<<
1967 "p6.="<<¶m6Diff<<
1968 "p6s1.="<<¶m6s1<<
1969 "p6s2.="<<¶m6s2<<
1970 // histograms mean RMS and entries
1989 //_____________________________________________________________________
1990 Long64_t AliTPCcalibAlign::Merge(TCollection* const list) {
1994 if (GetDebugLevel()>0) Info("AliTPCcalibAlign","Merge");
1997 if (list->IsEmpty())
2000 TIterator* iter = list->MakeIterator();
2005 TString str1(GetName());
2006 while((obj = iter->Next()) != 0)
2008 AliTPCcalibAlign* entry = dynamic_cast<AliTPCcalibAlign*>(obj);
2009 if (entry == 0) continue;
2010 if (str1.CompareTo(entry->GetName())!=0) continue;
2018 void AliTPCcalibAlign::Add(AliTPCcalibAlign * align){
2020 // Add entry - used for merging of compoents
2022 for (Int_t i=0; i<72;i++){
2023 for (Int_t j=0; j<72;j++){
2024 if (align->fPoints[GetIndex(i,j)]<1) continue;
2025 fPoints[GetIndex(i,j)]+=align->fPoints[GetIndex(i,j)];
2029 for (Int_t itype=0; itype<10; itype++){
2030 TH1 * his0=0, *his1=0;
2031 his0 = GetHisto((HistoType)itype,i,j);
2032 his1 = align->GetHisto((HistoType)itype,i,j);
2034 if (his0) his0->Add(his1);
2036 his0 = GetHisto((HistoType)itype,i,j,kTRUE);
2043 TLinearFitter *f0=0;
2044 TLinearFitter *f1=0;
2045 for (Int_t i=0; i<72;i++){
2046 for (Int_t j=0; j<72;j++){
2047 if (align->fPoints[GetIndex(i,j)]<1) continue;
2051 f0 = GetFitter12(i,j);
2052 f1 = align->GetFitter12(i,j);
2054 if (f0) f0->Add(f1);
2056 fFitterArray12.AddAt(f1->Clone(),GetIndex(i,j));
2061 f0 = GetFitter9(i,j);
2062 f1 = align->GetFitter9(i,j);
2064 if (f0) f0->Add(f1);
2066 fFitterArray9.AddAt(f1->Clone(),GetIndex(i,j));
2069 f0 = GetFitter6(i,j);
2070 f1 = align->GetFitter6(i,j);
2072 if (f0) f0->Add(f1);
2074 fFitterArray6.AddAt(f1->Clone(),GetIndex(i,j));
2080 // Add Kalman filter
2082 for (Int_t i=0;i<36;i++){
2083 TMatrixD *par0 = (TMatrixD*)fArraySectorIntParam.At(i);
2086 par0 = (TMatrixD*)fArraySectorIntParam.At(i);
2088 TMatrixD *par1 = (TMatrixD*)align->fArraySectorIntParam.At(i);
2089 if (!par1) continue;
2091 TMatrixD *cov0 = (TMatrixD*)fArraySectorIntCovar.At(i);
2092 TMatrixD *cov1 = (TMatrixD*)align->fArraySectorIntCovar.At(i);
2093 UpdateSectorKalman(*par0,*cov0,*par1,*cov1);
2095 if (!fSectorParamA){
2098 if (align->fSectorParamA){
2099 UpdateKalman(*fSectorParamA,*fSectorCovarA,*align->fSectorParamA,*align->fSectorCovarA);
2100 UpdateKalman(*fSectorParamC,*fSectorCovarC,*align->fSectorParamC,*align->fSectorCovarC);
2102 if (!fClusterDelta[1]) MakeResidualHistos();
2104 for (Int_t i=0; i<6; i++){
2106 delete fClusterDelta[i]; // memory problem do not fit into memory
2107 fClusterDelta[i]=0; //
2108 delete align->fClusterDelta[i]; // memory problem do not fit into memory
2109 align->fClusterDelta[i]=0; //
2111 if (i==3) continue; // skip constrained histo z
2112 if (i==0) continue; // skip non constrained histo y
2113 if (align->fClusterDelta[i]) fClusterDelta[i]->Add(align->fClusterDelta[i]);
2117 Double_t AliTPCcalibAlign::Correct(Int_t type, Int_t value, Int_t s1, Int_t s2, Double_t x1, Double_t y1, Double_t z1, Double_t dydx1,Double_t dzdx1){
2119 // GetTransformed value
2122 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
2123 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
2124 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
2125 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2126 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2129 const TMatrixD * mat = GetTransformation(s1,s2,type);
2131 if (value==0) return x1;
2132 if (value==1) return y1;
2133 if (value==2) return z1;
2134 if (value==3) return dydx1;
2135 if (value==4) return dzdx1;
2137 if (value==5) return dydx1;
2138 if (value==6) return dzdx1;
2144 valT = (*mat)(0,0)*x1+(*mat)(0,1)*y1+(*mat)(0,2)*z1+(*mat)(0,3);
2148 valT = (*mat)(1,0)*x1+(*mat)(1,1)*y1+(*mat)(1,2)*z1+(*mat)(1,3);
2151 valT = (*mat)(2,0)*x1+(*mat)(2,1)*y1+(*mat)(2,2)*z1+(*mat)(2,3);
2154 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2155 valT = (*mat)(1,0) +(*mat)(1,1)*dydx1 +(*mat)(1,2)*dzdx1;
2156 valT/= ((*mat)(0,0) +(*mat)(0,1)*dydx1 +(*mat)(0,2)*dzdx1);
2160 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2161 valT = (*mat)(2,0) +(*mat)(2,1)*dydx1 +(*mat)(2,2)*dzdx1;
2162 valT/= ((*mat)(0,0) +(*mat)(0,1)*dydx1 +(*mat)(0,2)*dzdx1);
2166 // onlys shift in angle
2167 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2168 valT = (*mat)(1,0) +(*mat)(1,1)*dydx1;
2172 // only shift in angle
2173 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2174 valT = (*mat)(2,0) +(*mat)(2,1)*dydx1;
2181 void AliTPCcalibAlign::Constrain1Pt(AliExternalTrackParam &track1, const AliExternalTrackParam &track2, Bool_t noField){
2183 // Update track parameters t1
2185 TMatrixD vecXk(5,1); // X vector
2186 TMatrixD covXk(5,5); // X covariance
2187 TMatrixD matHk(1,5); // vector to mesurement
2188 TMatrixD measR(1,1); // measurement error
2189 //TMatrixD matQk(5,5); // prediction noise vector
2190 TMatrixD vecZk(1,1); // measurement
2192 TMatrixD vecYk(1,1); // Innovation or measurement residual
2193 TMatrixD matHkT(5,1);
2194 TMatrixD matSk(1,1); // Innovation (or residual) covariance
2195 TMatrixD matKk(5,1); // Optimal Kalman gain
2196 TMatrixD mat1(5,5); // update covariance matrix
2197 TMatrixD covXk2(5,5); //
2198 TMatrixD covOut(5,5);
2200 Double_t *param1=(Double_t*) track1.GetParameter();
2201 Double_t *covar1=(Double_t*) track1.GetCovariance();
2204 // copy data to the matrix
2205 for (Int_t ipar=0; ipar<5; ipar++){
2206 vecXk(ipar,0) = param1[ipar];
2207 for (Int_t jpar=0; jpar<5; jpar++){
2208 covXk(ipar,jpar) = covar1[track1.GetIndex(ipar, jpar)];
2214 vecZk(0,0) = track2.GetParameter()[4]; // 1/pt measurement from track 2
2215 measR(0,0) = track2.GetCovariance()[14]; // 1/pt measurement error
2217 measR(0,0)*=0.000000001;
2221 matHk(0,0)=0; matHk(0,1)= 0; matHk(0,2)= 0;
2222 matHk(0,3)= 0; matHk(0,4)= 1; // vector to measurement
2226 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
2227 matHkT=matHk.T(); matHk.T();
2228 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
2230 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
2231 vecXk += matKk*vecYk; // updated vector
2232 mat1(0,0)=1; mat1(1,1)=1; mat1(2,2)=1; mat1(3,3)=1; mat1(4,4)=1;
2233 covXk2 = (mat1-(matKk*matHk));
2234 covOut = covXk2*covXk;
2238 // copy from matrix to parameters
2247 for (Int_t ipar=0; ipar<5; ipar++){
2248 param1[ipar]= vecXk(ipar,0) ;
2249 for (Int_t jpar=0; jpar<5; jpar++){
2250 covar1[track1.GetIndex(ipar, jpar)]=covOut(ipar,jpar);
2256 void AliTPCcalibAlign::GlobalAlign6(Int_t minPoints, Float_t sysError, Int_t niter){
2258 // Global Align -combine the partial alignment of pair of sectors
2259 // minPoints - minimal number of points - don't use sector alignment wit smaller number
2260 // sysError - error added to the alignemnt error
2262 AliTPCcalibAlign * align = this;
2263 TMatrixD * arrayAlign[72];
2264 TMatrixD * arrayAlignDiff[72];
2266 for (Int_t i=0;i<72; i++) {
2267 TMatrixD * mat = new TMatrixD(4,4);
2270 arrayAlignDiff[i]=(TMatrixD*)(mat->Clone());
2273 TTreeSRedirector *cstream = new TTreeSRedirector("galign6.root");
2274 for (Int_t iter=0; iter<niter;iter++){
2275 printf("Iter=\t%d\n",iter);
2276 for (Int_t is0=0;is0<72; is0++) {
2278 //TMatrixD *mati0 = arrayAlign[is0];
2279 TMatrixD matDiff(4,4);
2281 for (Int_t is1=0;is1<72; is1++) {
2282 Bool_t invers=kFALSE;
2286 const TMatrixD *mat = align->GetTransformation(is0,is1,0);
2288 npoints = align->GetFitter6(is0,is1)->GetNpoints();
2289 if (npoints>minPoints){
2290 align->GetFitter6(is0,is1)->GetCovarianceMatrix(covar);
2291 align->GetFitter6(is0,is1)->GetErrors(errors);
2296 mat = align->GetTransformation(is1,is0,0);
2298 npoints = align->GetFitter6(is1,is0)->GetNpoints();
2299 if (npoints>minPoints){
2300 align->GetFitter6(is1,is0)->GetCovarianceMatrix(covar);
2301 align->GetFitter6(is1,is0)->GetErrors(errors);
2306 if (npoints<minPoints) continue;
2309 if (is1/36>is0/36) weight*=2./3.; //IROC-OROC
2310 if (is1/36<is0/36) weight*=1./3.; //OROC-IROC
2311 if (is1/36==is0/36) weight*=1/3.; //OROC-OROC
2312 if (is1%36!=is0%36) weight*=1/2.; //Not up-down
2313 weight/=(errors[4]*errors[4]+sysError*sysError); // wieghting with error in Y
2316 TMatrixD matT = *mat;
2317 if (invers) matT.Invert();
2318 TMatrixD diffMat= (*(arrayAlign[is1]))*matT;
2319 diffMat-=(*arrayAlign[is0]);
2320 matDiff+=weight*diffMat;
2323 (*cstream)<<"LAlign"<<
2327 "npoints="<<npoints<<
2328 "m60.="<<arrayAlign[is0]<<
2329 "m61.="<<arrayAlign[is1]<<
2331 "diff.="<<&diffMat<<
2342 (*arrayAlignDiff[is0]) = matDiff;
2345 for (Int_t is0=0;is0<72; is0++) {
2346 if (is0<36) (*arrayAlign[is0]) += 0.4*(*arrayAlignDiff[is0]);
2347 if (is0>=36) (*arrayAlign[is0]) += 0.2*(*arrayAlignDiff[is0]);
2349 (*cstream)<<"GAlign"<<
2352 "m6.="<<arrayAlign[is0]<<
2358 for (Int_t isec=0;isec<72;isec++){
2359 fCombinedMatrixArray6.AddAt(arrayAlign[isec],isec);
2360 delete arrayAlignDiff[isec];
2365 Int_t AliTPCcalibAlign::RefitLinear(const AliTPCseed * track, Int_t isec, Double_t *fitParam, Int_t refSector, TMatrixD &tparam, TMatrixD&tcovar, Double_t xRef, Bool_t both){
2367 // Refit tracklet linearly using clusters at given sector isec
2368 // Clusters are rotated to the reference frame of sector refSector
2370 // fit parameters and errors retruning in the fitParam
2372 // seed - acces to the original clusters
2373 // isec - sector to be refited
2385 // ref sector is the sector defining ref frame - rotation
2386 // return value - number of used clusters
2388 const Int_t kMinClusterF=15;
2389 const Int_t kdrow1 =10; // rows to skip at the end
2390 const Int_t kdrow0 =3; // rows to skip at beginning
2391 const Float_t kedgeyIn=2.5;
2392 const Float_t kedgeyOut=4.0;
2393 const Float_t kMaxDist=5; // max distance -in sigma
2394 const Float_t kMaxCorrY=0.05; // max correction
2396 Double_t dalpha = 0;
2397 if ((refSector%18)!=(isec%18)){
2398 dalpha = -((refSector%18)-(isec%18))*TMath::TwoPi()/18.;
2400 Double_t ca = TMath::Cos(dalpha);
2401 Double_t sa = TMath::Sin(dalpha);
2404 AliTPCPointCorrection * corr = AliTPCPointCorrection::Instance();
2406 // full track fit parameters
2408 static TLinearFitter fyf(2,"pol1"); // change to static - suggestion of calgrind - 30 % of time
2409 static TLinearFitter fzf(2,"pol1"); // relative to time of given class
2410 TVectorD pyf(2), peyf(2),pzf(2), pezf(2);
2411 TMatrixD covY(4,4),covZ(4,4);
2412 Double_t chi2FacY =1;
2413 Double_t chi2FacZ =1;
2418 Float_t erry=0.1; // initial cluster error estimate
2419 Float_t errz=0.1; // initial cluster error estimate
2420 for (Int_t iter=0; iter<2; iter++){
2423 for (Int_t irow=kdrow0;irow<159-kdrow1;irow++) {
2424 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2427 if (c->GetDetector()%36!=(isec%36)) continue;
2428 if (!both && c->GetDetector()!=isec) continue;
2430 if (c->GetRow()<kdrow0) continue;
2431 //cluster position in reference frame
2432 Double_t lxR = ca*c->GetX()-sa*c->GetY();
2433 Double_t lyR = +sa*c->GetX()+ca*c->GetY();
2434 Double_t lzR = c->GetZ();
2436 Double_t dx = lxR -xRef; // distance to reference X
2437 Double_t x[2]={dx, dx*dx};
2439 Double_t yfitR = pyf[0]+pyf[1]*dx; // fit value Y in ref frame
2440 Double_t zfitR = pzf[0]+pzf[1]*dx; // fit value Z in ref frame
2442 Double_t yfit = -sa*lxR + ca*yfitR; // fit value Y in local frame
2444 if (iter==0 &&c->GetType()<0) continue;
2446 if (TMath::Abs(lyR-yfitR)>kMaxDist*erry) continue;
2447 if (TMath::Abs(lzR-zfitR)>kMaxDist*errz) continue;
2448 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2449 if (isec<36 && dedge<kedgeyIn) continue;
2450 if (isec>35 && dedge<kedgeyOut) continue;
2452 corr->RPhiCOGCorrection(isec,c->GetRow(), c->GetPad(),
2453 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2455 corr->RPhiCOGCorrection(isec,c->GetRow(), c->GetPad(),
2456 c->GetY(),c->GetY(), c->GetZ(), pyf[1], c->GetMax(),2.5);
2457 if (TMath::Abs((corrtrY+corrclY)*0.5)>kMaxCorrY) continue;
2458 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2460 fyf.AddPoint(x,lyR,erry);
2461 fzf.AddPoint(x,lzR,errz);
2463 nf = fyf.GetNpoints();
2464 if (nf<kMinClusterF) return 0; // not enough points - skip
2466 fyf.GetParameters(pyf);
2467 fyf.GetErrors(peyf);
2469 fzf.GetParameters(pzf);
2470 fzf.GetErrors(pezf);
2471 chi2FacY = TMath::Sqrt(fyf.GetChisquare()/(fyf.GetNpoints()-2.));
2472 chi2FacZ = TMath::Sqrt(fzf.GetChisquare()/(fzf.GetNpoints()-2.));
2479 fyf.GetCovarianceMatrix(covY);
2480 fzf.GetCovarianceMatrix(covZ);
2481 for (Int_t i0=0;i0<2;i0++)
2482 for (Int_t i1=0;i1<2;i1++){
2483 covY(i0,i1)*=chi2FacY*chi2FacY;
2484 covZ(i0,i1)*=chi2FacZ*chi2FacZ;
2489 fitParam[1] = pyf[0];
2490 fitParam[2] = pyf[1];
2491 fitParam[3] = pzf[0];
2492 fitParam[4] = pzf[1];
2495 fitParam[6] = peyf[0];
2496 fitParam[7] = peyf[1];
2497 fitParam[8] = pezf[0];
2498 fitParam[9] = pezf[1];
2501 tparam(0,0) = pyf[0];
2502 tparam(1,0) = pyf[1];
2503 tparam(2,0) = pzf[0];
2504 tparam(3,0) = pzf[1];
2506 tcovar(0,0) = covY(0,0);
2507 tcovar(1,1) = covY(1,1);
2508 tcovar(1,0) = covY(1,0);
2509 tcovar(0,1) = covY(0,1);
2510 tcovar(2,2) = covZ(0,0);
2511 tcovar(3,3) = covZ(1,1);
2512 tcovar(3,2) = covZ(1,0);
2513 tcovar(2,3) = covZ(0,1);
2517 void AliTPCcalibAlign::UpdateAlignSector(const AliTPCseed * track,Int_t isec){
2519 // Update Kalman filter of Alignment
2520 // IROC - OROC quadrants
2522 if (!fClusterDelta[0]) MakeResidualHistos();
2523 const Int_t kMinClusterF=40;
2524 const Int_t kMinClusterQ=10;
2526 const Int_t kdrow1Fit =5; // rows to skip from fit at the end
2527 const Int_t kdrow0Fit =10; // rows to skip from fit at beginning
2528 const Float_t kedgey=3.0;
2529 const Float_t kMaxDist=1;
2530 const Float_t kMaxCorrY=0.05;
2531 const Float_t kPRFWidth = 0.6; //cut 2 sigma of PRF
2532 isec = isec%36; // use the hardware numbering
2535 AliTPCPointCorrection * corr = AliTPCPointCorrection::Instance();
2537 // full track fit parameters
2539 static TLinearFitter fyf(2,"pol1"); // make it static - too much time for comiling of formula
2540 static TLinearFitter fzf(2,"pol1"); // calgrind recomendation
2541 TVectorD pyf(2), peyf(2),pzf(2), pezf(2);
2542 TVectorD pyfc(2),pzfc(2);
2545 // make full fit as reference
2547 for (Int_t iter=0; iter<2; iter++){
2550 for (Int_t irow=kdrow0Fit;irow<159-kdrow1Fit;irow++) {
2551 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2553 if ((c->GetDetector()%36)!=isec) continue;
2554 if (c->GetRow()<kdrow0Fit) continue;
2555 Double_t dx = c->GetX()-fXmiddle;
2556 Double_t x[2]={dx, dx*dx};
2557 if (iter==0 &&c->GetType()<0) continue;
2559 Double_t yfit = pyf[0]+pyf[1]*dx;
2560 Double_t zfit = pzf[0]+pzf[1]*dx;
2561 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2562 if (TMath::Abs(c->GetY()-yfit)>kMaxDist) continue;
2563 if (TMath::Abs(c->GetZ()-zfit)>kMaxDist) continue;
2564 if (dedge<kedgey) continue;
2566 corr->RPhiCOGCorrection(c->GetDetector(),c->GetRow(), c->GetPad(),
2567 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2568 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2570 fyf.AddPoint(x,c->GetY(),0.1);
2571 fzf.AddPoint(x,c->GetZ(),0.1);
2573 nf = fyf.GetNpoints();
2574 if (nf<kMinClusterF) return; // not enough points - skip
2576 fyf.GetParameters(pyf);
2577 fyf.GetErrors(peyf);
2579 fzf.GetParameters(pzf);
2580 fzf.GetErrors(pezf);
2585 TVectorD vecX(2*nf+kdrow0Fit+kdrow1Fit+5); // x vector
2586 TVectorD vecY(2*nf+kdrow0Fit+kdrow1Fit+5); // residuals vector
2587 TVectorD vecZ(2*nf+kdrow0Fit+kdrow1Fit+5); // residuals vector
2588 TVectorD vPosG(3); //vertex position
2589 TVectorD vPosL(3); // vertex position in the TPC local system
2590 TVectorF vImpact(2); //track impact parameter
2591 Double_t tofSignal= fCurrentTrack->GetTOFsignal(); // tof signal
2592 TVectorF tpcPosG(3); // global position of track at the middle of fXmiddle
2593 Double_t lphi = TMath::ATan2(pyf[0],fXmiddle); // expected local phi angle - if vertex at 0
2594 Double_t gphi = 2.*TMath::Pi()*(isec%18+0.5)/18.+lphi; // expected global phi if vertex at 0
2595 Double_t ky = pyf[0]/fXmiddle;
2596 Double_t kyE =0, kzE=0; // ky and kz expected
2597 Double_t alpha =2.*TMath::Pi()*(isec%18+0.5)/18.;
2598 Double_t scos=TMath::Cos(alpha);
2599 Double_t ssin=TMath::Sin(alpha);
2600 const AliESDVertex* vertex = fCurrentEvent->GetPrimaryVertexTracks();
2601 vertex->GetXYZ(vPosG.GetMatrixArray());
2602 fCurrentTrack->GetImpactParameters(vImpact[0],vImpact[1]); // track impact parameters
2604 tpcPosG[0]= scos*fXmiddle-ssin*pyf[0];
2605 tpcPosG[1]=+ssin*fXmiddle+scos*pyf[0];
2607 vPosL[0]= scos*vPosG[0]+ssin*vPosG[1];
2608 vPosL[1]=-ssin*vPosG[0]+scos*vPosG[1];
2610 kyE = (pyf[0]-vPosL[1])/(fXmiddle-vPosL[0]);
2611 kzE = (pzf[0]-vPosL[2])/(fXmiddle-vPosL[0]);
2613 // get constrained parameters
2615 Double_t xvertex=vPosL[0]-fXmiddle;
2616 fyf.AddPoint(&xvertex,vPosL[1], 0.1+TMath::Abs(vImpact[0]));
2617 fzf.AddPoint(&xvertex,vPosL[2], 0.1+TMath::Abs(vImpact[1]));
2619 fyf.GetParameters(pyfc);
2621 fzf.GetParameters(pzfc);
2624 // Make Fitters and params for 5 fitters
2625 // 1-4 OROC quadrants
2628 static TLinearFitter *fittersY[5]={0,0,0,0,0}; // calgrind recomendation - fater to clear points
2629 static TLinearFitter *fittersZ[5]={0,0,0,0,0}; // than create the fitter
2630 if (fittersY[0]==0){
2631 for (Int_t i=0;i<5;i++) {
2632 fittersY[i] = new TLinearFitter(2,"pol1");
2633 fittersZ[i] = new TLinearFitter(2,"pol1");
2638 TVectorD paramsY[5];
2639 TVectorD errorsY[5];
2642 TVectorD paramsZ[5];
2643 TVectorD errorsZ[5];
2646 for (Int_t i=0;i<5;i++) {
2648 paramsY[i].ResizeTo(2);
2649 errorsY[i].ResizeTo(2);
2650 covY[i].ResizeTo(2,2);
2651 paramsZ[i].ResizeTo(2);
2652 errorsZ[i].ResizeTo(2);
2653 covZ[i].ResizeTo(2,2);
2654 fittersY[i]->ClearPoints();
2655 fittersZ[i]->ClearPoints();
2661 for (Int_t irow=0;irow<159;irow++) {
2662 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2664 if ((c->GetDetector()%36)!=isec) continue;
2665 Double_t dx = c->GetX()-fXmiddle;
2666 Double_t x[2]={dx, dx*dx};
2667 Double_t yfit = pyf[0]+pyf[1]*dx;
2668 Double_t zfit = pzf[0]+pzf[1]*dx;
2669 Double_t yfitC = pyfc[0]+pyfc[1]*dx;
2670 Double_t zfitC = pzfc[0]+pzfc[1]*dx;
2671 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2672 if (TMath::Abs(c->GetY()-yfit)>kMaxDist) continue;
2673 if (TMath::Abs(c->GetZ()-zfit)>kMaxDist) continue;
2674 if (dedge<kedgey) continue;
2676 corr->RPhiCOGCorrection(c->GetDetector(),c->GetRow(), c->GetPad(),
2677 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2678 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2680 vecX[countRes]=c->GetX();
2681 vecY[countRes]=c->GetY()-yfit;
2682 vecZ[countRes]=c->GetZ()-zfit;
2685 // Fill THnSparse cluster residuals
2686 // use only primary candidates with ITS signal
2687 if (nf>100&&fCurrentTrack->IsOn(0x4)&&TMath::Abs(vImpact[0])<1&&TMath::Abs(vImpact[1])<1){
2688 Double_t resVector[5];
2689 resVector[1]= 9.*gphi/TMath::Pi();
2690 resVector[2]= c->GetX();
2691 resVector[3]= c->GetY()/c->GetX();
2692 resVector[4]= c->GetZ()/c->GetX();
2694 resVector[0]= c->GetY()-yfit;
2695 //fClusterDelta[0]->Fill(resVector);
2696 resVector[0]= c->GetZ()-zfit;
2697 fClusterDelta[1]->Fill(resVector);
2699 resVector[0]= c->GetY()-yfitC;
2700 fClusterDelta[2]->Fill(resVector);
2701 resVector[0]= c->GetZ()-zfitC;
2702 //fClusterDelta[3]->Fill(resVector);
2705 if (c->GetRow()<kdrow0Fit) continue;
2706 if (c->GetRow()>159-kdrow1Fit) continue;
2709 if (c->GetDetector()>35){
2710 if (c->GetX()<fXquadrant){
2711 if (yfit<-kPRFWidth) fittersY[1]->AddPoint(x,c->GetY(),0.1);
2712 if (yfit<-kPRFWidth) fittersZ[1]->AddPoint(x,c->GetZ(),0.1);
2713 if (yfit>kPRFWidth) fittersY[2]->AddPoint(x,c->GetY(),0.1);
2714 if (yfit>kPRFWidth) fittersZ[2]->AddPoint(x,c->GetZ(),0.1);
2716 if (c->GetX()>fXquadrant){
2717 if (yfit<-kPRFWidth) fittersY[3]->AddPoint(x,c->GetY(),0.1);
2718 if (yfit<-kPRFWidth) fittersZ[3]->AddPoint(x,c->GetZ(),0.1);
2719 if (yfit>kPRFWidth) fittersY[4]->AddPoint(x,c->GetY(),0.1);
2720 if (yfit>kPRFWidth) fittersZ[4]->AddPoint(x,c->GetZ(),0.1);
2723 if (c->GetDetector()<36){
2724 fittersY[0]->AddPoint(x,c->GetY(),0.1);
2725 fittersZ[0]->AddPoint(x,c->GetZ(),0.1);
2731 for (Int_t i=0;i<5;i++) {
2732 npoints[i] = fittersY[i]->GetNpoints();
2733 if (npoints[i]>=kMinClusterQ){
2735 fittersY[i]->Eval();
2736 Double_t chi2FacY = TMath::Sqrt(fittersY[i]->GetChisquare()/(fittersY[i]->GetNpoints()-2));
2738 fittersY[i]->GetParameters(paramsY[i]);
2739 fittersY[i]->GetErrors(errorsY[i]);
2740 fittersY[i]->GetCovarianceMatrix(covY[i]);
2741 // renormalize errors
2742 errorsY[i][0]*=chi2FacY;
2743 errorsY[i][1]*=chi2FacY;
2744 covY[i](0,0)*=chi2FacY*chi2FacY;
2745 covY[i](0,1)*=chi2FacY*chi2FacY;
2746 covY[i](1,0)*=chi2FacY*chi2FacY;
2747 covY[i](1,1)*=chi2FacY*chi2FacY;
2749 fittersZ[i]->Eval();
2750 Double_t chi2FacZ = TMath::Sqrt(fittersZ[i]->GetChisquare()/(fittersZ[i]->GetNpoints()-2));
2752 fittersZ[i]->GetParameters(paramsZ[i]);
2753 fittersZ[i]->GetErrors(errorsZ[i]);
2754 fittersZ[i]->GetCovarianceMatrix(covZ[i]);
2755 // renormalize errors
2756 errorsZ[i][0]*=chi2FacZ;
2757 errorsZ[i][1]*=chi2FacZ;
2758 covZ[i](0,0)*=chi2FacZ*chi2FacZ;
2759 covZ[i](0,1)*=chi2FacZ*chi2FacZ;
2760 covZ[i](1,0)*=chi2FacZ*chi2FacZ;
2761 covZ[i](1,1)*=chi2FacZ*chi2FacZ;
2765 // void UpdateSectorKalman
2767 for (Int_t i0=0;i0<5;i0++){
2768 for (Int_t i1=i0+1;i1<5;i1++){
2769 if(npoints[i0]<kMinClusterQ) continue;
2770 if(npoints[i1]<kMinClusterQ) continue;
2771 TMatrixD v0(4,1),v1(4,1); // measurement
2772 TMatrixD cov0(4,4),cov1(4,4); // covariance
2774 v0(0,0)= paramsY[i0][0]; v1(0,0)= paramsY[i1][0];
2775 v0(1,0)= paramsY[i0][1]; v1(1,0)= paramsY[i1][1];
2776 v0(2,0)= paramsZ[i0][0]; v1(2,0)= paramsZ[i1][0];
2777 v0(3,0)= paramsZ[i0][1]; v1(3,0)= paramsZ[i1][1];
2779 cov0(0,0) = covY[i0](0,0);
2780 cov0(1,1) = covY[i0](1,1);
2781 cov0(1,0) = covY[i0](1,0);
2782 cov0(0,1) = covY[i0](0,1);
2783 cov0(2,2) = covZ[i0](0,0);
2784 cov0(3,3) = covZ[i0](1,1);
2785 cov0(3,2) = covZ[i0](1,0);
2786 cov0(2,3) = covZ[i0](0,1);
2788 cov1(0,0) = covY[i1](0,0);
2789 cov1(1,1) = covY[i1](1,1);
2790 cov1(1,0) = covY[i1](1,0);
2791 cov1(0,1) = covY[i1](0,1);
2792 cov1(2,2) = covZ[i1](0,0);
2793 cov1(3,3) = covZ[i1](1,1);
2794 cov1(3,2) = covZ[i1](1,0);
2795 cov1(2,3) = covZ[i1](0,1);
2799 if (TMath::Abs(pyf[1])<0.8){ //angular cut
2800 UpdateSectorKalman(isec, i0,i1, &v0,&cov0,&v1,&cov1);
2806 // Dump debug information
2808 if (fStreamLevel>0){
2809 // get vertex position
2811 TTreeSRedirector *cstream = GetDebugStreamer();
2815 for (Int_t i0=0;i0<5;i0++){
2816 for (Int_t i1=i0;i1<5;i1++){
2817 if (i0==i1) continue;
2818 if(npoints[i0]<kMinClusterQ) continue;
2819 if(npoints[i1]<kMinClusterQ) continue;
2820 (*cstream)<<"sectorAlign"<<
2821 "run="<<fRun<< // run number
2822 "event="<<fEvent<< // event number
2823 "time="<<fTime<< // time stamp of event
2824 "trigger="<<fTrigger<< // trigger
2825 "triggerClass="<<&fTriggerClass<< // trigger
2826 "mag="<<fMagF<< // magnetic field
2827 "isec="<<isec<< // current sector
2829 "xref="<<fXmiddle<< // reference X
2830 "vPosG.="<<&vPosG<< // vertex position in global system
2831 "vPosL.="<<&vPosL<< // vertex position in local system
2832 "vImpact.="<<&vImpact<< // track impact parameter
2833 "tofSignal="<<tofSignal<< // tof signal
2834 "tpcPosG.="<<&tpcPosG<< // global position of track at the middle of fXmiddle
2835 "lphi="<<lphi<< // expected local phi angle - if vertex at 0
2836 "gphi="<<gphi<< // expected global phi if vertex at 0
2838 "kyE="<<kyE<< // expect ky - assiming pirmary track
2839 "kzE="<<kzE<< // expected kz - assuming primary tracks
2840 "salpha="<<alpha<< // sector alpha
2841 "scos="<<scos<< // tracking cosinus
2842 "ssin="<<ssin<< // tracking sinus
2846 "nf="<<nf<< // total number of points
2847 "pyf.="<<&pyf<< // full OROC fit y
2848 "pzf.="<<&pzf<< // full OROC fit z
2849 "vX.="<<&vecX<< // x cluster
2850 "vY.="<<&vecY<< // y residual cluster
2851 "vZ.="<<&vecZ<< // z residual cluster
2852 // quadrant and IROC fit
2853 "i0="<<i0<< // quadrant number
2855 "n0="<<npoints[i0]<< // number of points
2856 "n1="<<npoints[i1]<<
2858 "py0.="<<¶msY[i0]<< // parameters
2859 "py1.="<<¶msY[i1]<<
2860 "ey0.="<<&errorsY[i0]<< // errors
2861 "ey1.="<<&errorsY[i1]<<
2862 "chiy0="<<chi2CY[i0]<< // chi2s
2863 "chiy1="<<chi2CY[i1]<<
2865 "pz0.="<<¶msZ[i0]<< // parameters
2866 "pz1.="<<¶msZ[i1]<<
2867 "ez0.="<<&errorsZ[i0]<< // errors
2868 "ez1.="<<&errorsZ[i1]<<
2869 "chiz0="<<chi2CZ[i0]<< // chi2s
2870 "chiz1="<<chi2CZ[i1]<<
2878 void AliTPCcalibAlign::UpdateSectorKalman(Int_t sector, Int_t quadrant0, Int_t quadrant1, TMatrixD *const p0, TMatrixD *const c0, TMatrixD *const p1, TMatrixD *const c1 ){
2881 // tracks are refitted at sector middle
2883 if (fArraySectorIntParam.At(0)==NULL) MakeSectorKalman();
2886 static TMatrixD matHk(4,30); // vector to mesurement
2887 static TMatrixD measR(4,4); // measurement error
2888 // static TMatrixD matQk(2,2); // prediction noise vector
2889 static TMatrixD vecZk(4,1); // measurement
2891 static TMatrixD vecYk(4,1); // Innovation or measurement residual
2892 static TMatrixD matHkT(30,4); // helper matrix Hk transpose
2893 static TMatrixD matSk(4,4); // Innovation (or residual) covariance
2894 static TMatrixD matKk(30,4); // Optimal Kalman gain
2895 static TMatrixD mat1(30,30); // update covariance matrix
2896 static TMatrixD covXk2(30,30); // helper matrix
2898 TMatrixD *vOrig = (TMatrixD*)(fArraySectorIntParam.At(sector));
2899 TMatrixD *cOrig = (TMatrixD*)(fArraySectorIntCovar.At(sector));
2901 TMatrixD vecXk(*vOrig); // X vector
2902 TMatrixD covXk(*cOrig); // X covariance
2906 for (Int_t i=0;i<30;i++)
2907 for (Int_t j=0;j<30;j++){
2909 if (i==j) mat1(i,j)=1;
2913 // matHk - vector to measurement
2915 for (Int_t i=0;i<4;i++)
2916 for (Int_t j=0;j<30;j++){
2926 matHk(0,6*quadrant1+4) = 1.; // delta y
2927 matHk(1,6*quadrant1+0) = 1.; // delta ky
2928 matHk(2,6*quadrant1+5) = 1.; // delta z
2929 matHk(3,6*quadrant1+1) = 1.; // delta kz
2930 // bug fix 24.02 - aware of sign in dx
2931 matHk(0,6*quadrant1+3) = -(*p0)(1,0); // delta x to delta y - through ky
2932 matHk(2,6*quadrant1+3) = -(*p0)(3,0); // delta x to delta z - thorugh kz
2933 matHk(2,6*quadrant1+2) = ((*p0)(0,0)); // y to delta z - through psiz
2935 matHk(0,6*quadrant0+4) = -1.; // delta y
2936 matHk(1,6*quadrant0+0) = -1.; // delta ky
2937 matHk(2,6*quadrant0+5) = -1.; // delta z
2938 matHk(3,6*quadrant0+1) = -1.; // delta kz
2939 // bug fix 24.02 be aware of sign in dx
2940 matHk(0,6*quadrant0+3) = ((*p0)(1,0)); // delta x to delta y - through ky
2941 matHk(2,6*quadrant0+3) = ((*p0)(3,0)); // delta x to delta z - thorugh kz
2942 matHk(2,6*quadrant0+2) = -((*p0)(0,0)); // y to delta z - through psiz
2947 vecZk =(*p1)-(*p0); // measurement
2948 measR =(*c1)+(*c0); // error of measurement
2949 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
2952 matHkT=matHk.T(); matHk.T();
2953 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
2955 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
2956 vecXk += matKk*vecYk; // updated vector
2957 covXk2= (mat1-(matKk*matHk));
2958 covXk = covXk2*covXk;
2965 void AliTPCcalibAlign::MakeSectorKalman(){
2967 // Make a initial Kalman paramaters for IROC - Quadrants alignment
2969 TMatrixD param(5*6,1);
2970 TMatrixD covar(5*6,5*6);
2972 // Set inital parameters
2974 for (Int_t ip=0;ip<5*6;ip++) param(ip,0)=0; // mean alignment to 0
2976 for (Int_t iq=0;iq<5;iq++){
2977 // Initial uncertinty
2978 covar(iq*6+0,iq*6+0) = 0.002*0.002; // 2 mrad
2979 covar(iq*6+1,iq*6+1) = 0.002*0.002; // 2 mrad rotation
2980 covar(iq*6+2,iq*6+2) = 0.002*0.002; // 2 mrad
2982 covar(iq*6+3,iq*6+3) = 0.02*0.02; // 0.2 mm
2983 covar(iq*6+4,iq*6+4) = 0.02*0.02; // 0.2 mm translation
2984 covar(iq*6+5,iq*6+5) = 0.02*0.02; // 0.2 mm
2987 for (Int_t isec=0;isec<36;isec++){
2988 fArraySectorIntParam.AddAt(param.Clone(),isec);
2989 fArraySectorIntCovar.AddAt(covar.Clone(),isec);
2993 void AliTPCcalibAlign::UpdateSectorKalman(TMatrixD &par0, TMatrixD &cov0, TMatrixD &par1, TMatrixD &cov1){
2995 // Update kalman vector para0 with vector par1
2998 static TMatrixD matHk(30,30); // vector to mesurement
2999 static TMatrixD measR(30,30); // measurement error
3000 static TMatrixD vecZk(30,1); // measurement
3002 static TMatrixD vecYk(30,1); // Innovation or measurement residual
3003 static TMatrixD matHkT(30,30); // helper matrix Hk transpose
3004 static TMatrixD matSk(30,30); // Innovation (or residual) covariance
3005 static TMatrixD matKk(30,30); // Optimal Kalman gain
3006 static TMatrixD mat1(30,30); // update covariance matrix
3007 static TMatrixD covXk2(30,30); // helper matrix
3009 TMatrixD vecXk(par0); // X vector
3010 TMatrixD covXk(cov0); // X covariance
3015 for (Int_t i=0;i<30;i++)
3016 for (Int_t j=0;j<30;j++){
3018 if (i==j) mat1(i,j)=1;
3020 matHk = mat1; // unit matrix
3022 vecZk = par1; // measurement
3023 measR = cov1; // error of measurement
3024 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
3026 matHkT=matHk.T(); matHk.T();
3027 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
3029 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
3031 vecXk += matKk*vecYk; // updated vector
3032 covXk2= (mat1-(matKk*matHk));
3033 covXk = covXk2*covXk;
3034 CheckCovariance(covXk);
3035 CheckCovariance(cov1);
3037 par0 = vecXk; // update measurement param
3038 cov0 = covXk; // update measurement covar
3041 Double_t AliTPCcalibAlign::GetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t /*lz*/){
3043 // Get position correction for given sector
3046 TMatrixD * param = (TMatrixD*)fArraySectorIntParam.At(sector%36);
3047 if (!param) return 0;
3050 if (lx<fXquadrant) {
3051 if (ly<0) quadrant=1;
3052 if (ly>0) quadrant=2;
3054 if (lx>fXquadrant) {
3055 if (ly<0) quadrant=3;
3056 if (ly>0) quadrant=4;
3059 Double_t a10 = (*param)(quadrant*6+0,0);
3060 Double_t a20 = (*param)(quadrant*6+1,0);
3061 Double_t a21 = (*param)(quadrant*6+2,0);
3062 Double_t dx = (*param)(quadrant*6+3,0);
3063 Double_t dy = (*param)(quadrant*6+4,0);
3064 Double_t dz = (*param)(quadrant*6+5,0);
3065 Double_t deltaX = lx-fXIO;
3066 if (coord==0) return dx;
3067 if (coord==1) return dy+deltaX*a10;
3068 if (coord==2) return dz+deltaX*a20+ly*a21;
3072 Double_t AliTPCcalibAlign::SGetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t lz){
3076 if (!Instance()) return 0;
3077 return Instance()->GetCorrectionSector(coord,sector,lx,ly,lz);
3080 void AliTPCcalibAlign::MakeKalman(){
3082 // Make a initial Kalman paramaters for sector Alignemnt
3084 fSectorParamA = new TMatrixD(6*36+6,1);
3085 fSectorParamC = new TMatrixD(6*36+6,1);
3086 fSectorCovarA = new TMatrixD(6*36+6,6*36+6);
3087 fSectorCovarC = new TMatrixD(6*36+6,6*36+6);
3089 // set starting parameters at 0
3091 for (Int_t isec=0;isec<37;isec++)
3092 for (Int_t ipar=0;ipar<6;ipar++){
3093 (*fSectorParamA)(isec*6+ipar,0) =0;
3094 (*fSectorParamC)(isec*6+ipar,0) =0;
3097 // set starting covariance
3099 for (Int_t isec=0;isec<36;isec++)
3100 for (Int_t ipar=0;ipar<6;ipar++){
3102 (*fSectorCovarA)(isec*6+ipar,isec*6+ipar) =0.002*0.002; // 2 mrad
3103 (*fSectorCovarC)(isec*6+ipar,isec*6+ipar) =0.002*0.002;
3106 (*fSectorCovarA)(isec*6+ipar,isec*6+ipar) =0.02*0.02; // 0.2 mm
3107 (*fSectorCovarC)(isec*6+ipar,isec*6+ipar) =0.02*0.02;
3110 (*fSectorCovarA)(36*6+0,36*6+0) =0.04; // common shift y up-up
3111 (*fSectorCovarA)(36*6+1,36*6+1) =0.04; // common shift y down-down
3112 (*fSectorCovarA)(36*6+2,36*6+2) =0.04; // common shift y up-down
3113 (*fSectorCovarA)(36*6+3,36*6+3) =0.004; // common shift phi up-up
3114 (*fSectorCovarA)(36*6+4,36*6+4) =0.004; // common shift phi down-down
3115 (*fSectorCovarA)(36*6+5,36*6+5) =0.004; // common shift phi up-down
3117 (*fSectorCovarC)(36*6+0,36*6+0) =0.04; // common shift y up-up
3118 (*fSectorCovarC)(36*6+1,36*6+1) =0.04; // common shift y down-down
3119 (*fSectorCovarC)(36*6+2,36*6+2) =0.04; // common shift y up-down
3120 (*fSectorCovarC)(36*6+3,36*6+3) =0.004; // common shift phi up-up
3121 (*fSectorCovarC)(36*6+4,36*6+4) =0.004; // common shift phi down-down
3122 (*fSectorCovarC)(36*6+5,36*6+5) =0.004; // common shift phi up-down
3125 void AliTPCcalibAlign::UpdateKalman(Int_t sector0, Int_t sector1, TMatrixD &p0, TMatrixD &c0, TMatrixD &p1, TMatrixD &c1){
3127 // Update Kalman parameters
3128 // Note numbering from 0..36 0..17 IROC 18..35 OROC
3131 if (fSectorParamA==NULL) MakeKalman();
3132 if (CheckCovariance(c0)>0) return;
3133 if (CheckCovariance(c1)>0) return;
3134 const Int_t nelem = 6*36+6;
3137 static TMatrixD matHk(4,nelem); // vector to mesurement
3138 static TMatrixD measR(4,4); // measurement error
3139 static TMatrixD vecZk(4,1); // measurement
3141 static TMatrixD vecYk(4,1); // Innovation or measurement residual
3142 static TMatrixD matHkT(nelem,4); // helper matrix Hk transpose
3143 static TMatrixD matSk(4,4); // Innovation (or residual) covariance
3144 static TMatrixD matKk(nelem,4); // Optimal Kalman gain
3145 static TMatrixD mat1(nelem,nelem); // update covariance matrix
3146 static TMatrixD covXk2(nelem,nelem); // helper matrix
3148 TMatrixD *vOrig = 0;
3149 TMatrixD *cOrig = 0;
3150 vOrig = (sector0%36>=18) ? fSectorParamA:fSectorParamC;
3151 cOrig = (sector0%36>=18) ? fSectorCovarA:fSectorCovarC;
3153 Int_t sec0= sector0%18;
3154 Int_t sec1= sector1%18;
3155 if (sector0>35) sec0+=18;
3156 if (sector1>35) sec1+=18;
3158 TMatrixD vecXk(*vOrig); // X vector
3159 TMatrixD covXk(*cOrig); // X covariance
3163 for (Int_t i=0;i<nelem;i++)
3164 for (Int_t j=0;j<nelem;j++){
3166 if (i==j) mat1(i,j)=1;
3170 // matHk - vector to measurement
3172 for (Int_t i=0;i<4;i++)
3173 for (Int_t j=0;j<nelem;j++){
3183 matHk(0,6*sec1+4) = 1.; // delta y
3184 matHk(1,6*sec1+0) = 1.; // delta ky
3185 matHk(2,6*sec1+5) = 1.; // delta z
3186 matHk(3,6*sec1+1) = 1.; // delta kz
3187 matHk(0,6*sec1+3) = p0(1,0); // delta x to delta y - through ky
3188 matHk(2,6*sec1+3) = p0(3,0); // delta x to delta z - thorugh kz
3189 matHk(2,6*sec1+2) = p0(0,0); // y to delta z - through psiz
3191 matHk(0,6*sec0+4) = -1.; // delta y
3192 matHk(1,6*sec0+0) = -1.; // delta ky
3193 matHk(2,6*sec0+5) = -1.; // delta z
3194 matHk(3,6*sec0+1) = -1.; // delta kz
3195 matHk(0,6*sec0+3) = -p0(1,0); // delta x to delta y - through ky
3196 matHk(2,6*sec0+3) = -p0(3,0); // delta x to delta z - thorugh kz
3197 matHk(2,6*sec0+2) = -p0(0,0); // y to delta z - through psiz
3199 Int_t dsec = (sector1%18)-(sector0%18);
3200 if (dsec<-2) dsec+=18;
3201 if (TMath::Abs(dsec)==1){
3203 // Left right systematic fit part
3206 if (dsec>0) dir= 1.;
3207 if (dsec<0) dir=-1.;
3208 if (sector0>35&§or1>35){
3209 matHk(0,36*6+0)=dir;
3210 matHk(1,36*6+3+0)=dir;
3212 if (sector0<36&§or1<36){
3213 matHk(0,36*6+1)=dir;
3214 matHk(1,36*6+3+1)=dir;
3216 if (sector0<36&§or1>35){
3217 matHk(0,36*6+2)=dir;
3218 matHk(1,36*6+3+2)=dir;
3220 if (sector0>35&§or1<36){
3221 matHk(0,36*6+2)=-dir;
3222 matHk(1,36*6+3+2)=-dir;
3227 vecZk =(p1)-(p0); // measurement
3228 measR =(c1)+(c0); // error of measurement
3229 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
3232 matHkT=matHk.T(); matHk.T();
3233 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
3235 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
3236 vecXk += matKk*vecYk; // updated vector
3237 covXk2= (mat1-(matKk*matHk));
3238 covXk = covXk2*covXk;
3240 if (CheckCovariance(covXk)>0) return;
3249 void AliTPCcalibAlign::UpdateKalman(TMatrixD &par0, TMatrixD &cov0, TMatrixD &par1, TMatrixD &cov1){
3251 // Update kalman vector para0 with vector par1
3254 Int_t nelem = 6*36+6;
3255 static TMatrixD matHk(nelem,nelem); // vector to mesurement
3256 static TMatrixD measR(nelem,nelem); // measurement error
3257 static TMatrixD vecZk(nelem,1); // measurement
3259 static TMatrixD vecYk(nelem,1); // Innovation or measurement residual
3260 static TMatrixD matHkT(nelem,nelem); // helper matrix Hk transpose
3261 static TMatrixD matSk(nelem,nelem); // Innovation (or residual) covariance
3262 static TMatrixD matKk(nelem,nelem); // Optimal Kalman gain
3263 static TMatrixD mat1(nelem,nelem); // update covariance matrix
3264 static TMatrixD covXk2(nelem,nelem); // helper matrix
3266 TMatrixD vecXk(par0); // X vector
3267 TMatrixD covXk(cov0); // X covariance
3272 for (Int_t i=0;i<nelem;i++)
3273 for (Int_t j=0;j<nelem;j++){
3275 if (i==j) mat1(i,j)=1;
3277 matHk = mat1; // unit matrix
3279 vecZk = par1; // measurement
3280 measR = cov1; // error of measurement
3281 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
3283 matHkT=matHk.T(); matHk.T();
3284 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
3286 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
3288 vecXk += matKk*vecYk; // updated vector
3289 covXk2= (mat1-(matKk*matHk));
3290 covXk = covXk2*covXk;
3292 CheckCovariance(cov0);
3293 CheckCovariance(cov1);
3294 CheckCovariance(covXk);
3296 par0 = vecXk; // update measurement param
3297 cov0 = covXk; // update measurement covar
3303 Int_t AliTPCcalibAlign::CheckCovariance(TMatrixD &covar){
3305 // check the consistency of covariance matrix
3307 Int_t ncols = covar.GetNcols();
3308 Int_t nrows= covar.GetNrows();
3309 const Float_t kEpsilon = 0.0001;
3315 printf("Error 0 - wrong matrix\n");
3319 // 1. Check that the non diagonal elements
3321 for (Int_t i0=0;i0<nrows;i0++)
3322 for (Int_t i1=i0+1;i1<ncols;i1++){
3323 Double_t r0 = covar(i0,i1)/TMath::Sqrt(covar(i0,i0)*covar(i1,i1));
3324 Double_t r1 = covar(i1,i0)/TMath::Sqrt(covar(i0,i0)*covar(i1,i1));
3325 if (TMath::Abs(r0-r1)>kEpsilon){
3326 printf("Error 1 - non symetric matrix %d\t%d\t%f",i0,i1,r1-r0);
3329 if (TMath::Abs(r0)>=1){
3330 printf("Error 2 - Wrong correlation %d\t%d\t%f\n",i0,i1,r0);
3333 if (TMath::Abs(r1)>=1){
3334 printf("Error 3 - Wrong correlation %d\t%d\t%f\n",i0,i1,r1);
3343 void AliTPCcalibAlign::MakeReportDy(TFile *output){
3345 // Draw histogram of dY
3347 Int_t kmicolors[10]={1,2,3,4,6,7,8,9,10,11};
3348 Int_t kmimarkers[10]={21,22,23,24,25,26,27,28,29,30};
3350 AliTPCcalibAlign *align = this;
3351 TVectorD vecOOP(36);
3352 TVectorD vecOOM(36);
3353 TVectorD vecOIP(36);
3354 TVectorD vecOIM(36);
3355 TVectorD vecOIS(36);
3356 TVectorD vecSec(36);
3357 TCanvas * cOROCdy = new TCanvas("OROC dy","OROC dy",900,600);
3358 cOROCdy->Divide(6,6);
3359 TCanvas * cIROCdy = new TCanvas("IROC dy","IROC dy",900,600);
3360 cIROCdy->Divide(6,6);
3361 TCanvas * cDy = new TCanvas("Dy","Dy",600,700);
3363 for (Int_t isec=0;isec<36;isec++){
3364 Bool_t isDraw=kFALSE;
3366 cOROCdy->cd(isec+1);
3367 Int_t secPlus = (isec%18==17)? isec-17:isec+1;
3368 Int_t secMinus= (isec%18==0) ? isec+17:isec-1;
3369 printf("%d\t%d\t%d\n",isec,secPlus,secMinus);
3370 TH1 * hisOOP= align->GetHisto(AliTPCcalibAlign::kY,isec+36,secPlus+36);
3371 TH1 * hisOOM= align->GetHisto(AliTPCcalibAlign::kY,isec+36,secMinus+36);
3372 TH1 * hisOIS= align->GetHisto(AliTPCcalibAlign::kY,isec+36,isec);
3375 hisOIS = (TH1F*)(hisOIS->Clone());
3376 hisOIS->SetDirectory(0);
3377 hisOIS->Scale(1./(hisOIS->GetMaximum()+1));
3378 hisOIS->SetLineColor(kmicolors[0]);
3381 vecOIS(isec)=10*hisOIS->GetMean();
3384 hisOOP = (TH1F*)(hisOOP->Clone());
3385 hisOOP->SetDirectory(0);
3386 hisOOP->Scale(1./(hisOOP->GetMaximum()+1));
3387 hisOOP->SetLineColor(kmicolors[1]);
3388 if (isDraw) hisOOP->Draw("same");
3389 if (!isDraw) {hisOOP->Draw(""); isDraw=kTRUE;}
3390 vecOOP(isec)=10*hisOOP->GetMean();
3393 hisOOM = (TH1F*)(hisOOM->Clone());
3394 hisOOM->SetDirectory(0);
3395 hisOOM->Scale(1/(hisOOM->GetMaximum()+1));
3396 hisOOM->SetLineColor(kmicolors[3]);
3397 if (isDraw) hisOOM->Draw("same");
3398 if (!isDraw) {hisOOM->Draw(""); isDraw=kTRUE;}
3399 vecOOM(isec)=10*hisOOM->GetMean();
3404 for (Int_t isec=0;isec<36;isec++){
3405 Bool_t isDraw=kFALSE;
3406 cIROCdy->cd(isec+1);
3407 Int_t secPlus = (isec%18==17)? isec-17:isec+1;
3408 Int_t secMinus= (isec%18==0) ? isec+17:isec-1;
3409 printf("%d\t%d\t%d\n",isec,secPlus,secMinus);
3410 TH1 * hisOIP= align->GetHisto(AliTPCcalibAlign::kY,isec+36,secPlus);
3411 TH1 * hisOIM= align->GetHisto(AliTPCcalibAlign::kY,isec+36,secMinus);
3412 TH1 * hisOIS= align->GetHisto(AliTPCcalibAlign::kY,isec+36,isec);
3414 hisOIS = (TH1F*)(hisOIS->Clone());
3415 hisOIS->SetDirectory(0);
3416 hisOIS->Scale(1./(hisOIS->GetMaximum()+1));
3417 hisOIS->SetLineColor(kmicolors[0]);
3420 vecOIS(isec)=10*hisOIS->GetMean();
3423 hisOIP = (TH1F*)(hisOIP->Clone());
3424 hisOIP->SetDirectory(0);
3425 hisOIP->Scale(1./(hisOIP->GetMaximum()+1));
3426 hisOIP->SetLineColor(kmicolors[1]);
3427 if (isDraw) hisOIP->Draw("same");
3428 if (!isDraw) {hisOIP->Draw(""); isDraw=kTRUE;}
3429 hisOIP->Draw("same");
3430 vecOIP(isec)=10*hisOIP->GetMean();
3433 hisOIM = (TH1F*)(hisOIM->Clone());
3434 hisOIM->SetDirectory(0);
3435 hisOIM->Scale(1/(hisOIM->GetMaximum()+1));
3436 hisOIM->SetLineColor(kmicolors[3]);
3437 if (isDraw) hisOIM->Draw("same");
3438 if (!isDraw) {hisOIM->Draw(""); isDraw=kTRUE;}
3439 vecOIM(isec)=10*hisOIM->GetMean();
3442 TGraph* grOIM = new TGraph(36,vecSec.GetMatrixArray(),vecOIM.GetMatrixArray());
3443 TGraph* grOIP = new TGraph(36,vecSec.GetMatrixArray(),vecOIP.GetMatrixArray());
3444 TGraph* grOIS = new TGraph(36,vecSec.GetMatrixArray(),vecOIS.GetMatrixArray());
3445 TGraph* grOOM = new TGraph(36,vecSec.GetMatrixArray(),vecOOM.GetMatrixArray());
3446 TGraph* grOOP = new TGraph(36,vecSec.GetMatrixArray(),vecOOP.GetMatrixArray());
3448 grOIS->SetMarkerStyle(kmimarkers[0]);
3449 grOIP->SetMarkerStyle(kmimarkers[1]);
3450 grOIM->SetMarkerStyle(kmimarkers[3]);
3451 grOOP->SetMarkerStyle(kmimarkers[1]);
3452 grOOM->SetMarkerStyle(kmimarkers[3]);
3453 grOIS->SetMarkerColor(kmicolors[0]);
3454 grOIP->SetMarkerColor(kmicolors[1]);
3455 grOIM->SetMarkerColor(kmicolors[3]);
3456 grOOP->SetMarkerColor(kmicolors[1]);
3457 grOOM->SetMarkerColor(kmicolors[3]);
3458 grOIS->SetLineColor(kmicolors[0]);
3459 grOIP->SetLineColor(kmicolors[1]);
3460 grOIM->SetLineColor(kmicolors[3]);
3461 grOOP->SetLineColor(kmicolors[1]);
3462 grOOM->SetLineColor(kmicolors[3]);
3463 grOIS->SetMaximum(1.5);
3464 grOIS->SetMinimum(-1.5);
3465 grOIS->GetXaxis()->SetTitle("Sector number");
3466 grOIS->GetYaxis()->SetTitle("#Delta_{y} (mm)");
3476 cOROCdy->SaveAs("picAlign/OROCOROCdy.eps");
3477 cOROCdy->SaveAs("picAlign/OROCOROCdy.gif");
3478 cOROCdy->SaveAs("picAlign/OROCOROCdy.root");
3480 cIROCdy->SaveAs("picAlign/OROCIROCdy.eps");
3481 cIROCdy->SaveAs("picAlign/OROCIROCdy.gif");
3482 cIROCdy->SaveAs("picAlign/OROCIROCdy.root");
3484 cDy->SaveAs("picAlign/Sectordy.eps");
3485 cDy->SaveAs("picAlign/Sectordy.gif");
3486 cDy->SaveAs("picAlign/Sectordy.root");
3489 cOROCdy->Write("OROCOROCDy");
3490 cIROCdy->Write("OROCIROCDy");
3491 cDy->Write("SectorDy");
3495 void AliTPCcalibAlign::MakeReportDyPhi(TFile */*output*/){
3499 Int_t kmicolors[10]={1,2,3,4,6,7,8,9,10,11};
3500 Int_t kmimarkers[10]={21,22,23,24,25,26,27,28,29,30};
3502 AliTPCcalibAlign *align = this;
3503 TCanvas * cOROCdyPhi = new TCanvas("OROC dyphi","OROC dyphi",900,600);
3504 cOROCdyPhi->Divide(6,6);
3505 for (Int_t isec=0;isec<36;isec++){
3506 cOROCdyPhi->cd(isec+1);
3507 Int_t secPlus = (isec%18==17)? isec-17:isec+1;
3508 Int_t secMinus= (isec%18==0) ? isec+17:isec-1;
3509 //printf("%d\t%d\t%d\n",isec,secPlus,secMinus);
3511 TProfile * profdyphiOOP=0,*profdyphiOOM=0,*profdyphiOOS=0;
3512 htemp = (TH2F*) (align->GetHisto(AliTPCcalibAlign::kYPhi,isec+36,secPlus+36));
3513 if (htemp) profdyphiOOP= htemp->ProfileX();
3514 htemp = (TH2F*)(align->GetHisto(AliTPCcalibAlign::kYPhi,isec+36,secMinus+36));
3515 if (htemp) profdyphiOOM= htemp->ProfileX();
3516 htemp = (TH2F*)(align->GetHisto(AliTPCcalibAlign::kYPhi,isec+36,isec));
3517 if (htemp) profdyphiOOS= htemp->ProfileX();
3520 profdyphiOOS->SetLineColor(kmicolors[0]);
3521 profdyphiOOS->SetMarkerStyle(kmimarkers[0]);
3522 profdyphiOOS->SetMarkerSize(0.2);
3523 profdyphiOOS->SetMaximum(0.5);
3524 profdyphiOOS->SetMinimum(-0.5);
3525 profdyphiOOS->SetXTitle("tan(#phi)");
3526 profdyphiOOS->SetYTitle("#DeltaY (cm)");
3529 profdyphiOOP->SetLineColor(kmicolors[1]);
3530 profdyphiOOP->SetMarkerStyle(kmimarkers[1]);
3531 profdyphiOOP->SetMarkerSize(0.2);
3534 profdyphiOOM->SetLineColor(kmicolors[3]);
3535 profdyphiOOM->SetMarkerStyle(kmimarkers[3]);
3536 profdyphiOOM->SetMarkerSize(0.2);
3539 profdyphiOOS->Draw();
3541 if (profdyphiOOM) profdyphiOOM->Draw("");
3542 if (profdyphiOOP) profdyphiOOP->Draw("");
3544 if (profdyphiOOM) profdyphiOOM->Draw("same");
3545 if (profdyphiOOP) profdyphiOOP->Draw("same");