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 **************************************************************************/
16 /// \class AliTPCTransform
17 /// \brief Implementation of the TPC transformation class
19 /// Class for tranformation of the coordinate frame
21 /// local coordinate frame (sector, padrow, pad, timebine) ==>
22 /// rotated global (tracking) cooridnate frame (sector, lx,ly,lz)
24 /// Unisochronity - (substract time0 - pad by pad)
25 /// Drift velocity - Currently common drift velocity - functionality of AliTPCParam
28 /// Time of flight correction -
29 /// - Depends on the vertex position
35 /// AliTPCclusterer::AddCluster
36 /// AliTPCtracker::Transform
42 /// cdb=AliCDBManager::Instance()
43 /// cdb->SetDefaultStorage("local:///u/mmager/mycalib1")
44 /// c=AliTPCcalibDB::Instance()
46 /// Double_t x[]={1.0,2.0,3.0}
48 /// AliTPCTransform trafo
49 /// trafo.Transform(x,i,0,1)
52 /// \author Magnus Mager, Marian Ivanov
54 #include "AliTPCROC.h"
55 #include "AliTPCCalPad.h"
56 #include "AliTPCCalROC.h"
57 #include "AliTPCcalibDB.h"
58 #include "AliTPCParam.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"
68 #include "TGeoGlobalMagField.h"
69 #include "AliTracker.h"
70 #include <AliCTPTimeParams.h>
73 ClassImp(AliTPCTransform)
77 AliTPCTransform::AliTPCTransform():
79 fCurrentRecoParam(0), //! current reconstruction parameters
80 fCurrentRun(0), //! current run
81 fCurrentTimeStamp(0) //! current time stamp
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);
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
101 /// Speed it up a bit!
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);
113 AliTPCTransform::~AliTPCTransform() {
118 void AliTPCTransform::SetPrimVertex(Double_t *vtx){
127 void AliTPCTransform::Transform(Double_t *x,Int_t *i,UInt_t /*time*/,
128 Int_t /*coordinateType*/) {
129 /// input: x[0] - pad row
131 /// x[2] - time in us
133 /// output: x[0] - x (all in the rotated global coordinate frame)
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
142 if (!fCurrentRecoParam) {
145 Int_t row=TMath::Nint(x[0]);
146 Int_t pad=TMath::Nint(x[1]);
148 AliTPCcalibDB* calib=AliTPCcalibDB::Instance();
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());
158 AliFatal("Time unisochronity missing");
159 return ; // make coverity happy
161 AliTPCCorrection * correctionDelta = calib->GetTPCComposedCorrectionDelta();
164 AliFatal("Parameters missing");
165 return; // make coverity happy
169 // Apply Time0 correction - Pad by pad fluctuation
171 if (!calib->HasAlignmentOCDB()) x[2]-=time0TPC->GetCalROC(sector)->GetValue(row,pad);
173 // Tranform from pad - time coordinate system to the rotated global (tracking) system
175 Local2RotatedGlobal(sector,x);
180 //TODO: calib->GetParameters()->GetClusterMatrix(sector)->LocalToMaster(x,xx);
181 RotatedGlobal2Global(sector,x);
184 // old ExB correction
186 if(fCurrentRecoParam->GetUseExBCorrection()) {
188 calib->GetExB()->Correct(x,xx);
198 // new composed correction - will replace soon ExB correction
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);
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];
217 // Time of flight correction
219 if (fCurrentRecoParam->GetUseTOFCorrection()){
220 const Int_t kNIS=param->GetNInnerSector(), kNOS=param->GetNOuterSector();
223 sign = (sector < kNIS/2) ? 1 : -1;
225 sign = ((sector-kNIS) < kNOS/2) ? 1 : -1;
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();
243 Global2RotatedGlobal(sector,xx);
246 // Apply non linear distortion correction
248 if (distortionMapY ){
249 // wt - to get it form the OCDB
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);
260 //can be switch on for each dimension separatelly
261 if (fCurrentRecoParam->GetUseFieldCorrection()&0x2)
263 xx[1]-= c0*distortionMapY->GetCalROC(sector)->GetValue(row,pad);
264 xx[0]-= c1*distortionMapY->GetCalROC(sector)->GetValue(row,pad);
266 if (fCurrentRecoParam->GetUseFieldCorrection()&0x4)
268 xx[2]-=distortionMapZ->GetCalROC(sector)->GetValue(row,pad);
269 if (fCurrentRecoParam->GetUseFieldCorrection()&0x8)
271 xx[0]-= c0*distortionMapR->GetCalROC(sector)->GetValue(row,pad);
272 xx[1]-=-c1*distortionMapR->GetCalROC(sector)->GetValue(row,pad)*wt;
279 x[0]=xx[0];x[1]=xx[1];x[2]=xx[2];
282 void AliTPCTransform::Local2RotatedGlobal(Int_t sector, Double_t *x) const {
283 /// Tranform coordinate from
284 /// row, pad, time to x,y,z
287 /// Current implementation - common drift velocity - for full chamber
288 /// TODO: use a map or parametrisation!
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;
295 AliTPCcalibDB* calib=AliTPCcalibDB::Instance();
296 AliTPCParam * param = calib->GetParameters();
297 AliTPCCalibVdrift *driftCalib = AliTPCcalibDB::Instance()->GetVdrift(fCurrentRun);
298 Double_t driftCorr = 1.;
301 // caching drift correction - temp. fix
302 // Extremally slow procedure
303 if ( TMath::Abs((lastStamp)-Int_t(fCurrentTimeStamp))<kMax){
304 driftCorr = lastCorr;
306 driftCorr = 1.+(driftCalib->GetPTRelative(fCurrentTimeStamp,0)+ driftCalib->GetPTRelative(fCurrentTimeStamp,1))*0.5;
308 lastStamp=fCurrentTimeStamp;
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;
320 if (lastStampT!=(Int_t)fCurrentTimeStamp){
321 lastStampT=fCurrentTimeStamp;
322 if(fCurrentRecoParam->GetUseDriftCorrectionTime()>0) {
323 vdcorrectionTime = (1+AliTPCcalibDB::Instance()->
324 GetVDriftCorrectionTime(fCurrentTimeStamp,
327 fCurrentRecoParam->GetUseDriftCorrectionTime()));
328 time0corrTime= AliTPCcalibDB::Instance()->
329 GetTime0CorrectionTime(fCurrentTimeStamp,
332 fCurrentRecoParam->GetUseDriftCorrectionTime());
334 deltaZcorrTime= AliTPCcalibDB::Instance()->
335 GetVDriftCorrectionDeltaZ(fCurrentTimeStamp,
342 if(fCurrentRecoParam->GetUseDriftCorrectionGY()>0) {
344 Double_t corrGy= AliTPCcalibDB::Instance()->
345 GetVDriftCorrectionGy(fCurrentTimeStamp,
346 AliTPCcalibDB::Instance()->GetRun(),
348 fCurrentRecoParam->GetUseDriftCorrectionGY());
349 vdcorrectionTimeGY = corrGy;
355 AliFatal("Parameters missing");
356 return; // make coverity happy
358 Int_t row=TMath::Nint(x[0]);
359 // Int_t pad=TMath::Nint(x[1]);
361 const Int_t kNIS=param->GetNInnerSector(), kNOS=param->GetNOuterSector();
363 Double_t zwidth = param->GetZWidth()*driftCorr;
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;
372 maxPad = param->GetNPadsLow(row);
373 sign = (sector < kNIS/2) ? 1 : -1;
374 padLength = param->GetPadPitchLength(sector,row);
375 padWidth = param->GetPadPitchWidth(sector);
377 maxPad = param->GetNPadsUp(row);
378 sign = ((sector-kNIS) < kNOS/2) ? 1 : -1;
379 padLength = param->GetPadPitchLength(sector,row);
380 padWidth = param->GetPadPitchWidth(sector);
384 x[0] = param->GetPadRowRadii(sector,row); // padrow X position - ideal
388 x[1]=(x[1]-0.5*maxPad)*padWidth;
389 // pads are mirrorred on C-side
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();
403 //for TPC standalone runs no ctp info
404 Double_t delay = ctp->GetDelayL1L0()*0.000000025;
405 x[2]-=delay/param->GetTSample();
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)
416 void AliTPCTransform::RotatedGlobal2Global(Int_t sector,Double_t *x) const {
417 /// transform possition rotated global to the global
420 GetCosAndSin(sector,cos,sin);
422 x[0]= cos*tmp-sin*x[1];
423 x[1]=+sin*tmp+cos*x[1];
426 void AliTPCTransform::Global2RotatedGlobal(Int_t sector,Double_t *x) const {
427 /// tranform possition Global2RotatedGlobal
430 GetCosAndSin(sector,cos,sin);
432 x[0]= cos*tmp+sin*x[1];
433 x[1]= -sin*tmp+cos*x[1];
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];
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)