]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/TPCbase/AliTPCTransform.cxx
doxy: TPC/TPCbase converted
[u/mrichter/AliRoot.git] / TPC / TPCbase / AliTPCTransform.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /// \class AliTPCTransform
17 /// \brief Implementation of the TPC transformation class
18 ///
19 /// Class for tranformation of the coordinate frame
20 /// Transformation
21 /// local coordinate frame (sector, padrow, pad, timebine) ==>
22 /// rotated global (tracking) cooridnate frame (sector, lx,ly,lz)
23 ///
24 /// Unisochronity  - (substract time0 - pad by pad)
25 /// Drift velocity - Currently common drift velocity - functionality of AliTPCParam
26 /// ExB effect     -
27 ///
28 /// Time of flight correction -
29 /// - Depends on the vertex position
30 /// - by default
31 ///
32 /// Usage:
33 ///
34 /// ~~~{.cxx}
35 /// AliTPCclusterer::AddCluster
36 /// AliTPCtracker::Transform
37 /// ~~~
38 ///
39 /// To test it:
40 ///
41 /// ~~~{.cxx}
42 /// cdb=AliCDBManager::Instance()
43 /// cdb->SetDefaultStorage("local:///u/mmager/mycalib1")
44 /// c=AliTPCcalibDB::Instance()
45 /// c->SetRun(0)
46 /// Double_t x[]={1.0,2.0,3.0}
47 /// Int_t i[]={4}
48 /// AliTPCTransform trafo
49 /// trafo.Transform(x,i,0,1)
50 /// ~~~
51 ///
52 /// \author Magnus Mager, Marian Ivanov
53
54 #include "AliTPCROC.h"
55 #include "AliTPCCalPad.h"
56 #include "AliTPCCalROC.h"
57 #include "AliTPCcalibDB.h"
58 #include "AliTPCParam.h"
59 #include "TMath.h"
60 #include "AliLog.h"
61 #include "AliTPCExB.h"
62 #include "AliTPCCorrection.h"
63 #include "TGeoMatrix.h"
64 #include "AliTPCRecoParam.h"
65 #include "AliTPCCalibVdrift.h"
66 #include "AliTPCTransform.h"
67 #include "AliMagF.h"
68 #include "TGeoGlobalMagField.h"
69 #include "AliTracker.h"
70 #include <AliCTPTimeParams.h>
71
72 /// \cond CLASSIMP
73 ClassImp(AliTPCTransform)
74 /// \endcond
75
76
77 AliTPCTransform::AliTPCTransform():
78   AliTransform(),
79   fCurrentRecoParam(0),       //! current reconstruction parameters
80   fCurrentRun(0),             //! current run
81   fCurrentTimeStamp(0)        //! current time stamp
82 {
83   //
84   // Speed it up a bit!
85   //
86   for (Int_t i=0;i<18;++i) {
87     Double_t alpha=TMath::DegToRad()*(10.+20.*(i%18));
88     fSins[i]=TMath::Sin(alpha);
89     fCoss[i]=TMath::Cos(alpha);
90   }
91   fPrimVtx[0]=0;
92   fPrimVtx[1]=0;
93   fPrimVtx[2]=0;
94 }
95 AliTPCTransform::AliTPCTransform(const AliTPCTransform& transform):
96   AliTransform(transform),
97   fCurrentRecoParam(transform.fCurrentRecoParam),       //! current reconstruction parameters
98   fCurrentRun(transform.fCurrentRun),             //! current run
99   fCurrentTimeStamp(transform.fCurrentTimeStamp)        //! current time stamp
100 {
101   /// Speed it up a bit!
102
103   for (Int_t i=0;i<18;++i) {
104     Double_t alpha=TMath::DegToRad()*(10.+20.*(i%18));
105     fSins[i]=TMath::Sin(alpha);
106     fCoss[i]=TMath::Cos(alpha);
107   }
108   fPrimVtx[0]=0;
109   fPrimVtx[1]=0;
110   fPrimVtx[2]=0;
111 }
112
113 AliTPCTransform::~AliTPCTransform() {
114   /// Destructor
115
116 }
117
118 void AliTPCTransform::SetPrimVertex(Double_t *vtx){
119   ///
120
121   fPrimVtx[0]=vtx[0];
122   fPrimVtx[1]=vtx[1];
123   fPrimVtx[2]=vtx[2];
124 }
125
126
127 void AliTPCTransform::Transform(Double_t *x,Int_t *i,UInt_t /*time*/,
128                                 Int_t /*coordinateType*/) {
129   /// input: x[0] - pad row
130   ///        x[1] - pad
131   ///        x[2] - time in us
132   ///        i[0] - sector
133   /// output: x[0] - x (all in the rotated global coordinate frame)
134   /// x[1] - y
135   /// x[2] - z
136   ///
137   ///  primvtx     - position of the primary vertex
138   /// used for the TOF correction
139   /// TOF of particle calculated assuming the speed-of-light and
140   /// line approximation
141
142   if (!fCurrentRecoParam) {
143     return;
144   }
145   Int_t row=TMath::Nint(x[0]);
146   Int_t pad=TMath::Nint(x[1]);
147   Int_t sector=i[0];
148   AliTPCcalibDB*  calib=AliTPCcalibDB::Instance();
149   //
150   AliTPCCalPad * time0TPC = calib->GetPadTime0();
151   AliTPCCalPad * distortionMapY = calib->GetDistortionMap(0);
152   AliTPCCalPad * distortionMapZ = calib->GetDistortionMap(1);
153   AliTPCCalPad * distortionMapR = calib->GetDistortionMap(2);
154   AliTPCParam  * param    = calib->GetParameters();
155   AliTPCCorrection * correction = calib->GetTPCComposedCorrection();   // first user defined correction  // if does not exist  try to get it from calibDB array
156   if (!correction) correction = calib->GetTPCComposedCorrection(AliTracker::GetBz());
157   if (!time0TPC){
158     AliFatal("Time unisochronity missing");
159     return ; // make coverity happy
160   }
161   AliTPCCorrection * correctionDelta = calib->GetTPCComposedCorrectionDelta();
162
163   if (!param){
164     AliFatal("Parameters missing");
165     return; // make coverity happy
166   }
167
168   Double_t xx[3];
169   //  Apply Time0 correction - Pad by pad fluctuation
170   //
171   if (!calib->HasAlignmentOCDB()) x[2]-=time0TPC->GetCalROC(sector)->GetValue(row,pad);
172   //
173   // Tranform from pad - time coordinate system to the rotated global (tracking) system
174   //
175   Local2RotatedGlobal(sector,x);
176   //
177   //
178   //
179   // Alignment
180   //TODO:  calib->GetParameters()->GetClusterMatrix(sector)->LocalToMaster(x,xx);
181   RotatedGlobal2Global(sector,x);
182
183   //
184   // old ExB correction
185   //
186   if(fCurrentRecoParam->GetUseExBCorrection()) {
187
188     calib->GetExB()->Correct(x,xx);
189
190   } else {
191
192     xx[0] = x[0];
193     xx[1] = x[1];
194     xx[2] = x[2];
195   }
196
197   //
198   // new composed  correction  - will replace soon ExB correction
199   //
200   if(fCurrentRecoParam->GetUseComposedCorrection()&&correction) {
201     Float_t distPoint[3]={static_cast<Float_t>(xx[0]),static_cast<Float_t>(xx[1]),static_cast<Float_t>(xx[2])};
202     correction->CorrectPoint(distPoint, sector);
203     xx[0]=distPoint[0];
204     xx[1]=distPoint[1];
205     xx[2]=distPoint[2];
206     if (correctionDelta&&fCurrentRecoParam->GetUseAlignmentTime()){  // appply time dependent correction if available and enabled
207       Float_t distPointDelta[3]={static_cast<Float_t>(xx[0]),static_cast<Float_t>(xx[1]),static_cast<Float_t>(xx[2])};
208       correctionDelta->CorrectPoint(distPointDelta, sector);
209       xx[0]=distPointDelta[0];
210       xx[1]=distPointDelta[1];
211       xx[2]=distPointDelta[2];
212     }
213   }
214
215
216   //
217   // Time of flight correction
218   //
219   if (fCurrentRecoParam->GetUseTOFCorrection()){
220     const Int_t kNIS=param->GetNInnerSector(), kNOS=param->GetNOuterSector();
221     Float_t sign=1;
222     if (sector < kNIS) {
223       sign = (sector < kNIS/2) ? 1 : -1;
224     } else {
225       sign = ((sector-kNIS) < kNOS/2) ? 1 : -1;
226     }
227     Float_t deltaDr =0;
228     Float_t dist=0;
229     dist+=(fPrimVtx[0]-x[0])*(fPrimVtx[0]-x[0]);
230     dist+=(fPrimVtx[1]-x[1])*(fPrimVtx[1]-x[1]);
231     dist+=(fPrimVtx[2]-x[2])*(fPrimVtx[2]-x[2]);
232     dist = TMath::Sqrt(dist);
233     // drift length correction because of TOF
234     // the drift velocity is in cm/s therefore multiplication by 0.01
235     deltaDr = (dist*(0.01*param->GetDriftV()))/TMath::C();
236     xx[2]+=sign*deltaDr;
237   }
238   //
239   //
240   //
241
242   //
243   Global2RotatedGlobal(sector,xx);
244
245   //
246   // Apply non linear distortion correction
247   //
248   if (distortionMapY ){
249     // wt - to get it form the OCDB
250     // ignore T1 and T2
251     AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
252     Double_t bzField = magF->SolenoidField()/10.; //field in T
253     Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us]   // From dataBase: to be updated: per second (ideally)
254     Double_t ezField = 400; // [V/cm]   // to be updated: never (hopefully)
255     if (sector%36<18) ezField*=-1;
256     Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ;
257     Double_t c0=1./(1.+wt*wt);
258     Double_t c1=wt/c0;
259
260     //can be switch on for each dimension separatelly
261     if (fCurrentRecoParam->GetUseFieldCorrection()&0x2)
262       if (distortionMapY){
263         xx[1]-= c0*distortionMapY->GetCalROC(sector)->GetValue(row,pad);
264         xx[0]-= c1*distortionMapY->GetCalROC(sector)->GetValue(row,pad);
265       }
266     if (fCurrentRecoParam->GetUseFieldCorrection()&0x4)
267       if (distortionMapZ)
268         xx[2]-=distortionMapZ->GetCalROC(sector)->GetValue(row,pad);
269     if (fCurrentRecoParam->GetUseFieldCorrection()&0x8)
270       if (distortionMapR){
271         xx[0]-= c0*distortionMapR->GetCalROC(sector)->GetValue(row,pad);
272         xx[1]-=-c1*distortionMapR->GetCalROC(sector)->GetValue(row,pad)*wt;
273       }
274
275   }
276   //
277
278   //
279   x[0]=xx[0];x[1]=xx[1];x[2]=xx[2];
280 }
281
282 void AliTPCTransform::Local2RotatedGlobal(Int_t sector, Double_t *x) const {
283   /// Tranform coordinate from
284   /// row, pad, time to x,y,z
285   ///
286   /// Drift Velocity
287   /// Current implementation - common drift velocity - for full chamber
288   /// TODO: use a map or parametrisation!
289
290   if (!fCurrentRecoParam) return;
291   const  Int_t kMax =60;  // cache for 60 seconds
292   static Int_t lastStamp=-1;  //cached values
293   static Double_t lastCorr = 1;
294   //
295   AliTPCcalibDB*  calib=AliTPCcalibDB::Instance();
296   AliTPCParam  * param    = calib->GetParameters();
297   AliTPCCalibVdrift *driftCalib = AliTPCcalibDB::Instance()->GetVdrift(fCurrentRun);
298   Double_t driftCorr = 1.;
299   if (driftCalib){
300     //
301     // caching drift correction - temp. fix
302     // Extremally slow procedure
303     if ( TMath::Abs((lastStamp)-Int_t(fCurrentTimeStamp))<kMax){
304       driftCorr = lastCorr;
305     }else{
306       driftCorr = 1.+(driftCalib->GetPTRelative(fCurrentTimeStamp,0)+ driftCalib->GetPTRelative(fCurrentTimeStamp,1))*0.5;
307       lastCorr=driftCorr;
308       lastStamp=fCurrentTimeStamp;
309
310     }
311   }
312   //
313   // simple caching non thread save
314   static Double_t vdcorrectionTime=1;
315   static Double_t vdcorrectionTimeGY=0;
316   static Double_t time0corrTime=0;
317   static Double_t deltaZcorrTime=0;
318   static Int_t    lastStampT=-1;
319   //
320   if (lastStampT!=(Int_t)fCurrentTimeStamp){
321     lastStampT=fCurrentTimeStamp;
322     if(fCurrentRecoParam->GetUseDriftCorrectionTime()>0) {
323       vdcorrectionTime = (1+AliTPCcalibDB::Instance()->
324                           GetVDriftCorrectionTime(fCurrentTimeStamp,
325                                                   fCurrentRun,
326                                                   sector%36>=18,
327                                                   fCurrentRecoParam->GetUseDriftCorrectionTime()));
328       time0corrTime= AliTPCcalibDB::Instance()->
329         GetTime0CorrectionTime(fCurrentTimeStamp,
330                                fCurrentRun,
331                                sector%36>=18,
332                                fCurrentRecoParam->GetUseDriftCorrectionTime());
333       //
334       deltaZcorrTime= AliTPCcalibDB::Instance()->
335         GetVDriftCorrectionDeltaZ(fCurrentTimeStamp,
336                                fCurrentRun,
337                                sector%36>=18,
338                                0);
339
340     }
341     //
342     if(fCurrentRecoParam->GetUseDriftCorrectionGY()>0) {
343
344       Double_t corrGy= AliTPCcalibDB::Instance()->
345                         GetVDriftCorrectionGy(fCurrentTimeStamp,
346                                               AliTPCcalibDB::Instance()->GetRun(),
347                                               sector%36>=18,
348                                               fCurrentRecoParam->GetUseDriftCorrectionGY());
349       vdcorrectionTimeGY = corrGy;
350     }
351   }
352
353
354   if (!param){
355     AliFatal("Parameters missing");
356     return; // make coverity happy
357   }
358   Int_t row=TMath::Nint(x[0]);
359   //  Int_t pad=TMath::Nint(x[1]);
360   //
361   const Int_t kNIS=param->GetNInnerSector(), kNOS=param->GetNOuterSector();
362   Double_t sign = 1.;
363   Double_t zwidth    = param->GetZWidth()*driftCorr;
364   Float_t xyzPad[3];
365   AliTPCROC::Instance()->GetPositionGlobal(sector, TMath::Nint(x[0]) ,TMath::Nint(x[1]), xyzPad);
366   if (AliTPCRecoParam:: GetUseTimeCalibration()) zwidth*=vdcorrectionTime*(1+xyzPad[1]*vdcorrectionTimeGY);
367   Double_t padWidth  = 0;
368   Double_t padLength = 0;
369   Double_t    maxPad    = 0;
370   //
371   if (sector < kNIS) {
372     maxPad = param->GetNPadsLow(row);
373     sign = (sector < kNIS/2) ? 1 : -1;
374     padLength = param->GetPadPitchLength(sector,row);
375     padWidth = param->GetPadPitchWidth(sector);
376   } else {
377     maxPad = param->GetNPadsUp(row);
378     sign = ((sector-kNIS) < kNOS/2) ? 1 : -1;
379     padLength = param->GetPadPitchLength(sector,row);
380     padWidth  = param->GetPadPitchWidth(sector);
381   }
382   //
383   // X coordinate
384   x[0] = param->GetPadRowRadii(sector,row);  // padrow X position - ideal
385   //
386   // Y coordinate
387   //
388   x[1]=(x[1]-0.5*maxPad)*padWidth;
389   // pads are mirrorred on C-side
390   if (sector%36>17){
391     x[1]*=-1;
392   }
393
394   //
395
396   //
397   // Z coordinate
398   //
399   if (AliTPCcalibDB::Instance()->IsTrgL0()){
400     // by defualt we assume L1 trigger is used - make a correction in case of  L0
401     AliCTPTimeParams* ctp = AliTPCcalibDB::Instance()->GetCTPTimeParams();
402     if (ctp){
403       //for TPC standalone runs no ctp info
404       Double_t delay = ctp->GetDelayL1L0()*0.000000025;
405       x[2]-=delay/param->GetTSample();
406     }
407   }
408   x[2]-= param->GetNTBinsL1();
409   x[2]*= zwidth;  // tranform time bin to the distance to the ROC
410   x[2]-= 3.*param->GetZSigma() + time0corrTime;
411   // subtract the time offsets
412   x[2] = sign*( param->GetZLength(sector) - x[2]);
413   x[2]-=deltaZcorrTime;   // subtrack time dependent z shift (calibrated together with the drift velocity and T0)
414 }
415
416 void AliTPCTransform::RotatedGlobal2Global(Int_t sector,Double_t *x) const {
417   /// transform possition rotated global to the global
418
419   Double_t cos,sin;
420   GetCosAndSin(sector,cos,sin);
421   Double_t tmp=x[0];
422   x[0]= cos*tmp-sin*x[1];
423   x[1]=+sin*tmp+cos*x[1];
424 }
425
426 void AliTPCTransform::Global2RotatedGlobal(Int_t sector,Double_t *x) const {
427   /// tranform possition Global2RotatedGlobal
428
429   Double_t cos,sin;
430   GetCosAndSin(sector,cos,sin);
431   Double_t tmp=x[0];
432   x[0]= cos*tmp+sin*x[1];
433   x[1]= -sin*tmp+cos*x[1];
434 }
435
436 void AliTPCTransform::GetCosAndSin(Int_t sector,Double_t &cos,
437                                           Double_t &sin) const {
438   cos=fCoss[sector%18];
439   sin=fSins[sector%18];
440 }
441
442
443 void AliTPCTransform::ApplyTransformations(Double_t */*xyz*/, Int_t /*volID*/){
444   /// Modify global position
445   /// xyz    - global xyz position
446   /// volID  - volID of detector (sector number)
447
448 }