1 /// \class AliTPCPointCorrection
3 /**************************************************************************
4 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
6 * Author: The ALICE Off-line Project. *
7 * Contributors are mentioned in the code where appropriate. *
9 * Permission to use, copy, modify and distribute this software and its *
10 * documentation strictly for non-commercial purposes is hereby granted *
11 * without fee, provided that the above copyright notice appears in all *
12 * copies and that both the copyright notice and this permission notice *
13 * appear in the supporting documentation. The authors make no claims *
14 * about the suitability of this software for any purpose. It is *
15 * provided "as is" without express or implied warranty. *
16 **************************************************************************/
20 Unlinearities fitting:
22 Model for Outer field cage:
23 Unlinearities at the edge aproximated using two exponential decays.
25 dz = dz0(r,z) +dr(r,z)*tan(theta)
26 dy = +dr(r,z)*tan(phi)
33 #include "AliTPCcalibDB.h"
34 #include "TLinearFitter.h"
35 #include "Riostream.h"
43 #include "AliTPCROC.h"
44 #include "AliTPCClusterParam.h"
45 #include "AliTPCPointCorrection.h"
47 AliTPCPointCorrection* AliTPCPointCorrection::fgInstance = 0;
50 ClassImp(AliTPCPointCorrection)
53 AliTPCPointCorrection::AliTPCPointCorrection():
65 fArraySectorIntParam(36), // array of sector alignment parameters
66 fArraySectorIntCovar(36), // array of sector alignment covariances
68 // Kalman filter for global alignment
70 fSectorParam(0), // Kalman parameter
71 fSectorCovar(0) // Kalman covariance
75 // Default constructor
77 AliTPCROC * roc = AliTPCROC::Instance();
78 fXquadrant = roc->GetPadRowRadii(36,53);
79 fXmiddle = ( roc->GetPadRowRadii(0,0)+roc->GetPadRowRadii(36,roc->GetNRows(36)-1))*0.5;
80 fXIO = ( roc->GetPadRowRadii(0,roc->GetNRows(0)-1)+roc->GetPadRowRadii(36,0))*0.5;
83 AliTPCPointCorrection::AliTPCPointCorrection(const Text_t *name, const Text_t *title):
97 fArraySectorIntParam(36), // array of sector alignment parameters
98 fArraySectorIntCovar(36), // array of sector alignment covariances
100 // Kalman filter for global alignment
102 fSectorParam(0), // Kalman parameter for A side
103 fSectorCovar(0) // Kalman covariance for A side
106 /// Non default constructor
108 AliTPCROC * roc = AliTPCROC::Instance();
109 fXquadrant = roc->GetPadRowRadii(36,53);
110 fXmiddle = ( roc->GetPadRowRadii(0,0)+roc->GetPadRowRadii(36,roc->GetNRows(36)-1))*0.5;
111 fXIO = ( roc->GetPadRowRadii(0,roc->GetNRows(0)-1)+roc->GetPadRowRadii(36,0))*0.5;
115 AliTPCPointCorrection::~AliTPCPointCorrection(){
121 AliTPCPointCorrection* AliTPCPointCorrection::Instance()
123 /// Singleton implementation
124 /// Returns an instance of this class, it is created if neccessary
126 if (fgInstance == 0){
127 fgInstance = new AliTPCPointCorrection();
134 Double_t AliTPCPointCorrection::GetDrOut(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
135 /// return radial correction
137 if (fParamOutRVersion==0) return CorrectionOutR0(isGlobal, type,cx,cy,cz,sector);
141 Double_t AliTPCPointCorrection::SGetDrOut(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
142 /// return radial correction - static function
144 return fgInstance->GetDrOut(isGlobal, type,cx,cy,cz,sector);
150 Double_t AliTPCPointCorrection::GetDzOut(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
153 if (fParamOutZVersion==0) return CorrectionOutZ0(isGlobal, type,cx,cy,cz,sector);
158 Double_t AliTPCPointCorrection::SGetDzOut(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
161 return fgInstance->GetDzOut(isGlobal, type,cx,cy,cz,sector);
167 Double_t AliTPCPointCorrection::CorrectionOutR0(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
168 /// return dR correction - for correction version 0
170 /// isGlobal - is the x in global frame
171 /// type - kTRUE - use sectors - kFALSE - only Side param
172 /// cx, cy,cz - cluster position
173 /// sector - sector number
176 // recalculate sector if in global frame
177 Double_t alpha = TMath::ATan2(cy,cx);
178 if (alpha<0) alpha+=TMath::Pi()*2;
179 sector = Int_t(18*alpha/(TMath::Pi()*2));
182 if (type==kFALSE) sector=36+(sector%36>=18); // side level parameters
184 Double_t radius = TMath::Sqrt(cx*cx+cy*cy);
185 AliTPCROC * roc = AliTPCROC::Instance();
186 Double_t xout = roc->GetPadRowRadiiUp(roc->GetNRows(37)-1);
187 Double_t dout = xout-radius;
188 if (dout<0) return 0;
190 Double_t dr = 0.5 - TMath::Abs(cz/250.);
193 TVectorD * vec = GetParamOutR(sector);
195 Double_t eout10 = TMath::Exp(-dout/10.);
196 Double_t eout5 = TMath::Exp(-dout/5.);
197 Double_t eoutp = (eout10+eout5)*0.5;
198 Double_t eoutm = (eout10-eout5)*0.5;
201 result+=(*vec)[1]*eoutp;
202 result+=(*vec)[2]*eoutm;
203 result+=(*vec)[3]*eoutp*dr;
204 result+=(*vec)[4]*eoutm*dr;
205 result+=(*vec)[5]*eoutp*dr*dr;
206 result+=(*vec)[6]*eoutm*dr*dr;
210 Double_t AliTPCPointCorrection::RPhiCOGCorrection(Int_t sector, Int_t padrow, Float_t pad, Float_t cy, Float_t y, Float_t z, Float_t ky,Float_t qMax, Float_t threshold){
211 /// Calculates COG corection in RPHI direction
212 /// cluster and track position y is supposed to be corrected before for other effects
213 /// (e.g ExB and alignemnt)
214 /// Rphi distortion dependeds on the distance to the edge-pad, distance to the wire edge and
215 /// relative distance to the center of the pad. Therefore the y position is trnsfromed to the
216 /// pad coordiante frame (correction offset (ExB alignemnt) substracted).
218 /// Input parameters:
220 /// sector - sector number - 0-71 - cl.GetDetector()
221 /// padrow - padrow number -0-63 -IROC 0-95 OROC - cl->GetRow()
222 /// pad - mean pad number - cl->GetPad()
223 /// cy - cluster y - cl->GetY()
224 /// y - track -or cluster y
225 /// qMax - cluster max charge - cl-.GetMax()
226 /// threshold - clusterer threshold
228 AliTPCClusterParam * clparam = AliTPCcalibDB::Instance()->GetClusterParam();
230 AliFatal("TPC OCDB not initialized");
234 if (sector>=36) padtype = (padrow>64)?2:1;
235 Double_t padwidth=(padtype==0)? 0.4:0.6;
237 Double_t sigma = clparam->GetRMS0(0,padtype,250-TMath::Abs(z),ky)/padwidth;
239 Int_t npads = AliTPCROC::Instance()->GetNPads(sector,padrow);
240 Float_t yshift = TMath::Abs(cy)-TMath::Abs((-npads*0.5+pad)*padwidth); // the clusters can be corrected before
241 // shift to undo correction
243 y -= yshift*((y>0)?1.:-1.); // y in the sector coordinate
244 Double_t y0 = npads*0.5*padwidth;
245 Double_t dy = (TMath::Abs(y0)-TMath::Abs(y))/padwidth-0.5; // distance to the center of pad0
247 Double_t padcenter = TMath::Nint(dy);
250 for (Double_t ip=padcenter-2.5; ip<=padcenter+2.5;ip++){
251 Double_t weightGaus = qMax*TMath::Exp(-(dy-ip)*(dy-ip)/(2*sigma*sigma));
252 Double_t ypad = (ip-npads*0.5)*padwidth;
253 Double_t weightGain = GetEdgeQ0(sector,padrow,ypad);
255 Double_t weight = TMath::Nint(weightGaus*weightGain);
256 if (ip<0 &&weight> threshold) weight = threshold; // this is done in cl finder
257 if (weight<0) continue;
262 if (sumw>0) result = sumwi/sumw;
263 result = (result-dy)*padwidth;
270 Double_t AliTPCPointCorrection::CorrectionOutZ0(Bool_t isGlobal, Bool_t type, Double_t cx, Double_t cy, Double_t cz, Int_t sector){
271 /// return dR correction - for correction version 0
273 /// isGlobal - is the x in global frame
274 /// type - kTRUE - use sectors - kFALSE - only Side param
275 /// cx, cy,cz - cluster position
276 /// sector - sector number
279 // recalculate sector if in global frame
280 Double_t alpha = TMath::ATan2(cy,cx);
281 if (alpha<0) alpha+=TMath::Pi()*2;
282 sector = Int_t(18*alpha/(TMath::Pi()*2));
285 if (type==kFALSE) sector=36+(sector%36>=18); // side level parameters
287 Double_t radius = TMath::Sqrt(cx*cx+cy*cy);
288 AliTPCROC * roc = AliTPCROC::Instance();
289 Double_t xout = roc->GetPadRowRadiiUp(roc->GetNRows(37)-1);
290 Double_t dout = xout-radius;
291 if (dout<0) return 0;
293 Double_t dr = 0.5 - TMath::Abs(cz/250.);
296 TVectorD * vec = GetParamOutR(sector);
298 Double_t eout10 = TMath::Exp(-dout/10.);
299 Double_t eout5 = TMath::Exp(-dout/5.);
300 Double_t eoutp = (eout10+eout5)*0.5;
301 Double_t eoutm = (eout10-eout5)*0.5;
304 result+=(*vec)[1]*eoutp;
305 result+=(*vec)[2]*eoutm;
306 result+=(*vec)[3]*eoutp*dr;
307 result+=(*vec)[4]*eoutm*dr;
308 result+=(*vec)[5]*eoutp*dr*dr;
309 result+=(*vec)[6]*eoutm*dr*dr;
314 Double_t AliTPCPointCorrection::GetEdgeQ0(Int_t sector, Int_t padrow, Float_t y){
317 /* TF1 fexp("fexp","1-exp(-[0]*(x-[1]))",0,20)
318 | param [0] | param [1]
319 IROC | 4.71413 | 1.39558
320 OROC1| 2.11437 | 1.52643
321 OROC2| 2.15082 | 1.53537
324 Double_t params[2]={100,0};
326 params[0]=4.71413; params[1]=1.39558;
329 if (padrow<64) { params[0]=2.114; params[1]=1.526;}
330 if (padrow>=64){ params[0]=2.15; params[1]=1.535;}
333 Double_t xrow = AliTPCROC::Instance()->GetPadRowRadii(sector,padrow);
334 Double_t ymax = TMath::Tan(TMath::Pi()/18.)*xrow;
335 Double_t dedge = ymax-TMath::Abs(y);
336 if (dedge-params[1]<0) return 0;
337 if (dedge>10.*params[1]) return 1;
338 result = 1.-TMath::Exp(-params[0]*(dedge-params[1]));
342 Double_t AliTPCPointCorrection::SRPhiCOGCorrection(Int_t sector, Int_t padrow, Float_t pad, Float_t cy, Float_t y, Float_t z, Float_t ky,Float_t qMax, Float_t threshold){
343 return fgInstance->RPhiCOGCorrection(sector, padrow, pad, cy, y,z, ky, qMax, threshold);
346 Double_t AliTPCPointCorrection::SGetEdgeQ0(Int_t sector, Int_t padrow, Float_t y){
349 return fgInstance->GetEdgeQ0(sector, padrow, y);
352 void AliTPCPointCorrection::AddCorrectionSector(TObjArray & sideAPar, TObjArray &sideCPar, TObjArray & sideACov, TObjArray &sideCCov, Bool_t reset){
355 for (Int_t isec=0;isec<36;isec++){
356 TMatrixD * mat1 = (TMatrixD*)(sideAPar.At(isec));
357 TMatrixD * mat1Covar = (TMatrixD*)(sideACov.At(isec));
359 TMatrixD * mat0 = (TMatrixD*)(fArraySectorIntParam.At(isec));
360 TMatrixD * mat0Covar = (TMatrixD*)(fArraySectorIntCovar.At(isec));
362 fArraySectorIntParam.AddAt(mat1->Clone(),isec);
363 fArraySectorIntCovar.AddAt(mat1Covar->Clone(),isec);
366 (*mat0Covar)=(*mat1Covar);
367 if (reset) (*mat0)=(*mat1);
368 if (!reset) (*mat0)+=(*mat1);
371 for (Int_t isec=0;isec<36;isec++){
372 TMatrixD * mat1 = (TMatrixD*)(sideCPar.At(isec));
373 TMatrixD * mat1Covar = (TMatrixD*)(sideCCov.At(isec));
375 TMatrixD * mat0 = (TMatrixD*)(fArraySectorIntParam.At(isec));
376 TMatrixD * mat0Covar = (TMatrixD*)(fArraySectorIntCovar.At(isec));
378 fArraySectorIntParam.AddAt(mat1->Clone(),isec);
379 fArraySectorIntCovar.AddAt(mat1Covar->Clone(),isec);
382 (*mat0Covar)=(*mat1Covar);
383 if (reset) (*mat0)=(*mat1);
384 if (!reset) (*mat0)+=(*mat1);
389 Double_t AliTPCPointCorrection::GetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t /*lz*/, Int_t quadrant){
390 /// Get position correction for given sector
392 TMatrixD * param = (TMatrixD*)fArraySectorIntParam.At(sector%36);
393 if (!param) return 0;
394 if (quadrant<0){ //recalc quadrant if not specified
395 if (lx<fXIO) quadrant=0;
398 if (ly<0) quadrant=1;
399 if (ly>0) quadrant=2;
401 if (lx>=fXquadrant) {
402 if (ly<0) quadrant=3;
403 if (ly>0) quadrant=4;
407 Double_t a10 = (*param)(quadrant*6+0,0);
408 Double_t a20 = (*param)(quadrant*6+1,0);
409 Double_t a21 = (*param)(quadrant*6+2,0);
410 Double_t dx = (*param)(quadrant*6+3,0);
411 Double_t dy = (*param)(quadrant*6+4,0);
412 Double_t dz = (*param)(quadrant*6+5,0);
413 Double_t deltaX = lx-fXmiddle;
414 if (coord==0) return dx;
415 if (coord==1) return dy+deltaX*a10;
416 if (coord==2) return dz+deltaX*a20+ly*a21;
417 if (coord==3) return a10;
418 if (coord==4) return a20;
419 if (coord==5) return a21;
424 Double_t AliTPCPointCorrection::SGetCorrectionSector(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t lz, Int_t quadrant){
427 if (!Instance()) return 0;
428 return Instance()->GetCorrectionSector(coord,sector,lx,ly,lz, quadrant);
433 Double_t AliTPCPointCorrection::GetCorrection(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t /*lz*/){
434 /// Get position correction for given sector
436 if (!fSectorParam) return 0;
438 Double_t a10 = (*fSectorParam)(sector*6+0,0);
439 Double_t a20 = (*fSectorParam)(sector*6+1,0);
440 Double_t a21 = (*fSectorParam)(sector*6+2,0);
441 Double_t dx = (*fSectorParam)(sector*6+3,0);
442 Double_t dy = (*fSectorParam)(sector*6+4,0);
443 Double_t dz = (*fSectorParam)(sector*6+5,0);
444 Double_t deltaX = lx-fXIO;
446 if (coord==0) return dx;
447 if (coord==1) return dy+deltaX*a10;
448 if (coord==2) return dz+deltaX*a20+ly*a21;
449 if (coord==3) return a10;
450 if (coord==4) return a20;
451 if (coord==5) return a21;
455 Double_t AliTPCPointCorrection::SGetCorrection(Int_t coord, Int_t sector, Double_t lx, Double_t ly, Double_t lz){
458 if (!Instance()) return 0;
459 return Instance()->GetCorrection(coord,sector,lx,ly,lz);