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"
136 #include "TDatabasePDG.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),
188 fArraySectorIntParam(36), // array of sector alignment parameters
189 fArraySectorIntCovar(36), // array of sector alignment covariances
191 // Kalman filter for global alignment
193 fSectorParamA(0), // Kalman parameter for A side
194 fSectorCovarA(0), // Kalman covariance for A side
195 fSectorParamC(0), // Kalman parameter for A side
196 fSectorCovarC(0), // Kalman covariance for A side
197 fUseInnerOuter(kTRUE)// flag- use Inner Outer sector for left righ alignment
202 for (Int_t i=0;i<72*72;++i) {
205 AliTPCROC * roc = AliTPCROC::Instance();
206 fXquadrant = roc->GetPadRowRadii(36,53);
207 fXmiddle = ( roc->GetPadRowRadii(0,0)+roc->GetPadRowRadii(36,roc->GetNRows(36)-1))*0.5;
208 fXIO = ( roc->GetPadRowRadii(0,roc->GetNRows(0)-1)+roc->GetPadRowRadii(36,0))*0.5;
209 fClusterDelta[0]=0; // cluster residuals - Y
210 fClusterDelta[1]=0; // cluster residuals - Z
213 fTrackletDelta[0]=0; // tracklet residuals
214 fTrackletDelta[1]=0; // tracklet residuals
215 fTrackletDelta[2]=0; // tracklet residuals
216 fTrackletDelta[3]=0; // tracklet residuals
219 AliTPCcalibAlign::AliTPCcalibAlign(const Text_t *name, const Text_t *title)
221 fDphiHistArray(72*72),
222 fDthetaHistArray(72*72),
225 fDyPhiHistArray(72*72), // array of residual histograms y -kYPhi
226 fDzThetaHistArray(72*72), // array of residual histograms z-z -kZTheta
227 fDphiZHistArray(72*72), // array of residual histograms phi -kPhiz
228 fDthetaZHistArray(72*72), // array of residual histograms theta -kThetaz
229 fDyZHistArray(72*72), // array of residual histograms y -kYz
230 fDzZHistArray(72*72), // array of residual histograms z -kZz //
231 fFitterArray12(72*72),
232 fFitterArray9(72*72),
233 fFitterArray6(72*72),
234 fMatrixArray12(72*72),
235 fMatrixArray9(72*72),
236 fMatrixArray6(72*72),
237 fCombinedMatrixArray6(72),
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
269 fTrackletDelta[0]=0; // tracklet residuals
270 fTrackletDelta[1]=0; // tracklet residuals
271 fTrackletDelta[2]=0; // tracklet residuals
272 fTrackletDelta[3]=0; // tracklet residuals
276 AliTPCcalibAlign::AliTPCcalibAlign(const AliTPCcalibAlign &align)
277 :AliTPCcalibBase(align),
278 fDphiHistArray(align.fDphiHistArray),
279 fDthetaHistArray(align.fDthetaHistArray),
280 fDyHistArray(align.fDyHistArray),
281 fDzHistArray(align.fDzHistArray),
282 fDyPhiHistArray(align.fDyPhiHistArray), // array of residual histograms y -kYPhi
283 fDzThetaHistArray(align.fDzThetaHistArray), // array of residual histograms z-z -kZTheta
284 fDphiZHistArray(align.fDphiZHistArray), // array of residual histograms phi -kPhiz
285 fDthetaZHistArray(align.fDthetaZHistArray), // array of residual histograms theta -kThetaz
286 fDyZHistArray(align.fDyZHistArray), // array of residual histograms y -kYz
287 fDzZHistArray(align.fDzZHistArray), // array of residual histograms z -kZz
289 fFitterArray12(align.fFitterArray12),
290 fFitterArray9(align.fFitterArray9),
291 fFitterArray6(align.fFitterArray6),
293 fMatrixArray12(align.fMatrixArray12),
294 fMatrixArray9(align.fMatrixArray9),
295 fMatrixArray6(align.fMatrixArray6),
296 fCombinedMatrixArray6(align.fCombinedMatrixArray6),
297 fNoField(align.fNoField),
299 fXmiddle(align.fXmiddle),
300 fXquadrant(align.fXquadrant),
301 fArraySectorIntParam(align.fArraySectorIntParam), // array of sector alignment parameters
302 fArraySectorIntCovar(align.fArraySectorIntCovar), // array of sector alignment covariances
303 fSectorParamA(0), // Kalman parameter for A side
304 fSectorCovarA(0), // Kalman covariance for A side
305 fSectorParamC(0), // Kalman parameter for A side
306 fSectorCovarC(0), // Kalman covariance for A side
307 fUseInnerOuter(kTRUE)// flag- use Inner Outer sector for left righ alignment
311 // copy constructor - copy also the content
315 const TObjArray *arr1=0;
316 for (Int_t index =0; index<72*72; index++){
317 for (Int_t iarray=0;iarray<10; iarray++){
319 arr0 = &fDyHistArray;
320 arr1 = &align.fDyHistArray;
323 arr0 = &fDzHistArray;
324 arr1 = &align.fDzHistArray;
327 arr0 = &fDphiHistArray;
328 arr1 = &align.fDphiHistArray;
331 arr0 = &fDthetaHistArray;
332 arr1 = &align.fDthetaHistArray;
335 arr0 = &fDyZHistArray;
336 arr1 = &align.fDyZHistArray;
339 arr0 = &fDzZHistArray;
340 arr1 = &align.fDzZHistArray;
343 arr0 = &fDphiZHistArray;
344 arr1 = &align.fDphiZHistArray;
346 if (iarray==kThetaZ){
347 arr0 = &fDthetaZHistArray;
348 arr1 = &align.fDthetaZHistArray;
352 arr0 = &fDyPhiHistArray;
353 arr1 = &align.fDyPhiHistArray;
355 if (iarray==kZTheta){
356 arr0 = &fDzThetaHistArray;
357 arr1 = &align.fDzThetaHistArray;
360 if (arr1->At(index)) {
361 his = (TH1*)arr1->At(index)->Clone();
362 his->SetDirectory(0);
363 arr0->AddAt(his,index);
370 if (align.fSectorParamA){
371 fSectorParamA = (TMatrixD*)align.fSectorParamA->Clone();
372 fSectorParamA = (TMatrixD*)align.fSectorCovarA->Clone();
373 fSectorParamC = (TMatrixD*)align.fSectorParamA->Clone();
374 fSectorParamC = (TMatrixD*)align.fSectorCovarA->Clone();
376 fClusterDelta[0]=0; // cluster residuals
377 fClusterDelta[1]=0; // cluster residuals
379 fTrackletDelta[0]=0; // tracklet residuals
380 fTrackletDelta[1]=0; // tracklet residuals
381 fTrackletDelta[2]=0; // tracklet residuals
382 fTrackletDelta[3]=0; // tracklet residuals
386 AliTPCcalibAlign::~AliTPCcalibAlign() {
390 fDphiHistArray.SetOwner(kTRUE); // array of residual histograms phi -kPhi
391 fDthetaHistArray.SetOwner(kTRUE); // array of residual histograms theta -kTheta
392 fDyHistArray.SetOwner(kTRUE); // array of residual histograms y -kY
393 fDzHistArray.SetOwner(kTRUE); // array of residual histograms z -kZ
395 fDyPhiHistArray.SetOwner(kTRUE); // array of residual histograms y -kYPhi
396 fDzThetaHistArray.SetOwner(kTRUE); // array of residual histograms z-z -kZTheta
398 fDphiZHistArray.SetOwner(kTRUE); // array of residual histograms phi -kPhiz
399 fDthetaZHistArray.SetOwner(kTRUE); // array of residual histograms theta -kThetaz
400 fDyZHistArray.SetOwner(kTRUE); // array of residual histograms y -kYz
401 fDzZHistArray.SetOwner(kTRUE); // array of residual histograms z -kZz
403 fDphiHistArray.Delete(); // array of residual histograms phi -kPhi
404 fDthetaHistArray.Delete(); // array of residual histograms theta -kTheta
405 fDyHistArray.Delete(); // array of residual histograms y -kY
406 fDzHistArray.Delete(); // array of residual histograms z -kZ
408 fDyPhiHistArray.Delete(); // array of residual histograms y -kYPhi
409 fDzThetaHistArray.Delete(); // array of residual histograms z-z -kZTheta
411 fDphiZHistArray.Delete(); // array of residual histograms phi -kPhiz
412 fDthetaZHistArray.Delete(); // array of residual histograms theta -kThetaz
413 fDyZHistArray.Delete(); // array of residual histograms y -kYz
414 fDzZHistArray.Delete(); // array of residual histograms z -kZz
416 fFitterArray12.SetOwner(kTRUE); // array of fitters
417 fFitterArray9.SetOwner(kTRUE); // array of fitters
418 fFitterArray6.SetOwner(kTRUE); // array of fitters
420 fMatrixArray12.SetOwner(kTRUE); // array of transnformtation matrix
421 fMatrixArray9.SetOwner(kTRUE); // array of transnformtation matrix
422 fMatrixArray6.SetOwner(kTRUE); // array of transnformtation matrix
424 fFitterArray12.Delete(); // array of fitters
425 fFitterArray9.Delete(); // array of fitters
426 fFitterArray6.Delete(); // array of fitters
428 fMatrixArray12.Delete(); // array of transnformtation matrix
429 fMatrixArray9.Delete(); // array of transnformtation matrix
430 fMatrixArray6.Delete(); // array of transnformtation matrix
433 fArraySectorIntParam.SetOwner(kTRUE); // array of sector alignment parameters
434 fArraySectorIntCovar.SetOwner(kTRUE); // array of sector alignment covariances
435 fArraySectorIntParam.Delete(); // array of sector alignment parameters
436 fArraySectorIntCovar.Delete(); // array of sector alignment covariances
437 for (Int_t i=0; i<2; i++){
438 delete fClusterDelta[i]; // cluster residuals
441 for (Int_t i=0; i<4; i++){
442 delete fTrackletDelta[i]; // tracklet residuals
448 void AliTPCcalibAlign::Process(AliESDEvent *event) {
450 // Process pairs of cosmic tracks
452 if (!fClusterDelta[0]) MakeResidualHistos();
453 if (!fTrackletDelta[0]) MakeResidualHistosTracklet();
456 ExportTrackPoints(event); // export track points for external calibration
457 const Int_t kMaxTracks =6;
458 const Int_t kminCl = 40;
459 AliESDfriend *eESDfriend=static_cast<AliESDfriend*>(event->FindListObject("AliESDfriend"));
460 if (!eESDfriend) return;
461 Int_t ntracks=event->GetNumberOfTracks();
468 for (Int_t i0=0;i0<ntracks;++i0) {
469 AliESDtrack *track0 = event->GetTrack(i0);
470 AliESDfriendTrack *friendTrack = 0;
471 TObject *calibObject=0;
472 AliTPCseed *seed0 = 0;
474 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i0);;
475 if (!friendTrack) continue;
476 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
477 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
479 if (!seed0) continue;
480 fCurrentTrack=track0;
481 fCurrentFriendTrack=friendTrack;
487 // process cosmic pairs
489 if (ntracks>kMaxTracks) return;
491 //select pairs - for alignment
492 for (Int_t i0=0;i0<ntracks;++i0) {
493 AliESDtrack *track0 = event->GetTrack(i0);
494 // if (track0->GetTPCNcls()<kminCl) continue;
495 track0->GetImpactParameters(dca0[0],dca0[1]);
496 // if (TMath::Abs(dca0[0])>30) continue;
498 for (Int_t i1=0;i1<ntracks;++i1) {
499 if (i0==i1) continue;
500 AliESDtrack *track1 = event->GetTrack(i1);
501 // if (track1->GetTPCNcls()<kminCl) continue;
502 track1->GetImpactParameters(dca1[0],dca1[1]);
503 // fast cuts on dca and theta
504 // if (TMath::Abs(dca1[0]+dca0[0])>15) continue;
505 // if (TMath::Abs(dca1[1]-dca0[1])>15) continue;
506 if (TMath::Abs(track0->GetParameter()[3]+track1->GetParameter()[3])>0.1) continue;
508 AliESDfriendTrack *friendTrack = 0;
509 TObject *calibObject=0;
510 AliTPCseed *seed0 = 0,*seed1=0;
512 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i0);;
513 if (!friendTrack) continue;
514 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
515 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
517 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(i1);;
518 if (!friendTrack) continue;
519 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
520 if ((seed1=dynamic_cast<AliTPCseed*>(calibObject))) break;
522 if (!seed0) continue;
525 if (!seed1) continue;
526 Int_t nclsectors0[72], nclsectors1[72];
527 for (Int_t isec=0;isec<72;isec++){
531 for (Int_t i=0;i<160;i++){
532 AliTPCclusterMI *c0=seed0->GetClusterPointer(i);
533 AliTPCclusterMI *c1=seed1->GetClusterPointer(i);
534 if (c0) nclsectors0[c0->GetDetector()]+=1;
535 if (c1) nclsectors1[c1->GetDetector()]+=1;
538 for (Int_t isec0=0; isec0<72;isec0++){
539 if (nclsectors0[isec0]<kminCl) continue;
540 for (Int_t isec1=0; isec1<72;isec1++){
541 if (nclsectors1[isec1]<kminCl) continue;
544 Double_t parLine0[10];
545 Double_t parLine1[10];
546 TMatrixD par0(4,1),cov0(4,4),par1(4,1),cov1(4,4);
547 Bool_t useInnerOuter = kFALSE;
548 if (s1%36!=s0%36) useInnerOuter = fUseInnerOuter; // for left - right alignment both sectors refit can be used if specified
549 Int_t nl0 = RefitLinear(seed0,s0, parLine0, s0,par0,cov0,fXIO,useInnerOuter);
550 Int_t nl1 = RefitLinear(seed1,s1, parLine1, s0,par1,cov1,fXIO,useInnerOuter);
551 parLine0[0]=0; // reference frame in IO boundary
553 // if (nl0<kminCl || nl1<kminCl) continue;
557 if (TMath::Min(nl0,nl1)<kminCl) isOK=kFALSE;
558 // apply selection criteria
562 dp0=par0(0,0)-par1(0,0);
563 dp1=par0(1,0)-par1(1,0);
564 dp3=par0(3,0)-par1(3,0);
565 pp0=dp0/TMath::Sqrt(cov0(0,0)+cov1(0,0)+0.1*0.1);
566 pp1=dp1/TMath::Sqrt(cov0(1,1)+cov1(1,1)+0.0015*0.0015);
567 pp3=dp3/TMath::Sqrt(cov0(3,3)+cov1(3,3)+0.0015*0.0015);
569 if (TMath::Abs(dp0)>1.0) isOK=kFALSE;
570 if (TMath::Abs(dp1)>0.02) isOK=kFALSE;
571 if (TMath::Abs(dp3)>0.02) isOK=kFALSE;
572 if (TMath::Abs(pp0)>6) isOK=kFALSE;
573 if (TMath::Abs(pp1)>6) isOK=kFALSE;
574 if (TMath::Abs(pp3)>6) isOK=kFALSE;
577 FillHisto(parLine0,parLine1,s0,s1);
578 ProcessAlign(parLine0,parLine1,s0,s1);
579 UpdateKalman(s0,s1,par0, cov0, par1, cov1);
582 TTreeSRedirector *cstream = GetDebugStreamer();
584 (*cstream)<<"cosmic"<<
603 void AliTPCcalibAlign::ExportTrackPoints(AliESDEvent *event){
605 // Export track points for alignment - calibration
606 // export space points for pairs of tracks if possible
608 AliESDfriend *eESDfriend=static_cast<AliESDfriend*>(event->FindListObject("AliESDfriend"));
609 if (!eESDfriend) return;
610 Int_t ntracks=event->GetNumberOfTracks();
611 Int_t kMaxTracks=4; // maximal number of tracks for cosmic pairs
612 Int_t kMinVertexTracks=5; // maximal number of tracks for vertex mesurement
615 const Int_t kminCl = 60;
616 const Int_t kminClSum = 120;
617 //const Double_t kDistY = 5;
618 // const Double_t kDistZ = 40;
619 const Double_t kDistTh = 0.05;
620 const Double_t kDistThS = 0.002;
621 const Double_t kDist1Pt = 0.1;
622 const Double_t kMaxD0 =3; // max distance to the primary vertex
623 const Double_t kMaxD1 =5; // max distance to the primary vertex
624 const AliESDVertex *tpcVertex = 0;
625 // get the primary vertex TPC
626 if (ntracks>kMinVertexTracks) {
627 tpcVertex = event->GetPrimaryVertexSPD();
628 if (tpcVertex->GetNContributors()<kMinVertexTracks) tpcVertex=0;
633 Int_t index0=0,index1=0;
635 for (Int_t i0=0;i0<ntracks;++i0) {
636 AliESDtrack *track0 = event->GetTrack(i0);
637 if (!track0) continue;
638 if ((track0->GetStatus() & AliESDtrack::kTPCrefit)==0) continue;
639 if (track0->GetOuterParam()==0) continue;
640 if (track0->GetInnerParam()==0) continue;
641 if (TMath::Abs(track0->GetInnerParam()->GetSigned1Pt()-track0->GetOuterParam()->GetSigned1Pt())>kDist1Pt) continue;
642 if (TMath::Abs(track0->GetInnerParam()->GetSigned1Pt())>kDist1Pt) continue;
643 if (TMath::Abs(track0->GetInnerParam()->GetTgl()-track0->GetOuterParam()->GetTgl())>kDistThS) continue;
644 AliESDtrack *track1P = 0;
645 if (track0->GetTPCNcls()<kminCl) continue;
646 track0->GetImpactParameters(dca0[0],dca0[1]);
650 if (ntracks<kMaxTracks) for (Int_t i1=i0+1;i1<ntracks;++i1) {
651 if (i0==i1) continue;
652 AliESDtrack *track1 = event->GetTrack(i1);
653 if (!track1) continue;
654 if ((track1->GetStatus() & AliESDtrack::kTPCrefit)==0) continue;
655 if (track1->GetOuterParam()==0) continue;
656 if (track1->GetInnerParam()==0) continue;
657 if (track1->GetTPCNcls()<kminCl) continue;
658 if (TMath::Abs(track1->GetInnerParam()->GetSigned1Pt()-track1->GetOuterParam()->GetSigned1Pt())>kDist1Pt) continue;
659 if (TMath::Abs(track1->GetInnerParam()->GetTgl()-track1->GetOuterParam()->GetTgl())>kDistThS) continue;
660 if (TMath::Abs(track1->GetInnerParam()->GetSigned1Pt())>kDist1Pt) continue;
661 //track1->GetImpactParameters(dca1[0],dca1[1]);
662 //if (TMath::Abs(dca1[0]-dca0[0])>kDistY) continue;
663 //if (TMath::Abs(dca1[1]-dca0[1])>kDistZ) continue;
664 if (TMath::Abs(track0->GetTgl()+track1->GetTgl())>kDistTh) continue;
665 if (TMath::Abs(track0->GetSigned1Pt()+track1->GetSigned1Pt())>kDist1Pt) continue;
669 AliESDfriendTrack *friendTrack = 0;
670 TObject *calibObject=0;
671 AliTPCseed *seed0 = 0,*seed1=0;
673 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(index0);;
674 if (!friendTrack) continue;
675 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
676 if ((seed0=dynamic_cast<AliTPCseed*>(calibObject))) break;
679 friendTrack = (AliESDfriendTrack *)eESDfriend->GetTrack(index1);;
680 if (!friendTrack) continue;
681 for (Int_t l=0;(calibObject=friendTrack->GetCalibObject(l));++l) {
682 if ((seed1=dynamic_cast<AliTPCseed*>(calibObject))) break;
686 Int_t npoints=0, ncont=0;
687 if (seed0) {npoints+=seed0->GetNumberOfClusters(); ncont++;}
688 if (seed1) {npoints+=seed1->GetNumberOfClusters(); ncont++;}
689 if (npoints<kminClSum) continue;
691 AliTrackPointArray array(npoints);
693 Double_t dxyz[3]={0,0,0};
694 Double_t dc[6]={0,0,0};
695 tpcVertex->GetXYZ(dxyz);
696 tpcVertex->GetCovarianceMatrix(dc);
697 Float_t xyz[3]={dxyz[0],dxyz[1],dxyz[2]};
698 Float_t cov[6]={dc[0]+1,dc[1],dc[2]+1,dc[3],dc[4],dc[5]+100.};
699 AliTrackPoint point(xyz,cov,73); // add point to not existing volume
700 Float_t dtpc[2],dcov[3];
701 track0->GetImpactParametersTPC(dtpc,dcov);
702 if (TMath::Abs(dtpc[0])>kMaxD0) continue;
703 if (TMath::Abs(dtpc[1])>kMaxD1) continue;
706 if (seed0) for (Int_t icl = 0; icl<160; icl++){
707 AliTPCclusterMI *cluster=seed0->GetClusterPointer(icl);
708 if (!cluster) continue;
711 cluster->GetGlobalXYZ(xyz);
712 cluster->GetGlobalCov(cov);
713 AliTrackPoint point(xyz,cov,cluster->GetDetector());
714 array.AddPoint(npoints, &point);
715 if (cpoint>=npoints) continue; //shoul not happen
716 array.AddPoint(cpoint, &point);
719 if (seed1) for (Int_t icl = 0; icl<160; icl++){
720 AliTPCclusterMI *cluster=seed1->GetClusterPointer(icl);
721 if (!cluster) continue;
724 cluster->GetGlobalXYZ(xyz);
725 cluster->GetGlobalCov(cov);
726 AliTrackPoint point(xyz,cov,cluster->GetDetector());
727 array.AddPoint(npoints, &point);
728 if (cpoint>=npoints) continue; //shoul not happen
729 array.AddPoint(cpoint, &point);
735 TTreeSRedirector *cstream = GetDebugStreamer();
737 Bool_t isVertex=(tpcVertex)? kTRUE:kFALSE;
738 Double_t tof0=track0->GetTOFsignal();
739 Double_t tof1=(track1P) ? track1P->GetTOFsignal(): 0;
740 static AliExternalTrackParam dummy;
741 AliExternalTrackParam *p0In = &dummy;
742 AliExternalTrackParam *p1In = &dummy;
743 AliExternalTrackParam *p0Out = &dummy;
744 AliExternalTrackParam *p1Out = &dummy;
746 AliESDVertex *pvertex= (tpcVertex)? (AliESDVertex *)tpcVertex: &vdummy;
748 p0In= new AliExternalTrackParam(*track0);
749 p0Out=new AliExternalTrackParam(*(track0->GetOuterParam()));
752 p1In= new AliExternalTrackParam(*track1P);
753 p1Out=new AliExternalTrackParam(*(track1P->GetOuterParam()));
756 (*cstream)<<"trackPoints"<<
757 "run="<<fRun<< // run number
758 "event="<<fEvent<< // event number
759 "time="<<fTime<< // time stamp of event
760 "trigger="<<fTrigger<< // trigger
761 "triggerClass="<<&fTriggerClass<< // trigger
762 "mag="<<fMagF<< // magnetic field
763 "pvertex.="<<pvertex<< // vertex
765 "isVertex="<<isVertex<< // flag is with prim vertex
766 "tof0="<<tof0<< // tof signal 0
767 "tof1="<<tof1<< // tof signal 1
768 "seed0.="<<seed0<< // track info
769 "ntracks="<<ntracks<< // number of tracks
770 "ncont="<<ncont<< // number of contributors
771 "p0In.="<<p0In<< // track parameters0
772 "p1In.="<<p1In<< // track parameters1
773 "p0Out.="<<p0Out<< // track parameters0
774 "p1Out.="<<p1Out<< // track parameters0
784 void AliTPCcalibAlign::ProcessSeed(AliTPCseed *seed) {
788 // make a kalman tracklets out of seed
790 UpdateClusterDeltaField(seed);
792 AliTPCTracklet::CreateTracklets(seed,AliTPCTracklet::kKalman,
794 tracklets.SetOwner();
795 Int_t ntracklets = tracklets.GetEntries();
796 if (ntracklets<2) return;
799 for (Int_t i1=0;i1<ntracklets;i1++)
800 for (Int_t i2=0;i2<ntracklets;i2++){
801 if (i1==i2) continue;
802 AliTPCTracklet *t1=static_cast<AliTPCTracklet*>(tracklets[i1]);
803 AliTPCTracklet *t2=static_cast<AliTPCTracklet*>(tracklets[i2]);
804 AliExternalTrackParam *common1=0,*common2=0;
805 if (AliTPCTracklet::PropagateToMeanX(*t1,*t2,common1,common2)){
806 ProcessTracklets(*common1,*common2,seed, t1->GetSector(),t2->GetSector());
807 UpdateAlignSector(seed,t1->GetSector());
814 void AliTPCcalibAlign::Analyze(){
822 void AliTPCcalibAlign::Terminate(){
824 // Terminate function
825 // call base terminate + Eval of fitters
827 Info("AliTPCcalibAlign","Terminate");
829 AliTPCcalibBase::Terminate();
833 void AliTPCcalibAlign::UpdatePointCorrection(AliTPCPointCorrection * correction){
835 // Update point correction with alignment coefficients
837 for (Int_t isec=0;isec<36;isec++){
838 TMatrixD * matCorr = (TMatrixD*)(correction->fArraySectorIntParam.At(isec));
839 TMatrixD * matAlign = (TMatrixD*)(fArraySectorIntParam.At(isec));
840 TMatrixD * matAlignCovar = (TMatrixD*)(fArraySectorIntCovar.At(isec));
841 if (!matAlign) continue;
843 correction->fArraySectorIntParam.AddAt(matAlign->Clone(),isec);
844 correction->fArraySectorIntCovar.AddAt(matAlignCovar->Clone(),isec);
847 (*matCorr)+=(*matAlign);
848 correction->fArraySectorIntCovar.AddAt(matAlignCovar->Clone(),isec);
855 void AliTPCcalibAlign::ProcessTracklets(const AliExternalTrackParam &tp1,
856 const AliExternalTrackParam &tp2,
857 const AliTPCseed * seed,
860 // Process function to fill fitters
862 Double_t t1[10],t2[10];
863 Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
864 Double_t &x2=t2[0], &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
868 Double_t snp1=tp1.GetSnp();
869 dydx1=snp1/TMath::Sqrt((1.-snp1)*(1.+snp1));
870 Double_t tgl1=tp1.GetTgl();
871 // dz/dx = 1/(cos(theta)*cos(phi))
872 dzdx1=tgl1/TMath::Sqrt((1.-snp1)*(1.+snp1));
876 Double_t snp2=tp2.GetSnp();
877 dydx2=snp2/TMath::Sqrt((1.-snp2)*(1.+snp2));
878 Double_t tgl2=tp2.GetTgl();
879 dzdx2=tgl2/TMath::Sqrt((1.-snp2)*(1.+snp2));
888 t1[6]=TMath::Sqrt(tp1.GetSigmaY2());
889 t1[7]=TMath::Sqrt(tp1.GetSigmaSnp2());
890 t1[8]=TMath::Sqrt(tp1.GetSigmaZ2());
891 t1[9]=TMath::Sqrt(tp1.GetSigmaTgl2());
893 t2[6]=TMath::Sqrt(tp2.GetSigmaY2());
894 t2[7]=TMath::Sqrt(tp2.GetSigmaSnp2());
895 t2[8]=TMath::Sqrt(tp2.GetSigmaZ2());
896 t2[9]=TMath::Sqrt(tp2.GetSigmaTgl2());
900 Double_t parLine1[10];
901 Double_t parLine2[10];
902 TMatrixD par1(4,1),cov1(4,4),par2(4,1),cov2(4,4);
903 Bool_t useInnerOuter = kFALSE;
904 if (s1%36!=s2%36) useInnerOuter = fUseInnerOuter; // for left - right alignment bot sectors refit can be used if specified
905 Int_t nl1 = RefitLinear(seed,s1, parLine1, s1,par1,cov1,tp1.GetX(), useInnerOuter);
906 Int_t nl2 = RefitLinear(seed,s2, parLine2, s1,par2,cov2,tp1.GetX(), useInnerOuter);
907 parLine1[0]=tp1.GetX()-fXIO; // parameters in IROC-OROC boundary
908 parLine2[0]=tp1.GetX()-fXIO; // parameters in IROC-OROC boundary
912 Int_t accept = AcceptTracklet(tp1,tp2);
913 Int_t acceptLinear = AcceptTracklet(parLine1,parLine2);
916 if (fStreamLevel>1 && seed){
917 TTreeSRedirector *cstream = GetDebugStreamer();
919 static TVectorD vec1(5);
920 static TVectorD vec2(5);
921 static TVectorD vecL1(9);
922 static TVectorD vecL2(9);
923 vec1.SetElements(t1);
924 vec2.SetElements(t2);
925 vecL1.SetElements(parLine1);
926 vecL2.SetElements(parLine2);
927 AliExternalTrackParam *p1 = &((AliExternalTrackParam&)tp1);
928 AliExternalTrackParam *p2 = &((AliExternalTrackParam&)tp2);
929 (*cstream)<<"Tracklet"<<
931 "acceptLinear="<<acceptLinear<< // accept linear tracklets
932 "run="<<fRun<< // run number
933 "event="<<fEvent<< // event number
934 "time="<<fTime<< // time stamp of event
935 "trigger="<<fTrigger<< // trigger
936 "triggerClass="<<&fTriggerClass<< // trigger
937 "mag="<<fMagF<< // magnetic field
938 "isOK="<<accept<< // flag - used for alignment
945 "nl1="<<nl1<< // linear fit - n points
946 "nl2="<<nl2<< // linear fit - n points
947 "vl1.="<<&vecL1<< // linear fits
948 "vl2.="<<&vecL2<< // linear fits
952 if (TMath::Abs(fMagF)<0.005){
956 if (nl1>10 && nl2>10 &&(acceptLinear==0)){
957 if (seed) ProcessDiff(tp1,tp2, seed,s1,s2);
958 if (TMath::Abs(parLine1[2])<0.8 &&TMath::Abs(parLine1[2])<0.8 ){ //angular cut
959 FillHisto(parLine1,parLine2,s1,s2);
960 ProcessAlign(parLine1,parLine2,s1,s2);
961 //UpdateKalman(s1,s2,par1, cov1, par2, cov2); - OBSOLETE to be removed - 50 % of time here
965 if (accept>0) return;
967 // fill resolution histograms - previous cut included
968 if (TMath::Abs(fMagF)>0.005){
970 // use Kalman if mag field
973 ProcessDiff(tp1,tp2, seed,s1,s2);
974 FillHisto((AliExternalTrackParam*)&tp1,(AliExternalTrackParam*)&tp2,s1,s2);
975 FillHisto((AliExternalTrackParam*)&tp2,(AliExternalTrackParam*)&tp1,s2,s1);
977 FillHisto(t1,t2,s1,s2);
978 ProcessAlign(t1,t2,s1,s2);
982 void AliTPCcalibAlign::ProcessAlign(Double_t * t1,
986 // Do intersector alignment
988 //Process12(t1,t2,GetOrMakeFitter12(s1,s2));
989 //Process9(t1,t2,GetOrMakeFitter9(s1,s2));
990 Process6(t1,t2,GetOrMakeFitter6(s1,s2));
991 ++fPoints[GetIndex(s1,s2)];
994 void AliTPCcalibAlign::ProcessTree(TTree * chainTracklet, AliExternalComparison *comp){
996 // Process the debug streamer tree
997 // Possible to modify selection criteria
998 // Used with entry list
1000 TTreeSRedirector * cstream = new TTreeSRedirector("aligndump.root");
1002 AliTPCcalibAlign *align = this;
1004 TVectorD * vec1 = 0;
1005 TVectorD * vec2 = 0;
1006 AliExternalTrackParam * tp1 = 0;
1007 AliExternalTrackParam * tp2 = 0;
1012 Int_t entries=chainTracklet->GetEntries();
1013 for (Int_t i=0; i< entries; i++){
1014 chainTracklet->GetBranch("tp1.")->SetAddress(&tp1);
1015 chainTracklet->GetBranch("tp2.")->SetAddress(&tp2);
1016 chainTracklet->GetBranch("v1.")->SetAddress(&vec1);
1017 chainTracklet->GetBranch("v2.")->SetAddress(&vec2);
1018 chainTracklet->GetBranch("s1")->SetAddress(&s1);
1019 chainTracklet->GetBranch("s2")->SetAddress(&s2);
1020 chainTracklet->GetEntry(i);
1021 if (!vec1) continue;
1022 if (!vec2) continue;
1025 if (!vec1->GetMatrixArray()) continue;
1026 if (!vec2->GetMatrixArray()) continue;
1027 // make a local copy
1028 AliExternalTrackParam par1(*tp1);
1029 AliExternalTrackParam par2(*tp2);
1030 TVectorD svec1(*vec1);
1031 TVectorD svec2(*vec2);
1033 if (s1==s2) continue;
1034 if (i%100==0) printf("%d\t%d\t%d\t%d\t\n",i, npoints,s1,s2);
1035 AliExternalTrackParam cpar1(par1);
1036 AliExternalTrackParam cpar2(par2);
1037 Constrain1Pt(cpar1,par2,fNoField);
1038 Constrain1Pt(cpar2,par1,fNoField);
1039 Bool_t acceptComp = kFALSE;
1040 if (comp) acceptComp=comp->AcceptPair(&par1,&par2);
1041 if (comp) acceptComp&=comp->AcceptPair(&cpar1,&cpar2);
1043 Int_t reject = align->AcceptTracklet(par1,par2);
1044 Int_t rejectC =align->AcceptTracklet(cpar1,cpar2);
1046 if (1||fStreamLevel>0){
1047 (*cstream)<<"Tracklet"<<
1051 "rejectC="<<rejectC<<
1052 "acceptComp="<<acceptComp<<
1066 if (acceptComp) comp->Process(&cpar1,&cpar2);
1068 if (reject>0 || rejectC>0) continue;
1070 align->ProcessTracklets(cpar1,cpar2,0,s1,s2);
1071 align->ProcessTracklets(cpar2,cpar1,0,s2,s1);
1078 Int_t AliTPCcalibAlign::AcceptTracklet(const AliExternalTrackParam &p1,
1079 const AliExternalTrackParam &p2) const
1083 // Accept pair of tracklets?
1087 TCut cutS0("sqrt(tp2.fC[0]+tp1.fC[0])<0.2");
1088 TCut cutS1("sqrt(tp2.fC[2]+tp1.fC[2])<0.2");
1089 TCut cutS2("sqrt(tp2.fC[5]+tp1.fC[5])<0.01");
1090 TCut cutS3("sqrt(tp2.fC[9]+tp1.fC[9])<0.01");
1091 TCut cutS4("sqrt(tp2.fC[14]+tp1.fC[14])<0.25");
1092 TCut cutS=cutS0+cutS1+cutS2+cutS3+cutS4;
1094 // parameters matching cuts
1095 TCut cutP0("abs(tp1.fP[0]-tp2.fP[0])<0.6");
1096 TCut cutP1("abs(tp1.fP[1]-tp2.fP[1])<0.6");
1097 TCut cutP2("abs(tp1.fP[2]-tp2.fP[2])<0.03");
1098 TCut cutP3("abs(tp1.fP[3]-tp2.fP[3])<0.03");
1099 TCut cutP4("abs(tp1.fP[4]-tp2.fP[4])<0.5");
1100 TCut cutPP4("abs(tp1.fP[4]-tp2.fP[4])/sqrt(tp2.fC[14]+tp1.fC[14])<3");
1101 TCut cutP=cutP0+cutP1+cutP2+cutP3+cutP4+cutPP4;
1106 const Double_t *cp1 = p1.GetCovariance();
1107 const Double_t *cp2 = p2.GetCovariance();
1108 if (TMath::Sqrt(cp1[0]+cp2[0])>0.2) reject|=1;;
1109 if (TMath::Sqrt(cp1[2]+cp2[2])>0.2) reject|=2;
1110 if (TMath::Sqrt(cp1[5]+cp2[5])>0.01) reject|=4;
1111 if (TMath::Sqrt(cp1[9]+cp2[9])>0.01) reject|=8;
1112 if (TMath::Sqrt(cp1[14]+cp2[14])>0.2) reject|=16;
1114 //parameters difference
1115 const Double_t *tp1 = p1.GetParameter();
1116 const Double_t *tp2 = p2.GetParameter();
1117 if (TMath::Abs(tp1[0]-tp2[0])>0.6) reject|=32;
1118 if (TMath::Abs(tp1[1]-tp2[1])>0.6) reject|=64;
1119 if (TMath::Abs(tp1[2]-tp2[2])>0.03) reject|=128;
1120 if (TMath::Abs(tp1[3]-tp2[3])>0.03) reject|=526;
1121 if (TMath::Abs(tp1[4]-tp2[4])>0.4) reject|=1024;
1122 if (TMath::Abs(tp1[4]-tp2[4])/TMath::Sqrt(cp1[14]+cp2[14])>4) reject|=2048;
1125 if (TMath::Abs(tp2[1])>235) reject|=2*4096;
1135 Int_t AliTPCcalibAlign::AcceptTracklet(const Double_t *t1, const Double_t *t2) const
1138 // accept tracklet -
1139 // dist cut + 6 sigma cut
1141 Double_t dy = t2[1]-t1[1];
1142 Double_t dphi = t2[2]-t1[2];
1143 Double_t dz = t2[3]-t1[3];
1144 Double_t dtheta = t2[4]-t1[4];
1146 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]+0.05*0.05);
1147 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]+0.001*0.001);
1148 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]+0.05*0.05);
1149 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]+0.001*0.001);
1152 if (TMath::Abs(dy)>1.) reject|=2;
1153 if (TMath::Abs(dphi)>0.1) reject|=4;
1154 if (TMath::Abs(dz)>1.) reject|=8;
1155 if (TMath::Abs(dtheta)>0.1) reject|=16;
1157 if (TMath::Abs(dy/sy)>6) reject|=32;
1158 if (TMath::Abs(dphi/sdydx)>6) reject|=64;
1159 if (TMath::Abs(dz/sz)>6) reject|=128;
1160 if (TMath::Abs(dtheta/sdzdx)>6) reject|=256;
1165 void AliTPCcalibAlign::ProcessDiff(const AliExternalTrackParam &t1,
1166 const AliExternalTrackParam &t2,
1167 const AliTPCseed *seed,
1171 // Process local residuals function
1176 TVectorD vecClY(160);
1177 TVectorD vecClZ(160);
1178 TClonesArray arrCl("AliTPCclusterMI",160);
1179 arrCl.ExpandCreateFast(160);
1180 Int_t count1=0, count2=0;
1182 for (Int_t i=0;i<160;++i) {
1183 AliTPCclusterMI *c=seed->GetClusterPointer(i);
1188 AliTPCclusterMI & cl = (AliTPCclusterMI&) (*arrCl[i]);
1189 if (c->GetDetector()!=s1 && c->GetDetector()!=s2) continue;
1190 vecClY[i] = c->GetY();
1191 vecClZ[i] = c->GetZ();
1193 const AliExternalTrackParam *par = (c->GetDetector()==s1)? &t1:&t2;
1194 if (c->GetDetector()==s1) ++count1;
1195 if (c->GetDetector()==s2) ++count2;
1196 Double_t gxyz[3],xyz[3];
1198 Float_t bz = AliTracker::GetBz(gxyz);
1199 par->GetYAt(c->GetX(), bz, xyz[1]);
1200 par->GetZAt(c->GetX(), bz, xyz[2]);
1201 vecX[i] = c->GetX();
1207 if (fStreamLevel>5 && count1>10 && count2>10){
1209 // huge output - cluster residuals to be investigated
1211 TTreeSRedirector *cstream = GetDebugStreamer();
1212 AliExternalTrackParam *p1 = &((AliExternalTrackParam&)t1);
1213 AliExternalTrackParam *p2 = &((AliExternalTrackParam&)t2);
1216 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");
1221 (*cstream)<<"Track"<<
1222 "run="<<fRun<< // run number
1223 "event="<<fEvent<< // event number
1224 "time="<<fTime<< // time stamp of event
1225 "trigger="<<fTrigger<< // trigger
1226 "triggerClass="<<&fTriggerClass<< // trigger
1227 "mag="<<fMagF<< // magnetic field
1249 void AliTPCcalibAlign::Process12(const Double_t *t1,
1251 TLinearFitter *fitter) const
1253 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1254 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1255 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1256 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1257 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1259 // a00 a01 a02 a03 p[0] p[1] p[2] p[9]
1260 // a10 a11 a12 a13 ==> p[3] p[4] p[5] p[10]
1261 // a20 a21 a22 a23 p[6] p[7] p[8] p[11]
1265 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1266 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1269 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1270 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1271 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1272 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1277 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1278 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1279 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1280 for (Int_t i=0; i<12;i++) p[i]=0.;
1285 p[0+1] = y1*dydx2; // a01
1286 p[0+2] = z1*dydx2; // a02
1287 p[9+0] = dydx2; // a03
1289 fitter->AddPoint(p,value,sy);
1291 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1292 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1293 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1294 for (Int_t i=0; i<12;i++) p[i]=0.;
1299 p[0+1] = y1*dzdx2; // a01
1300 p[0+2] = z1*dzdx2; // a02
1301 p[9+0] = dzdx2; // a03
1303 fitter->AddPoint(p,value,sz);
1305 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1306 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1307 for (Int_t i=0; i<12;i++) p[i]=0.;
1309 p[3+1] = dydx1; // a11
1310 p[3+2] = dzdx1; // a12
1311 p[0+0] = -dydx2; // a00
1312 p[0+1] = -dydx1*dydx2; // a01
1313 p[0+2] = -dzdx1*dydx2; // a02
1315 fitter->AddPoint(p,value,sdydx);
1317 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1318 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1319 for (Int_t i=0; i<12;i++) p[i]=0.;
1321 p[6+1] = dydx1; // a21
1322 p[6+2] = dzdx1; // a22
1323 p[0+0] = -dzdx2; // a00
1324 p[0+1] = -dydx1*dzdx2; // a01
1325 p[0+2] = -dzdx1*dzdx2; // a02
1327 fitter->AddPoint(p,value,sdzdx);
1330 void AliTPCcalibAlign::Process9(const Double_t * const t1,
1331 const Double_t * const t2,
1332 TLinearFitter *fitter) const
1334 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1335 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1336 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1337 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1338 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1340 // a00 a01 a02 a03 1 p[0] p[1] p[6]
1341 // a10 a11 a12 a13 ==> p[2] 1 p[3] p[7]
1342 // a20 a21 a21 a23 p[4] p[5] 1 p[8]
1345 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1346 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1348 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1349 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1350 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1351 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1357 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1358 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1359 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1360 for (Int_t i=0; i<12;i++) p[i]=0.;
1365 p[0] += y1*dydx2; // a01
1366 p[1] += z1*dydx2; // a02
1367 p[6] += dydx2; // a03
1368 value = y2-y1; //-a11
1369 fitter->AddPoint(p,value,sy);
1371 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1372 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1373 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1374 for (Int_t i=0; i<12;i++) p[i]=0.;
1379 p[0] += y1*dzdx2; // a01
1380 p[1] += z1*dzdx2; // a02
1381 p[6] += dzdx2; // a03
1382 value = z2-z1; //-a22
1383 fitter->AddPoint(p,value,sz);
1385 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1386 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1387 for (Int_t i=0; i<12;i++) p[i]=0.;
1389 //p[] += dydx1; // a11
1390 p[3] += dzdx1; // a12
1391 //p[] += -dydx2; // a00
1392 p[0] += -dydx1*dydx2; // a01
1393 p[1] += -dzdx1*dydx2; // a02
1394 value = -dydx1+dydx2; // -a11 + a00
1395 fitter->AddPoint(p,value,sdydx);
1397 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1398 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1399 for (Int_t i=0; i<12;i++) p[i]=0.;
1401 p[5] += dydx1; // a21
1402 //p[] += dzdx1; // a22
1403 //p[] += -dzdx2; // a00
1404 p[0] += -dydx1*dzdx2; // a01
1405 p[1] += -dzdx1*dzdx2; // a02
1406 value = -dzdx1+dzdx2; // -a22 + a00
1407 fitter->AddPoint(p,value,sdzdx);
1410 void AliTPCcalibAlign::Process6(const Double_t *const t1,
1411 const Double_t *const t2,
1412 TLinearFitter *fitter) const
1414 // x2 = 1 *x1 +-a01*y1 + 0 +a03
1415 // y2 = a01*x1 + 1 *y1 + 0 +a13
1416 // z2 = a20*x1 + a21*y1 + 1 *z1 +a23
1417 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1418 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
1420 // a00 a01 a02 a03 1 -p[0] 0 p[3]
1421 // a10 a11 a12 a13 ==> p[0] 1 0 p[4]
1422 // a20 a21 a21 a23 p[1] p[2] 1 p[5]
1424 const Double_t &x1=t1[0], &y1=t1[1], &z1=t1[3], &dydx1=t1[2], &dzdx1=t1[4];
1425 const Double_t /*&x2=t2[0],*/ &y2=t2[1], &z2=t2[3], &dydx2=t2[2], &dzdx2=t2[4];
1428 Double_t sy = TMath::Sqrt(t1[6]*t1[6]+t2[6]*t2[6]);
1429 Double_t sdydx = TMath::Sqrt(t1[7]*t1[7]+t2[7]*t2[7]);
1430 Double_t sz = TMath::Sqrt(t1[8]*t1[8]+t2[8]*t2[8]);
1431 Double_t sdzdx = TMath::Sqrt(t1[9]*t1[9]+t2[9]*t2[9]);
1436 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1437 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
1438 // y2' = a10*x1 + a11*y1 + a12*z1 + a13 + (a01*y1 + a02*z1 + a03)*dydx2
1439 for (Int_t i=0; i<12;i++) p[i]=0.;
1444 p[0] += -y1*dydx2; // a01
1445 //p[] += z1*dydx2; // a02
1446 p[3] += dydx2; // a03
1447 value = y2-y1; //-a11
1448 fitter->AddPoint(p,value,sy);
1450 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
1451 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
1452 // z2' = a20*x1 + a21*y1 + a22*z1 + a23 + (a01*y1 + a02*z1 + a03)*dzdx2;
1453 for (Int_t i=0; i<12;i++) p[i]=0.;
1458 p[0] += -y1*dzdx2; // a01
1459 //p[] += z1*dzdx2; // a02
1460 p[3] += dzdx2; // a03
1461 value = z2-z1; //-a22
1462 fitter->AddPoint(p,value,sz);
1464 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1465 // (a10 + a11*dydx1 + a12*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dydx2 = 0
1466 for (Int_t i=0; i<12;i++) p[i]=0.;
1468 //p[] += dydx1; // a11
1469 //p[] += dzdx1; // a12
1470 //p[] += -dydx2; // a00
1471 //p[0] += dydx1*dydx2; // a01 FIXME- 0912 MI
1472 //p[] += -dzdx1*dydx2; // a02
1473 value = -dydx1+dydx2; // -a11 + a00
1474 fitter->AddPoint(p,value,sdydx);
1476 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/( a00 + a01*dydx1 + a02*dzdx1)
1477 // (a20 + a21*dydx1 + a22*dzdx1) - (a00 + a01*dydx1 + a02*dzdx1)*dzdx2 = 0
1478 for (Int_t i=0; i<12;i++) p[i]=0.;
1480 // p[2] += dydx1; // a21 FIXME- 0912 MI
1481 //p[] += dzdx1; // a22
1482 //p[] += -dzdx2; // a00
1483 //p[0] += dydx1*dzdx2; // a01 FIXME- 0912 MI
1484 //p[] += -dzdx1*dzdx2; // a02
1485 value = -dzdx1+dzdx2; // -a22 + a00
1486 fitter->AddPoint(p,value,sdzdx);
1492 void AliTPCcalibAlign::EvalFitters(Int_t minPoints) {
1496 // Perform the fitting using linear fitters
1499 TFile fff("alignDebug.root","recreate");
1500 for (Int_t s1=0;s1<72;++s1)
1501 for (Int_t s2=0;s2<72;++s2){
1502 if ((f=GetFitter12(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1503 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1505 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1506 f->Write(Form("f12_%d_%d",s1,s2));
1508 f->Write(Form("f12_%d_%d",s1,s2));
1511 if ((f=GetFitter9(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1512 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1514 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1516 f->Write(Form("f9_%d_%d",s1,s2));
1519 if ((f=GetFitter6(s1,s2))&&fPoints[GetIndex(s1,s2)]>minPoints) {
1520 // cerr<<s1<<","<<s2<<": "<<fPoints[GetIndex(s1,s2)]<<endl;
1522 cerr<<"Evaluation failed for "<<s1<<","<<s2<<endl;
1524 f->Write(Form("f6_%d_%d",s1,s2));
1529 for (Int_t s1=0;s1<72;++s1)
1530 for (Int_t s2=0;s2<72;++s2){
1531 if (GetTransformation12(s1,s2,mat)){
1532 fMatrixArray12.AddAt(mat.Clone(), GetIndex(s1,s2));
1534 if (GetTransformation9(s1,s2,mat)){
1535 fMatrixArray9.AddAt(mat.Clone(), GetIndex(s1,s2));
1537 if (GetTransformation6(s1,s2,mat)){
1538 fMatrixArray6.AddAt(mat.Clone(), GetIndex(s1,s2));
1541 //this->Write("align");
1545 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter12(Int_t s1,Int_t s2) {
1547 // get or make fitter - general linear transformation
1549 static Int_t counter12=0;
1550 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]");
1551 TLinearFitter * fitter = GetFitter12(s1,s2);
1552 if (fitter) return fitter;
1553 // 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]");
1554 fitter =new TLinearFitter(&f12,"");
1555 fitter->StoreData(kFALSE);
1556 fFitterArray12.AddAt(fitter,GetIndex(s1,s2));
1558 // if (GetDebugLevel()>0) cerr<<"Creating fitter12 "<<s1<<","<<s2<<" : "<<counter12<<endl;
1562 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter9(Int_t s1,Int_t s2) {
1564 //get or make fitter - general linear transformation - no scaling
1566 static Int_t counter9=0;
1567 static TF1 f9("f9","x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]");
1568 TLinearFitter * fitter = GetFitter9(s1,s2);
1569 if (fitter) return fitter;
1570 // fitter =new TLinearFitter(9,"x[0]++x[1]++x[2]++x[3]++x[4]++x[5]++x[6]++x[7]++x[8]");
1571 fitter =new TLinearFitter(&f9,"");
1572 fitter->StoreData(kFALSE);
1573 fFitterArray9.AddAt(fitter,GetIndex(s1,s2));
1575 // if (GetDebugLevel()>0) cerr<<"Creating fitter12 "<<s1<<","<<s2<<" : "<<counter9<<endl;
1579 TLinearFitter* AliTPCcalibAlign::GetOrMakeFitter6(Int_t s1,Int_t s2) {
1581 // get or make fitter - 6 paramater linear tranformation
1584 // - tilting x-z, y-z
1585 static Int_t counter6=0;
1586 static TF1 f6("f6","x[0]++x[1]++x[2]++x[3]++x[4]++x[5]");
1587 TLinearFitter * fitter = GetFitter6(s1,s2);
1588 if (fitter) return fitter;
1589 // fitter=new TLinearFitter(6,"x[0]++x[1]++x[2]++x[3]++x[4]++x[5]");
1590 fitter=new TLinearFitter(&f6,"");
1591 fitter->StoreData(kFALSE);
1592 fFitterArray6.AddAt(fitter,GetIndex(s1,s2));
1594 // if (GetDebugLevel()>0) cerr<<"Creating fitter6 "<<s1<<","<<s2<<" : "<<counter6<<endl;
1602 Bool_t AliTPCcalibAlign::GetTransformation12(Int_t s1,Int_t s2,TMatrixD &a) {
1604 // GetTransformation matrix - 12 paramaters - generael linear transformation
1606 if (!GetFitter12(s1,s2))
1610 GetFitter12(s1,s2)->GetParameters(p);
1612 a[0][0]=p[0]; a[0][1]=p[1]; a[0][2]=p[2]; a[0][3]=p[9];
1613 a[1][0]=p[3]; a[1][1]=p[4]; a[1][2]=p[5]; a[1][3]=p[10];
1614 a[2][0]=p[6]; a[2][1]=p[7]; a[2][2]=p[8]; a[2][3]=p[11];
1615 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1620 Bool_t AliTPCcalibAlign::GetTransformation9(Int_t s1,Int_t s2,TMatrixD &a) {
1622 // GetTransformation matrix - 9 paramaters - general linear transformation
1625 if (!GetFitter9(s1,s2))
1629 GetFitter9(s1,s2)->GetParameters(p);
1631 a[0][0]=1; a[0][1]=p[0]; a[0][2]=p[1]; a[0][3]=p[6];
1632 a[1][0]=p[2]; a[1][1]=1; a[1][2]=p[3]; a[1][3]=p[7];
1633 a[2][0]=p[4]; a[2][1]=p[5]; a[2][2]=1; a[2][3]=p[8];
1634 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1639 Bool_t AliTPCcalibAlign::GetTransformation6(Int_t s1,Int_t s2,TMatrixD &a) {
1641 // GetTransformation matrix - 6 paramaters
1644 // 2 tilting x-z y-z
1645 if (!GetFitter6(s1,s2))
1649 GetFitter6(s1,s2)->GetParameters(p);
1651 a[0][0]=1; a[0][1]=-p[0];a[0][2]=0; a[0][3]=p[3];
1652 a[1][0]=p[0]; a[1][1]=1; a[1][2]=0; a[1][3]=p[4];
1653 a[2][0]=p[1]; a[2][1]=p[2]; a[2][2]=1; a[2][3]=p[5];
1654 a[3][0]=0.; a[3][1]=0.; a[3][2]=0.; a[3][3]=1.;
1659 void AliTPCcalibAlign::MakeResidualHistos(){
1661 // Make cluster residual histograms
1663 Double_t xminTrack[9], xmaxTrack[9];
1665 TString axisName[9],axisTitle[9];
1667 // 0 - delta of interest
1668 // 1 - global phi in sector number as float
1673 axisName[0]="delta"; axisTitle[0]="#Delta (cm)";
1674 binsTrack[0]=60; xminTrack[0]=-0.6; xmaxTrack[0]=0.6;
1676 axisName[1]="sector"; axisTitle[1]="Sector Number";
1677 binsTrack[1]=180; xminTrack[1]=0; xmaxTrack[1]=18;
1679 axisName[2]="R"; axisTitle[2]="r (cm)";
1680 binsTrack[2]=53; xminTrack[2]=85.; xmaxTrack[2]=245.;
1683 axisName[3]="kZ"; axisTitle[3]="dz/dx";
1684 binsTrack[3]=36; xminTrack[3]=-1.8; xmaxTrack[3]=1.8;
1686 fClusterDelta[0] = new THnSparseS("#Delta_{Y} (cm)","#Delta_{Y} (cm)", 4, binsTrack,xminTrack, xmaxTrack);
1687 fClusterDelta[1] = new THnSparseS("#Delta_{Z} (cm)","#Delta_{Z} (cm)", 4, binsTrack,xminTrack, xmaxTrack);
1691 for (Int_t ivar=0;ivar<2;ivar++){
1692 for (Int_t ivar2=0;ivar2<4;ivar2++){
1693 fClusterDelta[ivar]->GetAxis(ivar2)->SetName(axisName[ivar2].Data());
1694 fClusterDelta[ivar]->GetAxis(ivar2)->SetTitle(axisName[ivar2].Data());
1701 void AliTPCcalibAlign::MakeResidualHistosTracklet(){
1703 // Make tracklet residual histograms
1705 Double_t xminTrack[9], xmaxTrack[9];
1707 TString axisName[9],axisTitle[9];
1709 // 0 - delta of interest
1710 // 1 - global phi in sector number as float
1717 axisName[0]="delta"; axisTitle[0]="#Delta (cm)";
1718 binsTrack[0]=60; xminTrack[0]=-0.6; xmaxTrack[0]=0.6;
1720 axisName[1]="phi"; axisTitle[1]="#phi";
1721 binsTrack[1]=180; xminTrack[1]=-TMath::Pi(); xmaxTrack[1]=TMath::Pi();
1723 axisName[2]="localX"; axisTitle[2]="x (cm)";
1724 binsTrack[2]=10; xminTrack[2]=120.; xmaxTrack[2]=200.;
1726 axisName[3]="kY"; axisTitle[3]="dy/dx";
1727 binsTrack[3]=10; xminTrack[3]=-0.5; xmaxTrack[3]=0.5;
1729 axisName[4]="kZ"; axisTitle[4]="dz/dx";
1730 binsTrack[4]=22; xminTrack[4]=-1.1; xmaxTrack[4]=1.1;
1732 axisName[5]="is1"; axisTitle[5]="is1";
1733 binsTrack[5]=72; xminTrack[5]=0; xmaxTrack[5]=72;
1735 axisName[6]="is0"; axisTitle[6]="is0";
1736 binsTrack[6]=72; xminTrack[6]=0; xmaxTrack[6]=72;
1739 xminTrack[0]=-0.3; xmaxTrack[0]=0.3;
1740 fTrackletDelta[0] = new THnSparseF("#Delta_{Y} (cm)","#Delta_{Y} (cm)", 7, binsTrack,xminTrack, xmaxTrack);
1741 xminTrack[0]=-0.5; xmaxTrack[0]=0.5;
1742 fTrackletDelta[1] = new THnSparseF("#Delta_{Z} (cm)","#Delta_{Z} (cm)", 7, binsTrack,xminTrack, xmaxTrack);
1743 xminTrack[0]=-0.005; xmaxTrack[0]=0.005;
1744 fTrackletDelta[2] = new THnSparseF("#Delta_{kY}","#Delta_{kY}", 7, binsTrack,xminTrack, xmaxTrack);
1745 xminTrack[0]=-0.005; xmaxTrack[0]=0.005;
1746 fTrackletDelta[3] = new THnSparseF("#Delta_{kZ}","#Delta_{kZ}", 7, binsTrack,xminTrack, xmaxTrack);
1750 for (Int_t ivar=0;ivar<4;ivar++){
1751 for (Int_t ivar2=0;ivar2<7;ivar2++){
1752 fTrackletDelta[ivar]->GetAxis(ivar2)->SetName(axisName[ivar2].Data());
1753 fTrackletDelta[ivar]->GetAxis(ivar2)->SetTitle(axisName[ivar2].Data());
1761 void AliTPCcalibAlign::FillHisto(const Double_t *t1,
1763 Int_t s1,Int_t s2) {
1765 // Fill residual histograms
1771 Double_t dy = t2[1]-t1[1];
1772 Double_t dphi = t2[2]-t1[2];
1773 Double_t dz = t2[3]-t1[3];
1774 Double_t dtheta = t2[4]-t1[4];
1775 Double_t zmean = (t2[3]+t1[3])*0.5;
1777 GetHisto(kPhi,s1,s2,kTRUE)->Fill(dphi);
1778 GetHisto(kTheta,s1,s2,kTRUE)->Fill(dtheta);
1779 GetHisto(kY,s1,s2,kTRUE)->Fill(dy);
1780 GetHisto(kZ,s1,s2,kTRUE)->Fill(dz);
1782 GetHisto(kPhiZ,s1,s2,kTRUE)->Fill(zmean,dphi);
1783 GetHisto(kThetaZ,s1,s2,kTRUE)->Fill(zmean,dtheta);
1784 GetHisto(kYz,s1,s2,kTRUE)->Fill(zmean,dy);
1785 GetHisto(kZz,s1,s2,kTRUE)->Fill(zmean,dz);
1787 GetHisto(kYPhi,s1,s2,kTRUE)->Fill(t2[2],dy);
1788 GetHisto(kZTheta,s1,s2,kTRUE)->Fill(t2[4],dz);
1793 void AliTPCcalibAlign::FillHisto(AliExternalTrackParam *tp1,
1794 AliExternalTrackParam *tp2,
1795 Int_t s1,Int_t s2) {
1797 // Fill residual histograms
1799 const Double_t kEpsilon=0.001;
1800 Double_t x[8]={0,0,0,0,0,0,0,0};
1801 AliExternalTrackParam p1(*tp1);
1802 AliExternalTrackParam p2(*tp2);
1804 // inner outer - match at the IROC-OROC boundary
1805 if (!p1.PropagateTo(fXIO, AliTrackerBase::GetBz())) return;
1807 if (!p2.Rotate(p1.GetAlpha())) return;
1808 if (!p2.PropagateTo(p1.GetX(),AliTrackerBase::GetBz())) return;
1809 if (TMath::Abs(p1.GetX()-p2.GetX())>kEpsilon) return;
1812 x[1]=TMath::ATan2(xyz[1],xyz[0]);
1814 x[3]=0.5*(p1.GetSnp()+p2.GetSnp()); // mean snp
1815 x[4]=0.5*(p1.GetTgl()+p2.GetTgl()); // mean tgl
1819 x[0]=p2.GetY()-p1.GetY();
1820 fTrackletDelta[0]->Fill(x);
1821 x[0]=p2.GetZ()-p1.GetZ();
1822 fTrackletDelta[1]->Fill(x);
1823 x[0]=p2.GetSnp()-p1.GetSnp();
1824 fTrackletDelta[2]->Fill(x);
1825 x[0]=p2.GetTgl()-p1.GetTgl();
1826 fTrackletDelta[3]->Fill(x);
1827 TTreeSRedirector *cstream = GetDebugStreamer();
1829 (*cstream)<<"trackletMatch"<<
1830 "tp1.="<<tp1<< // input tracklet
1832 "p1.="<<&p1<< // tracklet in the ref frame
1843 TH1 * AliTPCcalibAlign::GetHisto(HistoType type, Int_t s1, Int_t s2, Bool_t force)
1846 // return specified residual histogram - it is only QA
1847 // if force specified the histogram and given histogram is not existing
1848 // new histogram is created
1850 if (GetIndex(s1,s2)>=72*72) return 0;
1851 TObjArray *histoArray=0;
1854 histoArray = &fDyHistArray; break;
1856 histoArray = &fDzHistArray; break;
1858 histoArray = &fDphiHistArray; break;
1860 histoArray = &fDthetaHistArray; break;
1862 histoArray = &fDyPhiHistArray; break;
1864 histoArray = &fDzThetaHistArray; break;
1866 histoArray = &fDyZHistArray; break;
1868 histoArray = &fDzZHistArray; break;
1870 histoArray = &fDphiZHistArray; break;
1872 histoArray = &fDthetaZHistArray; break;
1874 TH1 * histo= (TH1*)histoArray->At(GetIndex(s1,s2));
1875 if (histo) return histo;
1876 if (force==kFALSE) return 0;
1882 name<<"hist_y_"<<s1<<"_"<<s2;
1883 title<<"Y Missalignment for sectors "<<s1<<" and "<<s2;
1884 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.5,0.5); // +/- 5 mm
1887 name<<"hist_z_"<<s1<<"_"<<s2;
1888 title<<"Z Missalignment for sectors "<<s1<<" and "<<s2;
1889 histo = new TH1D(name.str().c_str(),title.str().c_str(),100,-0.3,0.3); // +/- 3 mm
1892 name<<"hist_phi_"<<s1<<"_"<<s2;
1893 title<<"Phi Missalignment for sectors "<<s1<<" and "<<s2;
1894 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.01,0.01); // +/- 10 mrad
1897 name<<"hist_theta_"<<s1<<"_"<<s2;
1898 title<<"Theta Missalignment for sectors "<<s1<<" and "<<s2;
1899 histo =new TH1D(name.str().c_str(),title.str().c_str(),100,-0.01,0.01); // +/- 10 mrad
1904 name<<"hist_yphi_"<<s1<<"_"<<s2;
1905 title<<"Y Missalignment for sectors Phi"<<s1<<" and "<<s2;
1906 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-1,1,100,-0.5,0.5); // +/- 5 mm
1909 name<<"hist_ztheta_"<<s1<<"_"<<s2;
1910 title<<"Z Missalignment for sectors Theta"<<s1<<" and "<<s2;
1911 histo = new TH2F(name.str().c_str(),title.str().c_str(),20,-1,1,100,-0.3,0.3); // +/- 3 mm
1917 name<<"hist_yz_"<<s1<<"_"<<s2;
1918 title<<"Y Missalignment for sectors Z"<<s1<<" and "<<s2;
1919 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.5,0.5); // +/- 5 mm
1922 name<<"hist_zz_"<<s1<<"_"<<s2;
1923 title<<"Z Missalignment for sectors Z"<<s1<<" and "<<s2;
1924 histo = new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.3,0.3); // +/- 3 mm
1927 name<<"hist_phiz_"<<s1<<"_"<<s2;
1928 title<<"Phi Missalignment for sectors Z"<<s1<<" and "<<s2;
1929 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.01,0.01); // +/- 10 mrad
1932 name<<"hist_thetaz_"<<s1<<"_"<<s2;
1933 title<<"Theta Missalignment for sectors Z"<<s1<<" and "<<s2;
1934 histo =new TH2F(name.str().c_str(),title.str().c_str(),20,-250,250,100,-0.01,0.01); // +/- 10 mrad
1939 histo->SetDirectory(0);
1940 histoArray->AddAt(histo,GetIndex(s1,s2));
1944 TGraphErrors * AliTPCcalibAlign::MakeGraph(Int_t sec0, Int_t sec1, Int_t dsec,
1945 Int_t i0, Int_t i1, FitType type)
1951 //TObjArray *fitArray=0;
1952 Double_t xsec[1000];
1953 Double_t ysec[1000];
1955 for (Int_t isec = sec0; isec<=sec1; isec++){
1956 Int_t isec2 = (isec+dsec)%72;
1959 GetTransformation6(isec,isec2,mat);break;
1961 GetTransformation9(isec,isec2,mat);break;
1963 GetTransformation12(isec,isec2,mat);break;
1966 ysec[npoints]=mat(i0,i1);
1969 TGraphErrors *gr = new TGraphErrors(npoints,xsec,ysec,0,0);
1971 sprintf(name,"Mat[%d,%d] Type=%d",i0,i1,type);
1976 void AliTPCcalibAlign::MakeTree(const char *fname, Int_t minPoints){
1978 // make tree with alignment cosntant -
1979 // For QA visualization
1982 TFile fcalib("CalibObjects.root");
1983 TObjArray * array = (TObjArray*)fcalib.Get("TPCCalib");
1984 AliTPCcalibAlign * align = ( AliTPCcalibAlign *)array->FindObject("alignTPC");
1985 align->EvalFitters();
1986 align->MakeTree("alignTree.root");
1987 TFile falignTree("alignTree.root");
1988 TTree * treeAlign = (TTree*)falignTree.Get("Align");
1990 TTreeSRedirector cstream(fname);
1991 for (Int_t s1=0;s1<72;++s1)
1992 for (Int_t s2=0;s2<72;++s2){
1997 TVectorD param6Diff; // align parameters diff
1998 TVectorD param6s1(6); // align parameters sector1
1999 TVectorD param6s2(6); // align parameters sector2
2004 TMatrixD * kpar = fSectorParamA;
2005 TMatrixD * kcov = fSectorCovarA;
2007 kpar = fSectorParamC;
2008 kcov = fSectorCovarC;
2010 for (Int_t ipar=0;ipar<6;ipar++){
2011 Int_t isec1 = s1%18;
2012 Int_t isec2 = s2%18;
2013 if (s1>35) isec1+=18;
2014 if (s2>35) isec2+=18;
2015 param6s1(ipar)=(*kpar)(6*isec1+ipar,0);
2016 param6s2(ipar)=(*kpar)(6*isec2+ipar,0);
2020 Double_t dy=0, dz=0, dphi=0,dtheta=0;
2021 Double_t sy=0, sz=0, sphi=0,stheta=0;
2022 Double_t ny=0, nz=0, nphi=0,ntheta=0;
2023 Double_t chi2v12=0, chi2v9=0, chi2v6=0;
2025 // TLinearFitter * fitter = 0;
2026 if (fPoints[GetIndex(s1,s2)]>minPoints){
2030 // fitter = GetFitter12(s1,s2);
2031 // npoints = fitter->GetNpoints();
2032 // chi2v12 = TMath::Sqrt(fitter->GetChisquare()/npoints);
2035 // fitter = GetFitter9(s1,s2);
2036 // npoints = fitter->GetNpoints();
2037 // chi2v9 = TMath::Sqrt(fitter->GetChisquare()/npoints);
2039 // fitter = GetFitter6(s1,s2);
2040 // npoints = fitter->GetNpoints();
2041 // chi2v6 = TMath::Sqrt(fitter->GetChisquare()/npoints);
2042 // fitter->GetParameters(param6Diff);
2044 // GetTransformation6(s1,s2,m6);
2045 // GetTransformation9(s1,s2,m9);
2046 // GetTransformation12(s1,s2,m12);
2048 // fitter = GetFitter6(s1,s2);
2049 // //fitter->FixParameter(3,0);
2050 // //fitter->Eval();
2051 // GetTransformation6(s1,s2,m6FX);
2054 his = GetHisto(kY,s1,s2);
2055 if (his) { dy = his->GetMean(); sy = his->GetRMS(); ny = his->GetEntries();}
2056 his = GetHisto(kZ,s1,s2);
2057 if (his) { dz = his->GetMean(); sz = his->GetRMS(); nz = his->GetEntries();}
2058 his = GetHisto(kPhi,s1,s2);
2059 if (his) { dphi = his->GetMean(); sphi = his->GetRMS(); nphi = his->GetEntries();}
2060 his = GetHisto(kTheta,s1,s2);
2061 if (his) { dtheta = his->GetMean(); stheta = his->GetRMS(); ntheta = his->GetEntries();}
2065 AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
2066 if (!magF) AliError("Magneticd field - not initialized");
2067 Double_t bz = magF->SolenoidField()/10.; //field in T
2070 "run="<<fRun<< // run
2072 "s1="<<s1<< // reference sector
2073 "s2="<<s2<< // sector to align
2074 "m6FX.="<<&m6FX<< // tranformation matrix
2075 "m6.="<<&m6<< // tranformation matrix
2078 "chi2v12="<<chi2v12<<
2082 "p6.="<<¶m6Diff<<
2083 "p6s1.="<<¶m6s1<<
2084 "p6s2.="<<¶m6s2<<
2085 // histograms mean RMS and entries
2104 //_____________________________________________________________________
2105 Long64_t AliTPCcalibAlign::Merge(TCollection* const list) {
2109 if (GetDebugLevel()>0) Info("AliTPCcalibAlign","Merge");
2112 if (list->IsEmpty())
2115 TIterator* iter = list->MakeIterator();
2120 TString str1(GetName());
2121 while((obj = iter->Next()) != 0)
2123 AliTPCcalibAlign* entry = dynamic_cast<AliTPCcalibAlign*>(obj);
2124 if (entry == 0) continue;
2125 if (str1.CompareTo(entry->GetName())!=0) continue;
2133 void AliTPCcalibAlign::Add(AliTPCcalibAlign * align){
2135 // Add entry - used for merging of compoents
2137 for (Int_t i=0; i<72;i++){
2138 for (Int_t j=0; j<72;j++){
2139 if (align->fPoints[GetIndex(i,j)]<1) continue;
2140 fPoints[GetIndex(i,j)]+=align->fPoints[GetIndex(i,j)];
2144 for (Int_t itype=0; itype<10; itype++){
2145 TH1 * his0=0, *his1=0;
2146 his0 = GetHisto((HistoType)itype,i,j);
2147 his1 = align->GetHisto((HistoType)itype,i,j);
2149 if (his0) his0->Add(his1);
2151 his0 = GetHisto((HistoType)itype,i,j,kTRUE);
2158 TLinearFitter *f0=0;
2159 TLinearFitter *f1=0;
2160 for (Int_t i=0; i<72;i++){
2161 for (Int_t j=0; j<72;j++){
2162 if (align->fPoints[GetIndex(i,j)]<1) continue;
2166 f0 = GetFitter12(i,j);
2167 f1 = align->GetFitter12(i,j);
2169 if (f0) f0->Add(f1);
2171 fFitterArray12.AddAt(f1->Clone(),GetIndex(i,j));
2176 f0 = GetFitter9(i,j);
2177 f1 = align->GetFitter9(i,j);
2179 if (f0) f0->Add(f1);
2181 fFitterArray9.AddAt(f1->Clone(),GetIndex(i,j));
2184 f0 = GetFitter6(i,j);
2185 f1 = align->GetFitter6(i,j);
2187 if (f0) f0->Add(f1);
2189 fFitterArray6.AddAt(f1->Clone(),GetIndex(i,j));
2195 // Add Kalman filter
2197 for (Int_t i=0;i<36;i++){
2198 TMatrixD *par0 = (TMatrixD*)fArraySectorIntParam.At(i);
2201 par0 = (TMatrixD*)fArraySectorIntParam.At(i);
2203 TMatrixD *par1 = (TMatrixD*)align->fArraySectorIntParam.At(i);
2204 if (!par1) continue;
2206 TMatrixD *cov0 = (TMatrixD*)fArraySectorIntCovar.At(i);
2207 TMatrixD *cov1 = (TMatrixD*)align->fArraySectorIntCovar.At(i);
2208 UpdateSectorKalman(*par0,*cov0,*par1,*cov1);
2210 if (!fSectorParamA){
2213 if (align->fSectorParamA){
2214 UpdateKalman(*fSectorParamA,*fSectorCovarA,*align->fSectorParamA,*align->fSectorCovarA);
2215 UpdateKalman(*fSectorParamC,*fSectorCovarC,*align->fSectorParamC,*align->fSectorCovarC);
2217 if (!fClusterDelta[0]) MakeResidualHistos();
2219 for (Int_t i=0; i<2; i++){
2220 if (align->fClusterDelta[i]) fClusterDelta[i]->Add(align->fClusterDelta[i]);
2223 for (Int_t i=0; i<4; i++){
2224 if (!fTrackletDelta[i] && align->fTrackletDelta[i]) {
2225 fTrackletDelta[i]= (THnSparse*)(align->fTrackletDelta[i]->Clone());
2228 if (align->fTrackletDelta[i]) fTrackletDelta[i]->Add(align->fTrackletDelta[i]);
2233 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){
2235 // GetTransformed value
2238 // x2 = a00*x1 + a01*y1 + a02*z1 + a03
2239 // y2 = a10*x1 + a11*y1 + a12*z1 + a13
2240 // z2 = a20*x1 + a21*y1 + a22*z1 + a23
2241 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2242 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2245 const TMatrixD * mat = GetTransformation(s1,s2,type);
2247 if (value==0) return x1;
2248 if (value==1) return y1;
2249 if (value==2) return z1;
2250 if (value==3) return dydx1;
2251 if (value==4) return dzdx1;
2253 if (value==5) return dydx1;
2254 if (value==6) return dzdx1;
2260 valT = (*mat)(0,0)*x1+(*mat)(0,1)*y1+(*mat)(0,2)*z1+(*mat)(0,3);
2264 valT = (*mat)(1,0)*x1+(*mat)(1,1)*y1+(*mat)(1,2)*z1+(*mat)(1,3);
2267 valT = (*mat)(2,0)*x1+(*mat)(2,1)*y1+(*mat)(2,2)*z1+(*mat)(2,3);
2270 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2271 valT = (*mat)(1,0) +(*mat)(1,1)*dydx1 +(*mat)(1,2)*dzdx1;
2272 valT/= ((*mat)(0,0) +(*mat)(0,1)*dydx1 +(*mat)(0,2)*dzdx1);
2276 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2277 valT = (*mat)(2,0) +(*mat)(2,1)*dydx1 +(*mat)(2,2)*dzdx1;
2278 valT/= ((*mat)(0,0) +(*mat)(0,1)*dydx1 +(*mat)(0,2)*dzdx1);
2282 // onlys shift in angle
2283 // dydx2 = (a10 + a11*dydx1 + a12*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2284 valT = (*mat)(1,0) +(*mat)(1,1)*dydx1;
2288 // only shift in angle
2289 // dzdx2 = (a20 + a21*dydx1 + a22*dzdx1)/(a00 + a01*dydx1 + a02*dzdx1)
2290 valT = (*mat)(2,0) +(*mat)(2,1)*dydx1;
2297 void AliTPCcalibAlign::Constrain1Pt(AliExternalTrackParam &track1, const AliExternalTrackParam &track2, Bool_t noField){
2299 // Update track parameters t1
2301 TMatrixD vecXk(5,1); // X vector
2302 TMatrixD covXk(5,5); // X covariance
2303 TMatrixD matHk(1,5); // vector to mesurement
2304 TMatrixD measR(1,1); // measurement error
2305 //TMatrixD matQk(5,5); // prediction noise vector
2306 TMatrixD vecZk(1,1); // measurement
2308 TMatrixD vecYk(1,1); // Innovation or measurement residual
2309 TMatrixD matHkT(5,1);
2310 TMatrixD matSk(1,1); // Innovation (or residual) covariance
2311 TMatrixD matKk(5,1); // Optimal Kalman gain
2312 TMatrixD mat1(5,5); // update covariance matrix
2313 TMatrixD covXk2(5,5); //
2314 TMatrixD covOut(5,5);
2316 Double_t *param1=(Double_t*) track1.GetParameter();
2317 Double_t *covar1=(Double_t*) track1.GetCovariance();
2320 // copy data to the matrix
2321 for (Int_t ipar=0; ipar<5; ipar++){
2322 vecXk(ipar,0) = param1[ipar];
2323 for (Int_t jpar=0; jpar<5; jpar++){
2324 covXk(ipar,jpar) = covar1[track1.GetIndex(ipar, jpar)];
2330 vecZk(0,0) = track2.GetParameter()[4]; // 1/pt measurement from track 2
2331 measR(0,0) = track2.GetCovariance()[14]; // 1/pt measurement error
2333 measR(0,0)*=0.000000001;
2337 matHk(0,0)=0; matHk(0,1)= 0; matHk(0,2)= 0;
2338 matHk(0,3)= 0; matHk(0,4)= 1; // vector to measurement
2342 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
2343 matHkT=matHk.T(); matHk.T();
2344 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
2346 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
2347 vecXk += matKk*vecYk; // updated vector
2348 mat1(0,0)=1; mat1(1,1)=1; mat1(2,2)=1; mat1(3,3)=1; mat1(4,4)=1;
2349 covXk2 = (mat1-(matKk*matHk));
2350 covOut = covXk2*covXk;
2354 // copy from matrix to parameters
2363 for (Int_t ipar=0; ipar<5; ipar++){
2364 param1[ipar]= vecXk(ipar,0) ;
2365 for (Int_t jpar=0; jpar<5; jpar++){
2366 covar1[track1.GetIndex(ipar, jpar)]=covOut(ipar,jpar);
2372 void AliTPCcalibAlign::GlobalAlign6(Int_t minPoints, Float_t sysError, Int_t niter){
2374 // Global Align -combine the partial alignment of pair of sectors
2375 // minPoints - minimal number of points - don't use sector alignment wit smaller number
2376 // sysError - error added to the alignemnt error
2378 AliTPCcalibAlign * align = this;
2379 TMatrixD * arrayAlign[72];
2380 TMatrixD * arrayAlignDiff[72];
2382 for (Int_t i=0;i<72; i++) {
2383 TMatrixD * mat = new TMatrixD(4,4);
2386 arrayAlignDiff[i]=(TMatrixD*)(mat->Clone());
2389 TTreeSRedirector *cstream = new TTreeSRedirector("galign6.root");
2390 for (Int_t iter=0; iter<niter;iter++){
2391 printf("Iter=\t%d\n",iter);
2392 for (Int_t is0=0;is0<72; is0++) {
2394 //TMatrixD *mati0 = arrayAlign[is0];
2395 TMatrixD matDiff(4,4);
2397 for (Int_t is1=0;is1<72; is1++) {
2398 Bool_t invers=kFALSE;
2402 const TMatrixD *mat = align->GetTransformation(is0,is1,0);
2404 npoints = align->GetFitter6(is0,is1)->GetNpoints();
2405 if (npoints>minPoints){
2406 align->GetFitter6(is0,is1)->GetCovarianceMatrix(covar);
2407 align->GetFitter6(is0,is1)->GetErrors(errors);
2412 mat = align->GetTransformation(is1,is0,0);
2414 npoints = align->GetFitter6(is1,is0)->GetNpoints();
2415 if (npoints>minPoints){
2416 align->GetFitter6(is1,is0)->GetCovarianceMatrix(covar);
2417 align->GetFitter6(is1,is0)->GetErrors(errors);
2422 if (npoints<minPoints) continue;
2425 if (is1/36>is0/36) weight*=2./3.; //IROC-OROC
2426 if (is1/36<is0/36) weight*=1./3.; //OROC-IROC
2427 if (is1/36==is0/36) weight*=1/3.; //OROC-OROC
2428 if (is1%36!=is0%36) weight*=1/2.; //Not up-down
2429 weight/=(errors[4]*errors[4]+sysError*sysError); // wieghting with error in Y
2432 TMatrixD matT = *mat;
2433 if (invers) matT.Invert();
2434 TMatrixD diffMat= (*(arrayAlign[is1]))*matT;
2435 diffMat-=(*arrayAlign[is0]);
2436 matDiff+=weight*diffMat;
2439 (*cstream)<<"LAlign"<<
2443 "npoints="<<npoints<<
2444 "m60.="<<arrayAlign[is0]<<
2445 "m61.="<<arrayAlign[is1]<<
2447 "diff.="<<&diffMat<<
2458 (*arrayAlignDiff[is0]) = matDiff;
2461 for (Int_t is0=0;is0<72; is0++) {
2462 if (is0<36) (*arrayAlign[is0]) += 0.4*(*arrayAlignDiff[is0]);
2463 if (is0>=36) (*arrayAlign[is0]) += 0.2*(*arrayAlignDiff[is0]);
2465 (*cstream)<<"GAlign"<<
2468 "m6.="<<arrayAlign[is0]<<
2474 for (Int_t isec=0;isec<72;isec++){
2475 fCombinedMatrixArray6.AddAt(arrayAlign[isec],isec);
2476 delete arrayAlignDiff[isec];
2481 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){
2483 // Refit tracklet linearly using clusters at given sector isec
2484 // Clusters are rotated to the reference frame of sector refSector
2486 // fit parameters and errors retruning in the fitParam
2488 // seed - acces to the original clusters
2489 // isec - sector to be refited
2501 // ref sector is the sector defining ref frame - rotation
2502 // return value - number of used clusters
2504 const Int_t kMinClusterF=15;
2505 const Int_t kdrow1 =10; // rows to skip at the end
2506 const Int_t kdrow0 =3; // rows to skip at beginning
2507 const Float_t kedgeyIn=2.5;
2508 const Float_t kedgeyOut=4.0;
2509 const Float_t kMaxDist=5; // max distance -in sigma
2510 const Float_t kMaxCorrY=0.05; // max correction
2512 Double_t dalpha = 0;
2513 if ((refSector%18)!=(isec%18)){
2514 dalpha = -((refSector%18)-(isec%18))*TMath::TwoPi()/18.;
2516 Double_t ca = TMath::Cos(dalpha);
2517 Double_t sa = TMath::Sin(dalpha);
2520 AliTPCPointCorrection * corr = AliTPCPointCorrection::Instance();
2522 // full track fit parameters
2524 static TLinearFitter fyf(2,"pol1"); // change to static - suggestion of calgrind - 30 % of time
2525 static TLinearFitter fzf(2,"pol1"); // relative to time of given class
2526 TVectorD pyf(2), peyf(2),pzf(2), pezf(2);
2527 TMatrixD covY(4,4),covZ(4,4);
2528 Double_t chi2FacY =1;
2529 Double_t chi2FacZ =1;
2534 Float_t erry=0.1; // initial cluster error estimate
2535 Float_t errz=0.1; // initial cluster error estimate
2536 for (Int_t iter=0; iter<2; iter++){
2539 for (Int_t irow=kdrow0;irow<159-kdrow1;irow++) {
2540 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2543 if (c->GetDetector()%36!=(isec%36)) continue;
2544 if (!both && c->GetDetector()!=isec) continue;
2546 if (c->GetRow()<kdrow0) continue;
2547 //cluster position in reference frame
2548 Double_t lxR = ca*c->GetX()-sa*c->GetY();
2549 Double_t lyR = +sa*c->GetX()+ca*c->GetY();
2550 Double_t lzR = c->GetZ();
2552 Double_t dx = lxR -xRef; // distance to reference X
2553 Double_t x[2]={dx, dx*dx};
2555 Double_t yfitR = pyf[0]+pyf[1]*dx; // fit value Y in ref frame
2556 Double_t zfitR = pzf[0]+pzf[1]*dx; // fit value Z in ref frame
2558 Double_t yfit = -sa*lxR + ca*yfitR; // fit value Y in local frame
2560 if (iter==0 &&c->GetType()<0) continue;
2562 if (TMath::Abs(lyR-yfitR)>kMaxDist*erry) continue;
2563 if (TMath::Abs(lzR-zfitR)>kMaxDist*errz) continue;
2564 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2565 if (isec<36 && dedge<kedgeyIn) continue;
2566 if (isec>35 && dedge<kedgeyOut) continue;
2568 corr->RPhiCOGCorrection(isec,c->GetRow(), c->GetPad(),
2569 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2571 corr->RPhiCOGCorrection(isec,c->GetRow(), c->GetPad(),
2572 c->GetY(),c->GetY(), c->GetZ(), pyf[1], c->GetMax(),2.5);
2573 if (TMath::Abs((corrtrY+corrclY)*0.5)>kMaxCorrY) continue;
2574 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2576 fyf.AddPoint(x,lyR,erry);
2577 fzf.AddPoint(x,lzR,errz);
2579 nf = fyf.GetNpoints();
2580 if (nf<kMinClusterF) return 0; // not enough points - skip
2582 fyf.GetParameters(pyf);
2583 fyf.GetErrors(peyf);
2585 fzf.GetParameters(pzf);
2586 fzf.GetErrors(pezf);
2587 chi2FacY = TMath::Sqrt(fyf.GetChisquare()/(fyf.GetNpoints()-2.));
2588 chi2FacZ = TMath::Sqrt(fzf.GetChisquare()/(fzf.GetNpoints()-2.));
2595 fyf.GetCovarianceMatrix(covY);
2596 fzf.GetCovarianceMatrix(covZ);
2597 for (Int_t i0=0;i0<2;i0++)
2598 for (Int_t i1=0;i1<2;i1++){
2599 covY(i0,i1)*=chi2FacY*chi2FacY;
2600 covZ(i0,i1)*=chi2FacZ*chi2FacZ;
2605 fitParam[1] = pyf[0];
2606 fitParam[2] = pyf[1];
2607 fitParam[3] = pzf[0];
2608 fitParam[4] = pzf[1];
2611 fitParam[6] = peyf[0];
2612 fitParam[7] = peyf[1];
2613 fitParam[8] = pezf[0];
2614 fitParam[9] = pezf[1];
2617 tparam(0,0) = pyf[0];
2618 tparam(1,0) = pyf[1];
2619 tparam(2,0) = pzf[0];
2620 tparam(3,0) = pzf[1];
2622 tcovar(0,0) = covY(0,0);
2623 tcovar(1,1) = covY(1,1);
2624 tcovar(1,0) = covY(1,0);
2625 tcovar(0,1) = covY(0,1);
2626 tcovar(2,2) = covZ(0,0);
2627 tcovar(3,3) = covZ(1,1);
2628 tcovar(3,2) = covZ(1,0);
2629 tcovar(2,3) = covZ(0,1);
2633 void AliTPCcalibAlign::UpdateClusterDeltaField(const AliTPCseed * seed){
2635 // Update the cluster residula histograms for setup with field
2636 // Kalman track fitting is used
2637 // Only high momenta primary tracks used
2639 // 1. Apply selection
2640 // 2. Refit the track - in-out
2641 // - update the cluster delta in upper part
2642 // 3. Refit the track - out-in
2643 // - update the cluster delta histo lower part
2645 const Double_t kPtCut=1.0; // pt
2646 const Double_t kSnpCut=0.2; // snp cut
2647 const Double_t kNclCut=120; //
2648 const Double_t kVertexCut=1;
2649 const Double_t kMaxDist=0.5; // max distance between tracks and cluster
2650 const Double_t kEdgeCut = 2.5;
2651 if (!fCurrentTrack) return;
2652 if (!fCurrentFriendTrack) return;
2653 Float_t vertexXY=0,vertexZ=0;
2654 fCurrentTrack->GetImpactParameters(vertexXY,vertexZ);
2655 if (TMath::Abs(vertexXY)>kVertexCut) return;
2656 if (TMath::Abs(vertexZ)>kVertexCut) return;
2657 if (TMath::Abs(seed->Pt())<kPtCut) return;
2658 if (seed->GetNumberOfClusters()<kNclCut) return;
2659 if (TMath::Abs(seed->GetSnp())>kSnpCut) return;
2660 if (!fClusterDelta[0]) MakeResidualHistos();
2665 AliExternalTrackParam trackIn = *(fCurrentTrack->GetInnerParam());
2666 AliExternalTrackParam trackOut = *(fCurrentFriendTrack->GetTPCOut());
2667 static Double_t mass = TDatabasePDG::Instance()->GetParticle("pi+")->Mass();
2670 for (Int_t irow=0; irow<160; irow++){
2671 AliTPCclusterMI *cl=seed->GetClusterPointer(irow);
2673 if (cl->GetX()<80) continue;
2674 if (detector<0) detector=cl->GetDetector()%36;
2675 if (detector!=cl->GetDetector()%36) return; // cluster from different sectors
2679 if (ncl<kNclCut) return;
2681 Int_t nclIn=0,nclOut=0;
2684 // Refit out - store residual maps
2686 for (Int_t irow=0; irow<160; irow++){
2687 AliTPCclusterMI *cl=seed->GetClusterPointer(irow);
2689 if (cl->GetX()<80) continue;
2690 if (detector<0) detector=cl->GetDetector()%36;
2691 Int_t sector = cl->GetDetector();
2692 Float_t dalpha = TMath::DegToRad()*(sector%18*20.+10.)-trackOut.GetAlpha();
2693 if (TMath::Abs(dalpha)>0.01){
2694 if (!trackOut.Rotate(TMath::DegToRad()*(sector%18*20.+10.))) break;
2696 Double_t r[3]={cl->GetX(),cl->GetY(),cl->GetZ()};
2697 Double_t cov[3]={0.01,0.,0.01};
2698 AliTPCseed::GetError(cl, &trackOut,cov[0],cov[2]);
2699 Double_t dedge = cl->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(trackOut.GetY());
2700 cov[0]+=1./(irow+1.); // bigger error at boundary
2701 cov[0]+=1./(160.-irow); // bigger error at boundary
2702 cov[2]+=1./(irow+1.); // bigger error at boundary
2703 cov[2]+=1./(160.-irow); // bigger error at boundary
2704 cov[0]+=0.5/dedge; // bigger error close to the boundary
2705 cov[2]+=0.5/dedge; // bigger error close to the boundary
2708 if (!AliTracker::PropagateTrackToBxByBz(&trackOut, r[0],mass,1.,kFALSE)) continue;
2710 if (TMath::Abs(dedge)<kEdgeCut) continue;
2712 if (TMath::Abs(cl->GetY()-trackOut.GetY())<kMaxDist){
2714 trackOut.Update(&r[1],cov);
2716 if (nclOut<kNclCut/2) continue;
2717 if (cl->GetDetector()%36!=detector) continue;
2719 // fill residual histogram
2721 Double_t resVector[5];
2722 trackOut.GetXYZ(xyz);
2723 resVector[1]= 9.*TMath::ATan2(xyz[1],xyz[0])/TMath::Pi();
2724 if (resVector[1]<0) resVector[1]+=18;
2725 resVector[2]= TMath::Sqrt(cl->GetX()*cl->GetX()+cl->GetY()*cl->GetY());
2726 resVector[3]= cl->GetZ()/resVector[2];
2728 resVector[0]= cl->GetY()-trackOut.GetY();
2729 fClusterDelta[0]->Fill(resVector);
2730 resVector[0]= cl->GetZ()-trackOut.GetZ();
2731 fClusterDelta[1]->Fill(resVector);
2734 // Refit in - store residual maps
2736 for (Int_t irow=159; irow>=0; irow--){
2737 AliTPCclusterMI *cl=seed->GetClusterPointer(irow);
2739 if (cl->GetX()<80) continue;
2740 if (detector<0) detector=cl->GetDetector()%36;
2741 Int_t sector = cl->GetDetector();
2742 Float_t dalpha = TMath::DegToRad()*(sector%18*20.+10.)-trackIn.GetAlpha();
2743 if (TMath::Abs(dalpha)>0.01){
2744 if (!trackIn.Rotate(TMath::DegToRad()*(sector%18*20.+10.))) break;
2746 Double_t r[3]={cl->GetX(),cl->GetY(),cl->GetZ()};
2747 Double_t cov[3]={0.01,0.,0.01};
2748 AliTPCseed::GetError(cl, &trackIn,cov[0],cov[2]);
2749 Double_t dedge = cl->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(trackIn.GetY());
2750 cov[0]+=1./(irow+1.); // bigger error at boundary
2751 cov[0]+=1./(160.-irow); // bigger error at boundary
2752 cov[2]+=1./(irow+1.); // bigger error at boundary
2753 cov[2]+=1./(160.-irow); // bigger error at boundary
2754 cov[0]+=0.5/dedge; // bigger error close to the boundary +-
2755 cov[2]+=0.5/dedge; // bigger error close to the boundary +-
2758 if (!AliTracker::PropagateTrackToBxByBz(&trackIn, r[0],mass,1.,kFALSE)) continue;
2759 if (TMath::Abs(dedge)<kEdgeCut) continue;
2762 if (TMath::Abs(cl->GetY()-trackIn.GetY())<kMaxDist){
2764 trackIn.Update(&r[1],cov);
2766 if (nclIn<kNclCut/2) continue;
2767 if (cl->GetDetector()%36!=detector) continue;
2769 // fill residual histogram
2771 Double_t resVector[5];
2772 trackIn.GetXYZ(xyz);
2773 resVector[1]= 9.*TMath::ATan2(xyz[1],xyz[0])/TMath::Pi();
2774 if (resVector[1]<0) resVector[1]+=18;
2775 resVector[2]= TMath::Sqrt(cl->GetX()*cl->GetX()+cl->GetY()*cl->GetY());
2776 resVector[3]= cl->GetZ()/resVector[2];
2778 resVector[0]= cl->GetY()-trackIn.GetY();
2779 fClusterDelta[0]->Fill(resVector);
2780 resVector[0]= cl->GetZ()-trackIn.GetZ();
2781 fClusterDelta[1]->Fill(resVector);
2788 void AliTPCcalibAlign::UpdateAlignSector(const AliTPCseed * track,Int_t isec){
2790 // Update Kalman filter of Alignment - only setup without filed
2791 // IROC - OROC quadrants
2793 if (TMath::Abs(AliTracker::GetBz())>0.5) return;
2794 if (!fClusterDelta[0]) MakeResidualHistos();
2795 const Int_t kMinClusterF=40;
2796 const Int_t kMinClusterFit=10;
2797 const Int_t kMinClusterQ=10;
2799 const Int_t kdrow1Fit =5; // rows to skip from fit at the end
2800 const Int_t kdrow0Fit =10; // rows to skip from fit at beginning
2801 const Float_t kedgey=3.0;
2802 const Float_t kMaxDist=1;
2803 const Float_t kMaxCorrY=0.05;
2804 const Float_t kPRFWidth = 0.6; //cut 2 sigma of PRF
2805 isec = isec%36; // use the hardware numbering
2808 AliTPCPointCorrection * corr = AliTPCPointCorrection::Instance();
2810 // full track fit parameters
2812 static TLinearFitter fyf(2,"pol1"); // make it static - too much time for comiling of formula
2813 static TLinearFitter fzf(2,"pol1"); // calgrind recomendation
2814 TVectorD pyf(2), peyf(2),pzf(2), pezf(2);
2815 TVectorD pyfc(2),pzfc(2);
2818 // make full fit as reference
2820 for (Int_t iter=0; iter<2; iter++){
2823 for (Int_t irow=kdrow0Fit;irow<159-kdrow1Fit;irow++) {
2824 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2826 if ((c->GetDetector()%36)!=isec) continue;
2827 if (c->GetRow()<kdrow0Fit) continue;
2828 Double_t dx = c->GetX()-fXmiddle;
2829 Double_t x[2]={dx, dx*dx};
2830 if (iter==0 &&c->GetType()<0) continue;
2832 Double_t yfit = pyf[0]+pyf[1]*dx;
2833 Double_t zfit = pzf[0]+pzf[1]*dx;
2834 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2835 if (TMath::Abs(c->GetY()-yfit)>kMaxDist) continue;
2836 if (TMath::Abs(c->GetZ()-zfit)>kMaxDist) continue;
2837 if (dedge<kedgey) continue;
2839 corr->RPhiCOGCorrection(c->GetDetector(),c->GetRow(), c->GetPad(),
2840 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2841 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2843 if (TMath::Abs(x[0])<10){
2844 fyf.AddPoint(x,c->GetY(),0.1); //use only middle rows+-10cm
2846 fzf.AddPoint(x,c->GetZ(),0.1);
2848 nf = fyf.GetNpoints();
2849 if (fyf.GetNpoints()<kMinClusterFit) return; // not enough points - skip
2850 if (fzf.GetNpoints()<kMinClusterF) return; // not enough points - skip
2852 fyf.GetParameters(pyf);
2853 fyf.GetErrors(peyf);
2855 fzf.GetParameters(pzf);
2856 fzf.GetErrors(pezf);
2861 TVectorD vecX(160); // x vector
2862 TVectorD vecY(160); // residuals vector
2863 TVectorD vecZ(160); // residuals vector
2864 TVectorD vPosG(3); //vertex position
2865 TVectorD vPosL(3); // vertex position in the TPC local system
2866 TVectorF vImpact(2); //track impact parameter
2867 // Double_t tofSignal= fCurrentTrack->GetTOFsignal(); // tof signal
2868 TVectorF tpcPosG(3); // global position of track at the middle of fXmiddle
2869 Double_t lphi = TMath::ATan2(pyf[0],fXmiddle); // expected local phi angle - if vertex at 0
2870 Double_t gphi = 2.*TMath::Pi()*(isec%18+0.5)/18.+lphi; // expected global phi if vertex at 0
2871 Double_t ky = pyf[0]/fXmiddle;
2872 Double_t kyE =0, kzE=0; // ky and kz expected
2873 Double_t alpha =2.*TMath::Pi()*(isec%18+0.5)/18.;
2874 Double_t scos=TMath::Cos(alpha);
2875 Double_t ssin=TMath::Sin(alpha);
2876 const AliESDVertex* vertex = fCurrentEvent->GetPrimaryVertexTracks();
2877 vertex->GetXYZ(vPosG.GetMatrixArray());
2878 fCurrentTrack->GetImpactParameters(vImpact[0],vImpact[1]); // track impact parameters
2880 tpcPosG[0]= scos*fXmiddle-ssin*pyf[0];
2881 tpcPosG[1]=+ssin*fXmiddle+scos*pyf[0];
2883 vPosL[0]= scos*vPosG[0]+ssin*vPosG[1];
2884 vPosL[1]=-ssin*vPosG[0]+scos*vPosG[1];
2886 kyE = (pyf[0]-vPosL[1])/(fXmiddle-vPosL[0]);
2887 kzE = (pzf[0]-vPosL[2])/(fXmiddle-vPosL[0]);
2889 // get constrained parameters
2891 Double_t xvertex=vPosL[0]-fXmiddle;
2892 fyf.AddPoint(&xvertex,vPosL[1], 0.00001);
2893 fzf.AddPoint(&xvertex,vPosL[2], 2.);
2895 fyf.GetParameters(pyfc);
2897 fzf.GetParameters(pzfc);
2900 // Make Fitters and params for 5 fitters
2901 // 1-4 OROC quadrants
2904 static TLinearFitter *fittersY[5]={0,0,0,0,0}; // calgrind recomendation - fater to clear points
2905 static TLinearFitter *fittersZ[5]={0,0,0,0,0}; // than create the fitter
2906 if (fittersY[0]==0){
2907 for (Int_t i=0;i<5;i++) {
2908 fittersY[i] = new TLinearFitter(2,"pol1");
2909 fittersZ[i] = new TLinearFitter(2,"pol1");
2914 TVectorD paramsY[5];
2915 TVectorD errorsY[5];
2918 TVectorD paramsZ[5];
2919 TVectorD errorsZ[5];
2922 for (Int_t i=0;i<5;i++) {
2924 paramsY[i].ResizeTo(2);
2925 errorsY[i].ResizeTo(2);
2926 covY[i].ResizeTo(2,2);
2927 paramsZ[i].ResizeTo(2);
2928 errorsZ[i].ResizeTo(2);
2929 covZ[i].ResizeTo(2,2);
2930 fittersY[i]->ClearPoints();
2931 fittersZ[i]->ClearPoints();
2937 for (Int_t irow=0;irow<159;irow++) {
2938 AliTPCclusterMI *c=track->GetClusterPointer(irow);
2940 if ((c->GetDetector()%36)!=isec) continue;
2941 Double_t dx = c->GetX()-fXmiddle;
2942 Double_t x[2]={dx, dx*dx};
2943 Double_t yfit = pyf[0]+pyf[1]*dx;
2944 Double_t zfit = pzf[0]+pzf[1]*dx;
2945 Double_t yfitC = pyfc[0]+pyfc[1]*dx;
2946 Double_t zfitC = pzfc[0]+pzfc[1]*dx;
2947 Double_t dedge = c->GetX()*TMath::Tan(TMath::Pi()/18.)-TMath::Abs(yfit);
2948 if (TMath::Abs(c->GetY()-yfit)>kMaxDist) continue;
2949 if (TMath::Abs(c->GetZ()-zfit)>kMaxDist) continue;
2950 if (dedge<kedgey) continue;
2952 corr->RPhiCOGCorrection(c->GetDetector(),c->GetRow(), c->GetPad(),
2953 c->GetY(),yfit, c->GetZ(), pyf[1], c->GetMax(),2.5);
2954 if (TMath::Abs(corrtrY)>kMaxCorrY) continue;
2956 vecX[countRes]=c->GetX();
2957 vecY[countRes]=c->GetY()-yfit;
2958 vecZ[countRes]=c->GetZ()-zfit;
2961 // Fill THnSparse cluster residuals
2962 // use only primary candidates with ITS signal
2963 if (fCurrentTrack->IsOn(0x4)&&TMath::Abs(vImpact[0])<1&&TMath::Abs(vImpact[1])<1){
2964 Double_t resVector[5];
2965 resVector[1]= 9.*gphi/TMath::Pi();
2966 resVector[2]= TMath::Sqrt(c->GetX()*c->GetX()+c->GetY()*c->GetY());
2967 resVector[3]= c->GetZ()/resVector[2];
2970 resVector[0]= c->GetY()-yfitC;
2971 fClusterDelta[0]->Fill(resVector);
2972 resVector[0]= c->GetZ()-zfitC;
2973 fClusterDelta[1]->Fill(resVector);
2975 if (c->GetRow()<kdrow0Fit) continue;
2976 if (c->GetRow()>159-kdrow1Fit) continue;
2979 if (c->GetDetector()>35){
2980 if (c->GetX()<fXquadrant){
2981 if (yfit<-kPRFWidth) fittersY[1]->AddPoint(x,c->GetY(),0.1);
2982 if (yfit<-kPRFWidth) fittersZ[1]->AddPoint(x,c->GetZ(),0.1);
2983 if (yfit>kPRFWidth) fittersY[2]->AddPoint(x,c->GetY(),0.1);
2984 if (yfit>kPRFWidth) fittersZ[2]->AddPoint(x,c->GetZ(),0.1);
2986 if (c->GetX()>fXquadrant){
2987 if (yfit<-kPRFWidth) fittersY[3]->AddPoint(x,c->GetY(),0.1);
2988 if (yfit<-kPRFWidth) fittersZ[3]->AddPoint(x,c->GetZ(),0.1);
2989 if (yfit>kPRFWidth) fittersY[4]->AddPoint(x,c->GetY(),0.1);
2990 if (yfit>kPRFWidth) fittersZ[4]->AddPoint(x,c->GetZ(),0.1);
2993 if (c->GetDetector()<36){
2994 fittersY[0]->AddPoint(x,c->GetY(),0.1);
2995 fittersZ[0]->AddPoint(x,c->GetZ(),0.1);
3001 for (Int_t i=0;i<5;i++) {
3002 npoints[i] = fittersY[i]->GetNpoints();
3003 if (npoints[i]>=kMinClusterQ){
3005 fittersY[i]->Eval();
3006 Double_t chi2FacY = TMath::Sqrt(fittersY[i]->GetChisquare()/(fittersY[i]->GetNpoints()-2));
3008 fittersY[i]->GetParameters(paramsY[i]);
3009 fittersY[i]->GetErrors(errorsY[i]);
3010 fittersY[i]->GetCovarianceMatrix(covY[i]);
3011 // renormalize errors
3012 errorsY[i][0]*=chi2FacY;
3013 errorsY[i][1]*=chi2FacY;
3014 covY[i](0,0)*=chi2FacY*chi2FacY;
3015 covY[i](0,1)*=chi2FacY*chi2FacY;
3016 covY[i](1,0)*=chi2FacY*chi2FacY;
3017 covY[i](1,1)*=chi2FacY*chi2FacY;
3019 fittersZ[i]->Eval();
3020 Double_t chi2FacZ = TMath::Sqrt(fittersZ[i]->GetChisquare()/(fittersZ[i]->GetNpoints()-2));
3022 fittersZ[i]->GetParameters(paramsZ[i]);
3023 fittersZ[i]->GetErrors(errorsZ[i]);
3024 fittersZ[i]->GetCovarianceMatrix(covZ[i]);
3025 // renormalize errors
3026 errorsZ[i][0]*=chi2FacZ;
3027 errorsZ[i][1]*=chi2FacZ;
3028 covZ[i](0,0)*=chi2FacZ*chi2FacZ;
3029 covZ[i](0,1)*=chi2FacZ*chi2FacZ;
3030 covZ[i](1,0)*=chi2FacZ*chi2FacZ;
3031 covZ[i](1,1)*=chi2FacZ*chi2FacZ;
3035 // void UpdateSectorKalman
3037 for (Int_t i0=0;i0<5;i0++){
3038 for (Int_t i1=i0+1;i1<5;i1++){
3039 if(npoints[i0]<kMinClusterQ) continue;
3040 if(npoints[i1]<kMinClusterQ) continue;
3041 TMatrixD v0(4,1),v1(4,1); // measurement
3042 TMatrixD cov0(4,4),cov1(4,4); // covariance
3044 v0(0,0)= paramsY[i0][0]; v1(0,0)= paramsY[i1][0];
3045 v0(1,0)= paramsY[i0][1]; v1(1,0)= paramsY[i1][1];
3046 v0(2,0)= paramsZ[i0][0]; v1(2,0)= paramsZ[i1][0];
3047 v0(3,0)= paramsZ[i0][1]; v1(3,0)= paramsZ[i1][1];
3049 cov0(0,0) = covY[i0](0,0);
3050 cov0(1,1) = covY[i0](1,1);
3051 cov0(1,0) = covY[i0](1,0);
3052 cov0(0,1) = covY[i0](0,1);
3053 cov0(2,2) = covZ[i0](0,0);
3054 cov0(3,3) = covZ[i0](1,1);
3055 cov0(3,2) = covZ[i0](1,0);
3056 cov0(2,3) = covZ[i0](0,1);
3058 cov1(0,0) = covY[i1](0,0);
3059 cov1(1,1) = covY[i1](1,1);
3060 cov1(1,0) = covY[i1](1,0);
3061 cov1(0,1) = covY[i1](0,1);
3062 cov1(2,2) = covZ[i1](0,0);
3063 cov1(3,3) = covZ[i1](1,1);
3064 cov1(3,2) = covZ[i1](1,0);
3065 cov1(2,3) = covZ[i1](0,1);
3069 if (TMath::Abs(pyf[1])<0.8){ //angular cut
3070 UpdateSectorKalman(isec, i0,i1, &v0,&cov0,&v1,&cov1);
3076 // Dump debug information
3078 if (fStreamLevel>0){
3079 // get vertex position
3081 TTreeSRedirector *cstream = GetDebugStreamer();
3085 for (Int_t i0=0;i0<5;i0++){
3086 for (Int_t i1=i0;i1<5;i1++){
3087 if (i0==i1) continue;
3088 if(npoints[i0]<kMinClusterQ) continue;
3089 if(npoints[i1]<kMinClusterQ) continue;
3090 (*cstream)<<"sectorAlign"<<
3091 "run="<<fRun<< // run number
3092 "event="<<fEvent<< // event number
3093 "time="<<fTime<< // time stamp of event
3094 "trigger="<<fTrigger<< // trigger
3095 "triggerClass="<<&fTriggerClass<< // trigger
3096 "mag="<<fMagF<< // magnetic field
3097 "isec="<<isec<< // current sector
3099 "xref="<<fXmiddle<< // reference X
3100 "vPosG.="<<&vPosG<< // vertex position in global system
3101 "vPosL.="<<&vPosL<< // vertex position in local system
3102 "vImpact.="<<&vImpact<< // track impact parameter
3103 //"tofSignal="<<tofSignal<< // tof signal
3104 "tpcPosG.="<<&tpcPosG<< // global position of track at the middle of fXmiddle
3105 "lphi="<<lphi<< // expected local phi angle - if vertex at 0
3106 "gphi="<<gphi<< // expected global phi if vertex at 0
3108 "kyE="<<kyE<< // expect ky - assiming pirmary track
3109 "kzE="<<kzE<< // expected kz - assuming primary tracks
3110 "salpha="<<alpha<< // sector alpha
3111 "scos="<<scos<< // tracking cosinus
3112 "ssin="<<ssin<< // tracking sinus
3116 "nf="<<nf<< // total number of points
3117 "pyf.="<<&pyf<< // full OROC fit y
3118 "pzf.="<<&pzf<< // full OROC fit z
3119 "vX.="<<&vecX<< // x cluster
3120 "vY.="<<&vecY<< // y residual cluster
3121 "vZ.="<<&vecZ<< // z residual cluster
3122 // quadrant and IROC fit
3123 "i0="<<i0<< // quadrant number
3125 "n0="<<npoints[i0]<< // number of points
3126 "n1="<<npoints[i1]<<
3128 "py0.="<<¶msY[i0]<< // parameters
3129 "py1.="<<¶msY[i1]<<
3130 "ey0.="<<&errorsY[i0]<< // errors
3131 "ey1.="<<&errorsY[i1]<<
3132 "chiy0="<<chi2CY[i0]<< // chi2s
3133 "chiy1="<<chi2CY[i1]<<
3135 "pz0.="<<¶msZ[i0]<< // parameters
3136 "pz1.="<<¶msZ[i1]<<
3137 "ez0.="<<&errorsZ[i0]<< // errors
3138 "ez1.="<<&errorsZ[i1]<<
3139 "chiz0="<<chi2CZ[i0]<< // chi2s
3140 "chiz1="<<chi2CZ[i1]<<
3148 void AliTPCcalibAlign::UpdateSectorKalman(Int_t sector, Int_t quadrant0, Int_t quadrant1, TMatrixD *const p0, TMatrixD *const c0, TMatrixD *const p1, TMatrixD *const c1 ){
3151 // tracks are refitted at sector middle
3153 if (fArraySectorIntParam.At(0)==NULL) MakeSectorKalman();
3156 static TMatrixD matHk(4,30); // vector to mesurement
3157 static TMatrixD measR(4,4); // measurement error
3158 // static TMatrixD matQk(2,2); // prediction noise vector
3159 static TMatrixD vecZk(4,1); // measurement
3161 static TMatrixD vecYk(4,1); // Innovation or measurement residual
3162 static TMatrixD matHkT(30,4); // helper matrix Hk transpose
3163 static TMatrixD matSk(4,4); // Innovation (or residual) covariance
3164 static TMatrixD matKk(30,4); // Optimal Kalman gain
3165 static TMatrixD mat1(30,30); // update covariance matrix
3166 static TMatrixD covXk2(30,30); // helper matrix
3168 TMatrixD *vOrig = (TMatrixD*)(fArraySectorIntParam.At(sector));
3169 TMatrixD *cOrig = (TMatrixD*)(fArraySectorIntCovar.At(sector));
3171 TMatrixD vecXk(*vOrig); // X vector
3172 TMatrixD covXk(*cOrig); // X covariance
3176 for (Int_t i=0;i<30;i++)
3177 for (Int_t j=0;j<30;j++){
3179 if (i==j) mat1(i,j)=1;
3183 // matHk - vector to measurement
3185 for (Int_t i=0;i<4;i++)
3186 for (Int_t j=0;j<30;j++){
3196 matHk(0,6*quadrant1+4) = 1.; // delta y
3197 matHk(1,6*quadrant1+0) = 1.; // delta ky
3198 matHk(2,6*quadrant1+5) = 1.; // delta z
3199 matHk(3,6*quadrant1+1) = 1.; // delta kz
3200 // bug fix 24.02 - aware of sign in dx
3201 matHk(0,6*quadrant1+3) = -(*p0)(1,0); // delta x to delta y - through ky
3202 matHk(2,6*quadrant1+3) = -(*p0)(3,0); // delta x to delta z - thorugh kz
3203 matHk(2,6*quadrant1+2) = ((*p0)(0,0)); // y to delta z - through psiz
3205 matHk(0,6*quadrant0+4) = -1.; // delta y
3206 matHk(1,6*quadrant0+0) = -1.; // delta ky
3207 matHk(2,6*quadrant0+5) = -1.; // delta z
3208 matHk(3,6*quadrant0+1) = -1.; // delta kz
3209 // bug fix 24.02 be aware of sign in dx
3210 matHk(0,6*quadrant0+3) = ((*p0)(1,0)); // delta x to delta y - through ky
3211 matHk(2,6*quadrant0+3) = ((*p0)(3,0)); // delta x to delta z - thorugh kz
3212 matHk(2,6*quadrant0+2) = -((*p0)(0,0)); // y to delta z - through psiz
3217 vecZk =(*p1)-(*p0); // measurement
3218 measR =(*c1)+(*c0); // error of measurement
3219 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
3222 matHkT=matHk.T(); matHk.T();
3223 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
3225 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
3226 vecXk += matKk*vecYk; // updated vector
3227 covXk2= (mat1-(matKk*matHk));
3228 covXk = covXk2*covXk;
3235 void AliTPCcalibAlign::MakeSectorKalman(){
3237 // Make a initial Kalman paramaters for IROC - Quadrants alignment
3239 TMatrixD param(5*6,1);
3240 TMatrixD covar(5*6,5*6);
3242 // Set inital parameters
3244 for (Int_t ip=0;ip<5*6;ip++) param(ip,0)=0; // mean alignment to 0
3246 for (Int_t iq=0;iq<5;iq++){
3247 // Initial uncertinty
3248 covar(iq*6+0,iq*6+0) = 0.002*0.002; // 2 mrad
3249 covar(iq*6+1,iq*6+1) = 0.002*0.002; // 2 mrad rotation
3250 covar(iq*6+2,iq*6+2) = 0.002*0.002; // 2 mrad
3252 covar(iq*6+3,iq*6+3) = 0.02*0.02; // 0.2 mm
3253 covar(iq*6+4,iq*6+4) = 0.02*0.02; // 0.2 mm translation
3254 covar(iq*6+5,iq*6+5) = 0.02*0.02; // 0.2 mm
3257 for (Int_t isec=0;isec<36;isec++){
3258 fArraySectorIntParam.AddAt(param.Clone(),isec);
3259 fArraySectorIntCovar.AddAt(covar.Clone(),isec);
3263 void AliTPCcalibAlign::UpdateSectorKalman(TMatrixD &par0, TMatrixD &cov0, TMatrixD &par1, TMatrixD &cov1){
3265 // Update kalman vector para0 with vector par1
3268 static TMatrixD matHk(30,30); // vector to mesurement
3269 static TMatrixD measR(30,30); // measurement error
3270 static TMatrixD vecZk(30,1); // measurement
3272 static TMatrixD vecYk(30,1); // Innovation or measurement residual
3273 static TMatrixD matHkT(30,30); // helper matrix Hk transpose
3274 static TMatrixD matSk(30,30); // Innovation (or residual) covariance
3275 static TMatrixD matKk(30,30); // Optimal Kalman gain
3276 static TMatrixD mat1(30,30); // update covariance matrix
3277 static TMatrixD covXk2(30,30); // helper matrix
3279 TMatrixD vecXk(par0); // X vector
3280 TMatrixD covXk(cov0); // X covariance
3285 for (Int_t i=0;i<30;i++)
3286 for (Int_t j=0;j<30;j++){
3288 if (i==j) mat1(i,j)=1;
3290 matHk = mat1; // unit matrix
3292 vecZk = par1; // measurement
3293 measR = cov1; // error of measurement
3294 vecYk = vecZk-matHk*vecXk; // Innovation or measurement residual
3296 matHkT=matHk.T(); matHk.T();
3297 matSk = (matHk*(covXk*matHkT))+measR; // Innovation (or residual) covariance
3299 matKk = (covXk*matHkT)*matSk; // Optimal Kalman gain
3301 vecXk += matKk*vecYk; // updated vector
3302 covXk2= (mat1-(matKk*matHk));
3303 covXk = covXk2*covXk;
3304 CheckCovariance(covXk);
3305 CheckCovariance(cov1);
3307 par0 = vecXk; // update measurement param
3308 cov0 = covXk; // update measurement covar
3311 Double_t AliTPCcalibAlign::GetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t /*lz*/){
3313 // Get position correction for given sector
3316 TMatrixD * param = (TMatrixD*)fArraySectorIntParam.At(sector%36);
3317 if (!param) return 0;
3320 if (lx<fXquadrant) {
3321 if (ly<0) quadrant=1;
3322 if (ly>0) quadrant=2;
3324 if (lx>fXquadrant) {
3325 if (ly<0) quadrant=3;
3326 if (ly>0) quadrant=4;
3329 Double_t a10 = (*param)(quadrant*6+0,0);
3330 Double_t a20 = (*param)(quadrant*6+1,0);
3331 Double_t a21 = (*param)(quadrant*6+2,0);
3332 Double_t dx = (*param)(quadrant*6+3,0);
3333 Double_t dy = (*param)(quadrant*6+4,0);
3334 Double_t dz = (*param)(quadrant*6+5,0);
3335 Double_t deltaX = lx-fXIO;
3336 if (coord==0) return dx;
3337 if (coord==1) return dy+deltaX*a10;
3338 if (coord==2) return dz+deltaX*a20+ly*a21;
3342 Double_t AliTPCcalibAlign::SGetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t lz){
3346 if (!Instance()) return 0;
3347 return Instance()->GetCorrectionSector(coord,sector,lx,ly,lz);
3350 void AliTPCcalibAlign::MakeKalman(){
3352 // Make a initial Kalman paramaters for sector Alignemnt
3354 fSectorParamA = new TMatrixD(6*36+6,1);
3355 fSectorParamC = new TMatrixD(6*36+6,1);
3356 fSectorCovarA = new TMatrixD(6*36+6,6*36+6);
3357 fSectorCovarC = new TMatrixD(6*36+6,6*36+6);
3359 // set starting parameters at 0
3361 for (Int_t isec=0;isec<37;isec++)
3362 for (Int_t ipar=0;ipar<6;ipar++){
3363 (*fSectorParamA)(isec*6+ipar,0) =0;
3364 (*fSectorParamC)(isec*6+ipar,0) =0;
3367 // set starting covariance
3369 for (Int_t isec=0;isec<36;isec++)
3370 for (Int_t ipar=0;ipar<6;ipar++){
3372 (*fSectorCovarA)(isec*6+ipar,isec*6+ipar) =0.002*0.002; // 2 mrad
3373 (*fSectorCovarC)(isec*6+ipar,isec*6+ipar) =0.002*0.002;
3376 (*fSectorCovarA)(isec*6+ipar,isec*6+ipar) =0.02*0.02; // 0.2 mm
3377 (*fSectorCovarC)(isec*6+ipar,isec*6+ipar) =0.02*0.02;
3380 (*fSectorCovarA)(36*6+0,36*6+0) =0.04; // common shift y up-up
3381 (*fSectorCovarA)(36*6+1,36*6+1) =0.04; // common shift y down-down
3382 (*fSectorCovarA)(36*6+2,36*6+2) =0.04; // common shift y up-down
3383 (*fSectorCovarA)(36*6+3,36*6+3) =0.004; // common shift phi up-up
3384 (*fSectorCovarA)(36*6+4,36*6+4) =0.004; // common shift phi down-down
3385 (*fSectorCovarA)(36*6+5,36*6+5) =0.004; // common shift phi up-down
3387 (*fSectorCovarC)(36*6+0,36*6+0) =0.04; // common shift y up-up
3388 (*fSectorCovarC)(36*6+1,36*6+1) =0.04; // common shift y down-down
3389 (*fSectorCovarC)(36*6+2,36*6+2) =0.04; // common shift y up-down
3390 (*fSectorCovarC)(36*6+3,36*6+3) =0.004; // common shift phi up-up
3391 (*fSectorCovarC)(36*6+4,36*6+4) =0.004; // common shift phi down-down
3392 (*fSectorCovarC)(36*6+5,36*6+5) =0.004; // common shift phi up-down
3395 void AliTPCcalibAlign::UpdateKalman(Int_t sector0, Int_t sector1, TMatrixD &p0, TMatrixD &c0, TMatrixD &p1, TMatrixD &c1){
3397 // Update Kalman parameters
3398 // Note numbering from 0..36 0..17 IROC 18..35 OROC
3401 if (fSectorParamA==NULL) MakeKalman();
3402 if (CheckCovariance(c0)>0) return;
3403 if (CheckCovariance(c1)>0) return;
3404 const Int_t nelem = 6*36+6;
3407 static TMatrixD matHk(4,nelem); // vector to mesurement
3408 static TMatrixD measR(4,4); // measurement error
3409 static TMatrixD vecZk(4,1); // measurement
3411 static TMatrixD vecYk(4,1); // Innovation or measurement residual
3412 static TMatrixD matHkT(nelem,4); // helper matrix Hk transpose
3413 static TMatrixD matSk(4,4); // Innovation (or residual) covariance
3414 static TMatrixD matKk(nelem,4); // Optimal Kalman gain
3415 static TMatrixD mat1(nelem,nelem); // update covariance matrix
3416 static TMatrixD covXk2(nelem,nelem); // helper matrix
3418 TMatrixD *vOrig = 0;
3419 TMatrixD *cOrig = 0;
3420 vOrig = (sector0%36>=18) ? fSectorParamA:fSectorParamC;
3421 cOrig = (sector0%36>=18) ? fSectorCovarA:fSectorCovarC;
3423 Int_t sec0= sector0%18;
3424 Int_t sec1= sector1%18;
3425 if (sector0>35) sec0+=18;
3426 if (sector1>35) sec1+=18;
3428 TMatrixD vecXk(*vOrig); // X vector
3429 TMatrixD covXk(*cOrig); // X covariance
3433 for (Int_t i=0;i<nelem;i++)
3434 for (Int_t j=0;j<nelem;j++){
3436 if (i==j) mat1(i,j)=1;
3440 // matHk - vector to measurement
3442 for (Int_t i=0;i<4;i++)
3443 for (Int_t j=0;j<nelem;j++){
3453 matHk(0,6*sec1+4) = 1.; // delta y
3454 matHk(1,6*sec1+0) = 1.; // delta ky
3455 matHk(2,6*sec1+5) = 1.; // delta z
3456 matHk(3,6*sec1+1) = 1.; // delta kz
3457 matHk(0,6*sec1+3) = p0(1,0); // delta x to delta y - through ky
3458 matHk(2,6*sec1+3) = p0(3,0); // delta x to delta z - thorugh kz
3459 matHk(2,6*sec1+2) = p0(0,0); // y to delta z - through psiz
3461 matHk(0,6*sec0+4) = -1.; // delta y
3462 matHk(1,6*sec0+0) = -1.; // delta ky
3463 matHk(2,6*sec0+5) = -1.; // delta z
3464 matHk(3,6*sec0+1) = -1.; // delta kz
3465 matHk(0,6*sec0+3) =&nbs