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