]>
Commit | Line | Data |
---|---|---|
022ee144 | 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 | |
66954e3f | 23 | // Transformation |
022ee144 | 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 | // | |
003b43ed | 31 | // Time of flight correction - |
32 | // - Depends on the vertex position | |
33 | // - by default | |
34 | // | |
022ee144 | 35 | // Usage: |
36 | // AliTPCclustererMI::AddCluster | |
37 | // AliTPCtrackerMI::Transform | |
38 | // | |
39 | //------------------------------------------------------- | |
c1bdda91 | 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 | ||
022ee144 | 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" | |
cf5b0aa0 | 62 | #include "AliTPCCorrection.h" |
66954e3f | 63 | #include "TGeoMatrix.h" |
9430b11a | 64 | #include "AliTPCRecoParam.h" |
65 | #include "AliTPCCalibVdrift.h" | |
022ee144 | 66 | #include "AliTPCTransform.h" |
0b736a46 | 67 | #include "AliMagF.h" |
68 | #include "TGeoGlobalMagField.h" | |
69 | #include "AliTracker.h" | |
1e6337b1 | 70 | #include <AliCTPTimeParams.h> |
022ee144 | 71 | |
66954e3f | 72 | ClassImp(AliTPCTransform) |
022ee144 | 73 | |
74 | ||
9430b11a | 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 | |
003b43ed | 98 | { |
24db6af7 | 99 | // |
c1bdda91 | 100 | // Speed it up a bit! |
24db6af7 | 101 | // |
c1bdda91 | 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 | } | |
003b43ed | 107 | fPrimVtx[0]=0; |
108 | fPrimVtx[1]=0; | |
109 | fPrimVtx[2]=0; | |
c1bdda91 | 110 | } |
111 | ||
112 | AliTPCTransform::~AliTPCTransform() { | |
24db6af7 | 113 | // |
114 | // Destructor | |
115 | // | |
c1bdda91 | 116 | } |
117 | ||
003b43ed | 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 | ||
24db6af7 | 128 | void AliTPCTransform::Transform(Double_t *x,Int_t *i,UInt_t /*time*/, |
003b43ed | 129 | Int_t /*coordinateType*/) { |
24db6af7 | 130 | // input: x[0] - pad row |
131 | // x[1] - pad | |
c1bdda91 | 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 | |
ecc5dd8f | 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 | // | |
768e46f1 | 143 | if (!fCurrentRecoParam) { |
144 | return; | |
145 | } | |
24db6af7 | 146 | Int_t row=TMath::Nint(x[0]); |
147 | Int_t pad=TMath::Nint(x[1]); | |
c1bdda91 | 148 | Int_t sector=i[0]; |
9430b11a | 149 | AliTPCcalibDB* calib=AliTPCcalibDB::Instance(); |
24db6af7 | 150 | // |
151 | AliTPCCalPad * time0TPC = calib->GetPadTime0(); | |
2293155b | 152 | AliTPCCalPad * distortionMapY = calib->GetDistortionMap(0); |
153 | AliTPCCalPad * distortionMapZ = calib->GetDistortionMap(1); | |
4486a91f | 154 | AliTPCCalPad * distortionMapR = calib->GetDistortionMap(2); |
24db6af7 | 155 | AliTPCParam * param = calib->GetParameters(); |
0b736a46 | 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()); | |
24db6af7 | 158 | if (!time0TPC){ |
159 | AliFatal("Time unisochronity missing"); | |
768e46f1 | 160 | return ; // make coverity happy |
24db6af7 | 161 | } |
3f3549a3 | 162 | AliTPCCorrection * correctionDelta = calib->GetTPCComposedCorrectionDelta(); |
c1bdda91 | 163 | |
24db6af7 | 164 | if (!param){ |
165 | AliFatal("Parameters missing"); | |
768e46f1 | 166 | return; // make coverity happy |
24db6af7 | 167 | } |
c1bdda91 | 168 | |
24db6af7 | 169 | Double_t xx[3]; |
170 | // Apply Time0 correction - Pad by pad fluctuation | |
3f3549a3 | 171 | // |
172 | if (!calib->HasAlignmentOCDB()) x[2]-=time0TPC->GetCalROC(sector)->GetValue(row,pad); | |
24db6af7 | 173 | // |
174 | // Tranform from pad - time coordinate system to the rotated global (tracking) system | |
175 | // | |
176 | Local2RotatedGlobal(sector,x); | |
177 | // | |
178 | // | |
179 | // | |
c1bdda91 | 180 | // Alignment |
181 | //TODO: calib->GetParameters()->GetClusterMatrix(sector)->LocalToMaster(x,xx); | |
c1bdda91 | 182 | RotatedGlobal2Global(sector,x); |
cf5b0aa0 | 183 | |
24db6af7 | 184 | // |
cf5b0aa0 | 185 | // old ExB correction |
24db6af7 | 186 | // |
768e46f1 | 187 | if(fCurrentRecoParam->GetUseExBCorrection()) { |
3ce45991 | 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 | ||
cf5b0aa0 | 198 | // |
199 | // new composed correction - will replace soon ExB correction | |
200 | // | |
768e46f1 | 201 | if(fCurrentRecoParam->GetUseComposedCorrection()&&correction) { |
cf5b0aa0 | 202 | Float_t distPoint[3]={xx[0],xx[1],xx[2]}; |
203 | correction->CorrectPoint(distPoint, sector); | |
204 | xx[0]=distPoint[0]; | |
205 | xx[1]=distPoint[1]; | |
206 | xx[2]=distPoint[2]; | |
3f3549a3 | 207 | if (correctionDelta&&fCurrentRecoParam->GetUseAlignmentTime()){ // appply time dependent correction if available and enabled |
208 | Float_t distPointDelta[3]={xx[0],xx[1],xx[2]}; | |
5c8d0ec4 | 209 | correctionDelta->CorrectPoint(distPointDelta, sector); |
3f3549a3 | 210 | xx[0]=distPointDelta[0]; |
211 | xx[1]=distPointDelta[1]; | |
212 | xx[2]=distPointDelta[2]; | |
213 | } | |
cf5b0aa0 | 214 | } |
215 | ||
216 | ||
ecc5dd8f | 217 | // |
218 | // Time of flight correction | |
003b43ed | 219 | // |
768e46f1 | 220 | if (fCurrentRecoParam->GetUseTOFCorrection()){ |
9430b11a | 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; | |
ecc5dd8f | 238 | } |
9430b11a | 239 | // |
240 | // | |
241 | // | |
242 | ||
ecc5dd8f | 243 | // |
c1bdda91 | 244 | Global2RotatedGlobal(sector,xx); |
2293155b | 245 | |
246 | // | |
247 | // Apply non linear distortion correction | |
248 | // | |
249 | if (distortionMapY ){ | |
0b736a46 | 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 | ||
2293155b | 261 | //can be switch on for each dimension separatelly |
4486a91f | 262 | if (fCurrentRecoParam->GetUseFieldCorrection()&0x2) |
0b736a46 | 263 | if (distortionMapY){ |
264 | xx[1]-= c0*distortionMapY->GetCalROC(sector)->GetValue(row,pad); | |
265 | xx[0]-= c1*distortionMapY->GetCalROC(sector)->GetValue(row,pad); | |
266 | } | |
2293155b | 267 | if (fCurrentRecoParam->GetUseFieldCorrection()&0x4) |
4486a91f | 268 | if (distortionMapZ) |
269 | xx[2]-=distortionMapZ->GetCalROC(sector)->GetValue(row,pad); | |
270 | if (fCurrentRecoParam->GetUseFieldCorrection()&0x8) | |
0b736a46 | 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 | ||
2293155b | 276 | } |
4486a91f | 277 | // |
2293155b | 278 | |
003b43ed | 279 | // |
c1bdda91 | 280 | x[0]=xx[0];x[1]=xx[1];x[2]=xx[2]; |
281 | } | |
282 | ||
24db6af7 | 283 | void AliTPCTransform::Local2RotatedGlobal(Int_t sector, Double_t *x) const { |
284 | // | |
285 | // | |
022ee144 | 286 | // Tranform coordinate from |
287 | // row, pad, time to x,y,z | |
24db6af7 | 288 | // |
022ee144 | 289 | // Drift Velocity |
290 | // Current implementation - common drift velocity - for full chamber | |
24db6af7 | 291 | // TODO: use a map or parametrisation! |
292 | // | |
293 | // | |
294 | // | |
768e46f1 | 295 | if (!fCurrentRecoParam) return; |
9430b11a | 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 | // | |
66954e3f | 300 | AliTPCcalibDB* calib=AliTPCcalibDB::Instance(); |
24db6af7 | 301 | AliTPCParam * param = calib->GetParameters(); |
9430b11a | 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 | } | |
43a74775 | 317 | // |
a8f8b6a1 | 318 | // simple caching non thread save |
319 | static Double_t vdcorrectionTime=1; | |
5647625c | 320 | static Double_t vdcorrectionTimeGY=0; |
a8f8b6a1 | 321 | static Double_t time0corrTime=0; |
322 | static Int_t lastStampT=-1; | |
323 | // | |
817766d5 | 324 | if (lastStampT!=(Int_t)fCurrentTimeStamp){ |
a8f8b6a1 | 325 | lastStampT=fCurrentTimeStamp; |
768e46f1 | 326 | if(fCurrentRecoParam->GetUseDriftCorrectionTime()>0) { |
a8f8b6a1 | 327 | vdcorrectionTime = (1+AliTPCcalibDB::Instance()-> |
328 | GetVDriftCorrectionTime(fCurrentTimeStamp, | |
fefec90f | 329 | fCurrentRun, |
a8f8b6a1 | 330 | sector%36>=18, |
331 | fCurrentRecoParam->GetUseDriftCorrectionTime())); | |
332 | time0corrTime= AliTPCcalibDB::Instance()-> | |
333 | GetTime0CorrectionTime(fCurrentTimeStamp, | |
fefec90f | 334 | fCurrentRun, |
a8f8b6a1 | 335 | sector%36>=18, |
336 | fCurrentRecoParam->GetUseDriftCorrectionTime()); | |
337 | } | |
338 | // | |
768e46f1 | 339 | if(fCurrentRecoParam->GetUseDriftCorrectionGY()>0) { |
a8f8b6a1 | 340 | |
5647625c | 341 | Double_t corrGy= AliTPCcalibDB::Instance()-> |
a8f8b6a1 | 342 | GetVDriftCorrectionGy(fCurrentTimeStamp, |
343 | AliTPCcalibDB::Instance()->GetRun(), | |
344 | sector%36>=18, | |
5647625c | 345 | fCurrentRecoParam->GetUseDriftCorrectionGY()); |
346 | vdcorrectionTimeGY = corrGy; | |
a8f8b6a1 | 347 | } |
43a74775 | 348 | } |
9430b11a | 349 | |
350 | ||
24db6af7 | 351 | if (!param){ |
352 | AliFatal("Parameters missing"); | |
768e46f1 | 353 | return; // make coverity happy |
24db6af7 | 354 | } |
355 | Int_t row=TMath::Nint(x[0]); | |
9389f9a4 | 356 | // Int_t pad=TMath::Nint(x[1]); |
24db6af7 | 357 | // |
358 | const Int_t kNIS=param->GetNInnerSector(), kNOS=param->GetNOuterSector(); | |
359 | Double_t sign = 1.; | |
502d13b5 | 360 | Double_t zwidth = param->GetZWidth()*driftCorr; |
5647625c | 361 | Float_t xyzPad[3]; |
362 | AliTPCROC::Instance()->GetPositionGlobal(sector, TMath::Nint(x[0]) ,TMath::Nint(x[1]), xyzPad); | |
363 | if (AliTPCRecoParam:: GetUseTimeCalibration()) zwidth*=vdcorrectionTime*(1+xyzPad[1]*vdcorrectionTimeGY); | |
24db6af7 | 364 | Double_t padWidth = 0; |
365 | Double_t padLength = 0; | |
366 | Double_t maxPad = 0; | |
367 | // | |
368 | if (sector < kNIS) { | |
369 | maxPad = param->GetNPadsLow(row); | |
370 | sign = (sector < kNIS/2) ? 1 : -1; | |
371 | padLength = param->GetPadPitchLength(sector,row); | |
372 | padWidth = param->GetPadPitchWidth(sector); | |
373 | } else { | |
374 | maxPad = param->GetNPadsUp(row); | |
375 | sign = ((sector-kNIS) < kNOS/2) ? 1 : -1; | |
376 | padLength = param->GetPadPitchLength(sector,row); | |
377 | padWidth = param->GetPadPitchWidth(sector); | |
378 | } | |
379 | // | |
380 | // X coordinate | |
022ee144 | 381 | x[0] = param->GetPadRowRadii(sector,row); // padrow X position - ideal |
24db6af7 | 382 | // |
383 | // Y coordinate | |
384 | // | |
385 | x[1]=(x[1]-0.5*maxPad)*padWidth; | |
afbaa016 | 386 | // pads are mirrorred on C-side |
387 | if (sector%36>17){ | |
388 | x[1]*=-1; | |
389 | } | |
390 | ||
391 | // | |
392 | ||
24db6af7 | 393 | // |
394 | // Z coordinate | |
395 | // | |
1e6337b1 | 396 | if (AliTPCcalibDB::Instance()->IsTrgL0()){ |
397 | // by defualt we assume L1 trigger is used - make a correction in case of L0 | |
398 | AliCTPTimeParams* ctp = AliTPCcalibDB::Instance()->GetCTPTimeParams(); | |
3d1b41c1 | 399 | if (ctp){ |
400 | //for TPC standalone runs no ctp info | |
401 | Double_t delay = ctp->GetDelayL1L0()*0.000000025; | |
402 | x[2]-=delay/param->GetTSample(); | |
403 | } | |
1e6337b1 | 404 | } |
405 | x[2]-= param->GetNTBinsL1(); | |
24db6af7 | 406 | x[2]*= zwidth; // tranform time bin to the distance to the ROC |
1e6337b1 | 407 | x[2]-= 3.*param->GetZSigma() + time0corrTime; |
24db6af7 | 408 | // subtract the time offsets |
409 | x[2] = sign*( param->GetZLength(sector) - x[2]); | |
c1bdda91 | 410 | } |
411 | ||
c2da420d | 412 | void AliTPCTransform::RotatedGlobal2Global(Int_t sector,Double_t *x) const { |
24db6af7 | 413 | // |
414 | // transform possition rotated global to the global | |
415 | // | |
c1bdda91 | 416 | Double_t cos,sin; |
417 | GetCosAndSin(sector,cos,sin); | |
418 | Double_t tmp=x[0]; | |
e81544f7 | 419 | x[0]= cos*tmp-sin*x[1]; |
420 | x[1]=+sin*tmp+cos*x[1]; | |
c1bdda91 | 421 | } |
422 | ||
c2da420d | 423 | void AliTPCTransform::Global2RotatedGlobal(Int_t sector,Double_t *x) const { |
24db6af7 | 424 | // |
425 | // tranform possition Global2RotatedGlobal | |
426 | // | |
c1bdda91 | 427 | Double_t cos,sin; |
428 | GetCosAndSin(sector,cos,sin); | |
429 | Double_t tmp=x[0]; | |
e81544f7 | 430 | x[0]= cos*tmp+sin*x[1]; |
431 | x[1]= -sin*tmp+cos*x[1]; | |
c1bdda91 | 432 | } |
433 | ||
c2da420d | 434 | void AliTPCTransform::GetCosAndSin(Int_t sector,Double_t &cos, |
c1bdda91 | 435 | Double_t &sin) const { |
436 | cos=fCoss[sector%18]; | |
437 | sin=fSins[sector%18]; | |
438 | } | |
439 | ||
c1bdda91 | 440 | |
43a74775 | 441 | void AliTPCTransform::ApplyTransformations(Double_t */*xyz*/, Int_t /*volID*/){ |
442 | // | |
443 | // Modify global position | |
444 | // xyz - global xyz position | |
445 | // volID - volID of detector (sector number) | |
446 | // | |
447 | // | |
448 | ||
449 | } |