Line data Source code
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 AliTPCROCVoltError3D
17 : /// \brief The class calculates the space point distortions due to z offsets of the
18 : ///
19 : /// ROCs via the residual voltage technique (Poisson relaxation) in 3D.
20 : /// Since the GG (part of the ROCs) represents the closure of the FC in z direction,
21 : /// every misalignment in z produces not only dz distortions but also electrical
22 : /// field inhomogeneities throughout the volume, which produces additional dr and rd$\phi$ distortions.
23 : ///
24 : /// Each ROC can be misaligned (in z direction) in three ways. A general z0 offset,
25 : /// an inclination along the x and an inclination along the y axis. The z-misalignment's
26 : /// can be set via the function SetROCData(TMatrixD *mat) for each single chamber (ROC).
27 : /// The array size has to be (72,3) representing the 72 chambers according to the
28 : /// offline numbering scheme (IROC: roc$<$36; OROC: roc$\geq$36) and the three misalignment's
29 : /// (see the source code for further details).
30 : ///
31 : /// Internally, these z offsets (unit is cm) are recalculated into residual voltage
32 : /// equivalents in order to make use of the relaxation technique.
33 : ///
34 : /// One has two possibilities when calculating the $dz$ distortions. The resulting
35 : /// distortions are purely due to the change of the drift velocity (along with the
36 : /// change of the drift field) when the SetROCDisplacement is FALSE.
37 : /// For this class, this is a rather unphysical setting and should be avoided.
38 : /// When the flag is set to TRUE, the corresponding offset in z is added to the dz
39 : /// calculation of the outer ROCs.
40 : /// For the Alice TPC gas, both effects are of similar magnitude. This means, if the
41 : /// drift length is sufficiently large, a z-offset of a chamber appears to have (approx.)
42 : /// twice the magnitude when one looks at the actual dz distortions.
43 : ///
44 : /// In addition, this class allows a correction regarding the different arrival times
45 : /// of the electrons due to the geometrical difference of the inner and outer chambers.
46 : /// The impact was simulated via Garfield. If the flag is set via the
47 : /// function SetElectronArrivalCorrection, the electron-arrival correction is added to the dz calculation.
48 : /// 
49 : ///
50 : /// \author Jim Thomas, Stefan Rossegger
51 : /// \date 08/08/2010
52 :
53 :
54 : #include "AliMagF.h"
55 : #include "TGeoGlobalMagField.h"
56 : #include "AliTPCcalibDB.h"
57 : #include "AliTPCParam.h"
58 : #include "AliLog.h"
59 : #include "TMatrixD.h"
60 : #include "TFile.h"
61 :
62 : #include "TMath.h"
63 : #include "AliTPCROC.h"
64 : #include "AliTPCROCVoltError3D.h"
65 :
66 : /// \cond CLASSIMP
67 24 : ClassImp(AliTPCROCVoltError3D)
68 : /// \endcond
69 :
70 : AliTPCROCVoltError3D::AliTPCROCVoltError3D()
71 0 : : AliTPCCorrection("ROCVoltErrors","ROC z alignment Errors"),
72 0 : fC0(0.),fC1(0.),
73 0 : fROCdisplacement(kTRUE),
74 0 : fElectronArrivalCorrection(kTRUE),
75 0 : fInitLookUp(kFALSE),
76 0 : fROCDataFileName(""),
77 0 : fdzDataLinFit(0)
78 0 : {
79 : //
80 : // default constructor
81 : //
82 :
83 : // Array which will contain the solution according to the setted boundary conditions
84 : // main input: z alignment of the Read Out chambers
85 : // see InitROCVoltError3D() function
86 0 : for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
87 0 : fLookUpErOverEz[k] = new TMatrixF(kNR,kNZ);
88 0 : fLookUpEphiOverEz[k] = new TMatrixF(kNR,kNZ);
89 0 : fLookUpDeltaEz[k] = new TMatrixF(kNR,kNZ);
90 : }
91 : // fROCDataFileName="$ALICE_ROOT/TPC/Calib/maps/TPCROCdzSurvey.root";
92 : // SetROCDataFileName(fROCDataFileName.Data()); // initialization of fdzDataLinFit is included
93 :
94 0 : }
95 :
96 0 : AliTPCROCVoltError3D::~AliTPCROCVoltError3D() {
97 : /// destructor
98 :
99 0 : for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
100 0 : delete fLookUpErOverEz[k];
101 0 : delete fLookUpEphiOverEz[k];
102 0 : delete fLookUpDeltaEz[k];
103 : }
104 :
105 0 : delete fdzDataLinFit;
106 0 : }
107 :
108 :
109 :
110 : Bool_t AliTPCROCVoltError3D::AddCorrectionCompact(AliTPCCorrection* corr, Double_t weight){
111 : /// Add correction and make them compact
112 : /// Assumptions:
113 : /// - origin of distortion/correction are additive
114 : /// - only correction ot the same type supported ()
115 :
116 0 : if (corr==NULL) {
117 0 : AliError("Zerro pointer - correction");
118 0 : return kFALSE;
119 : }
120 0 : AliTPCROCVoltError3D * corrC = dynamic_cast<AliTPCROCVoltError3D *>(corr);
121 0 : if (corrC == NULL) {
122 0 : AliError(TString::Format("Inconsistent class types: %s\%s",IsA()->GetName(),corr->IsA()->GetName()).Data());
123 0 : return kFALSE;
124 : }
125 : //
126 0 : TMatrixD matrixDz=*(corrC->fdzDataLinFit);
127 0 : matrixDz*=weight;
128 0 : if (fdzDataLinFit==NULL) {
129 0 : fdzDataLinFit=new TMatrixD(matrixDz);
130 0 : fROCdisplacement=corrC->fROCdisplacement;
131 0 : fElectronArrivalCorrection=corrC->fElectronArrivalCorrection;
132 0 : }
133 : else{
134 0 : (*fdzDataLinFit)+=matrixDz;
135 : }
136 : return kTRUE;
137 0 : }
138 :
139 :
140 :
141 :
142 :
143 : void AliTPCROCVoltError3D::SetROCData(TMatrixD * matrix){
144 : /// Set a z alignment map of the chambers not via a file, but
145 : /// directly via a TMatrix(72,3), where dz = p0 + p1*(lx-133.4) + p2*ly (all in cm)
146 :
147 0 : if (!fdzDataLinFit) fdzDataLinFit=new TMatrixD(*matrix);
148 0 : else *fdzDataLinFit = *matrix;
149 0 : }
150 :
151 :
152 : void AliTPCROCVoltError3D::Init() {
153 : /// Initialization funtion
154 :
155 0 : AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
156 0 : if (!magF) AliError("Magneticd field - not initialized");
157 0 : Double_t bzField = magF->SolenoidField()/10.; //field in T
158 0 : AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
159 0 : if (!param) AliError("Parameters - not initialized");
160 0 : Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us] // From dataBase: to be updated: per second (ideally)
161 : Double_t ezField = 400; // [V/cm] // to be updated: never (hopefully)
162 0 : Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ;
163 : // Correction Terms for effective omegaTau; obtained by a laser calibration run
164 0 : SetOmegaTauT1T2(wt,fT1,fT2);
165 :
166 0 : if (!fInitLookUp) InitROCVoltError3D();
167 0 : }
168 :
169 : void AliTPCROCVoltError3D::Update(const TTimeStamp &/*timeStamp*/) {
170 : /// Update function
171 :
172 0 : AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
173 0 : if (!magF) AliError("Magneticd field - not initialized");
174 0 : Double_t bzField = magF->SolenoidField()/10.; //field in T
175 0 : AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
176 0 : if (!param) AliError("Parameters - not initialized");
177 0 : Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us] // From dataBase: to be updated: per second (ideally)
178 : Double_t ezField = 400; // [V/cm] // to be updated: never (hopefully)
179 0 : Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ;
180 : // Correction Terms for effective omegaTau; obtained by a laser calibration run
181 0 : SetOmegaTauT1T2(wt,fT1,fT2);
182 :
183 0 : }
184 :
185 : void AliTPCROCVoltError3D::SetROCDataFileName(const char * fname) {
186 : /// Set / load the ROC data (linear fit of ROC misalignments)
187 :
188 0 : fROCDataFileName = fname;
189 :
190 0 : TFile f(fROCDataFileName.Data(),"READ");
191 0 : TMatrixD *m = (TMatrixD*) f.Get("dzSurveyLinFitData");
192 : TMatrixD &mf = *m;
193 :
194 : // prepare some space
195 :
196 0 : if (fdzDataLinFit) delete fdzDataLinFit;
197 0 : fdzDataLinFit = new TMatrixD(72,3);
198 : TMatrixD &dataIntern = *fdzDataLinFit;
199 :
200 0 : for (Int_t iroc=0;iroc<72;iroc++) {
201 0 : dataIntern(iroc,0) = mf(iroc,0); // z0 offset
202 0 : dataIntern(iroc,1) = mf(iroc,1); // slope in x
203 0 : dataIntern(iroc,2) = mf(iroc,2); // slope in y
204 : }
205 :
206 0 : f.Close();
207 :
208 0 : fInitLookUp = kFALSE;
209 :
210 0 : }
211 :
212 : void AliTPCROCVoltError3D::GetCorrection(const Float_t x[],const Short_t roc,Float_t dx[]) {
213 : /// Calculates the correction due e.g. residual voltage errors on the TPC boundaries
214 :
215 : const Double_t kEpsilon=Double_t(FLT_MIN);
216 0 : if (!fInitLookUp) {
217 0 : AliInfo("Lookup table was not initialized! Perform the inizialisation now ...");
218 0 : InitROCVoltError3D();
219 0 : }
220 : static Bool_t forceInit=kTRUE; //temporary needed for back compatibility with old OCDB entries
221 0 : if (forceInit&&fLookUpErOverEz[0]){
222 0 : if (TMath::Abs(fLookUpErOverEz[0]->Sum())<kEpsilon){//temporary needed for back compatibility with old OCDB entries
223 0 : ForceInitROCVoltError3D();
224 0 : }
225 0 : forceInit=kFALSE;
226 0 : }
227 :
228 :
229 : Int_t order = 1 ; // FIXME: hardcoded? Linear interpolation = 1, Quadratic = 2
230 :
231 : Float_t intEr, intEphi, intDeltaEz;
232 : Double_t r, phi, z ;
233 : Int_t sign;
234 :
235 0 : r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
236 0 : phi = TMath::ATan2(x[1],x[0]) ;
237 0 : if ( phi < 0 ) phi += TMath::TwoPi() ; // Table uses phi from 0 to 2*Pi
238 0 : z = x[2] ; // Create temporary copy of x[2]
239 :
240 0 : if ( (roc%36) < 18 ) {
241 : sign = 1; // (TPC A side)
242 0 : } else {
243 : sign = -1; // (TPC C side)
244 : }
245 :
246 0 : if ( sign==1 && z < fgkZOffSet ) z = fgkZOffSet; // Protect against discontinuity at CE
247 0 : if ( sign==-1 && z > -fgkZOffSet ) z = -fgkZOffSet; // Protect against discontinuity at CE
248 :
249 :
250 0 : if ( (sign==1 && z<0) || (sign==-1 && z>0) ) // just a consistency check
251 0 : AliError("ROC number does not correspond to z coordinate! Calculation of distortions is most likely wrong!");
252 :
253 : // Get the Er and Ephi field integrals plus the integral over DeltaEz
254 0 : intEr = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi,
255 0 : fgkRList, fgkZList, fgkPhiList, fLookUpErOverEz );
256 0 : intEphi = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi,
257 0 : fgkRList, fgkZList, fgkPhiList, fLookUpEphiOverEz);
258 0 : intDeltaEz = Interpolate3DTable(order, r, z, phi, kNR, kNZ, kNPhi,
259 0 : fgkRList, fgkZList, fgkPhiList, fLookUpDeltaEz );
260 :
261 : // printf("%lf %lf %lf\n",intEr,intEphi,intDeltaEz);
262 :
263 : // Calculate distorted position
264 0 : if ( r > 0.0 ) {
265 0 : phi = phi + ( fC0*intEphi - fC1*intEr ) / r;
266 0 : r = r + ( fC0*intEr + fC1*intEphi );
267 0 : }
268 :
269 : // Calculate correction in cartesian coordinates
270 0 : dx[0] = r * TMath::Cos(phi) - x[0];
271 0 : dx[1] = r * TMath::Sin(phi) - x[1];
272 0 : dx[2] = intDeltaEz; // z distortion - (internally scaled with driftvelocity dependency
273 : // on the Ez field plus the actual ROC misalignment (if set TRUE)
274 :
275 :
276 0 : if (fElectronArrivalCorrection) {
277 :
278 : // correction for the OROC (in average, a 0.014usec longer drift time
279 : // due to different position of the anode wires) -> vd*dt -> 2.64*0.014 = 0.0369 cm
280 : // FIXME: correction are token from Magboltz simulations
281 : // should be loaded from a database
282 :
283 0 : AliTPCROC * rocInfo = AliTPCROC::Instance();
284 0 : Double_t rCrossingROC = (rocInfo->GetPadRowRadii(0,62)+rocInfo->GetPadRowRadii(36,0))/2;
285 :
286 0 : if (r>rCrossingROC) {
287 0 : if (sign==1)
288 0 : dx[2] += 0.0369; // A side - negative correction
289 : else
290 0 : dx[2] -= 0.0369; // C side - positive correction
291 : }
292 :
293 0 : }
294 :
295 0 : }
296 :
297 : void AliTPCROCVoltError3D::InitROCVoltError3D() {
298 : /// Initialization of the Lookup table which contains the solutions of the
299 : /// Dirichlet boundary problem
300 : /// Calculation of the single 3D-Poisson solver is done just if needed
301 : /// (see basic lookup tables in header file)
302 :
303 : const Int_t order = 1 ; // Linear interpolation = 1, Quadratic = 2
304 0 : const Float_t gridSizeR = (fgkOFCRadius-fgkIFCRadius) / (kRows-1) ;
305 0 : const Float_t gridSizeZ = fgkTPCZ0 / (kColumns-1) ;
306 0 : const Float_t gridSizePhi = TMath::TwoPi() / ( 18.0 * kPhiSlicesPerSector);
307 :
308 : // temporary arrays to create the boundary conditions
309 0 : TMatrixD *arrayofArrayV[kPhiSlices], *arrayofCharge[kPhiSlices] ;
310 0 : TMatrixD *arrayofEroverEz[kPhiSlices], *arrayofEphioverEz[kPhiSlices], *arrayofDeltaEz[kPhiSlices] ;
311 :
312 0 : for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
313 0 : arrayofArrayV[k] = new TMatrixD(kRows,kColumns) ;
314 0 : arrayofCharge[k] = new TMatrixD(kRows,kColumns) ;
315 0 : arrayofEroverEz[k] = new TMatrixD(kRows,kColumns) ;
316 0 : arrayofEphioverEz[k] = new TMatrixD(kRows,kColumns) ;
317 0 : arrayofDeltaEz[k] = new TMatrixD(kRows,kColumns) ;
318 : }
319 :
320 : // list of point as used in the poisson relation and the interpolation (during sum up)
321 0 : Double_t rlist[kRows], zedlist[kColumns] , philist[kPhiSlices];
322 0 : for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
323 0 : philist[k] = gridSizePhi * k;
324 0 : for ( Int_t i = 0 ; i < kRows ; i++ ) {
325 0 : rlist[i] = fgkIFCRadius + i*gridSizeR ;
326 0 : for ( Int_t j = 0 ; j < kColumns ; j++ ) { // Fill Vmatrix with Boundary Conditions
327 0 : zedlist[j] = j * gridSizeZ ;
328 : }
329 : }
330 : }
331 :
332 : // ==========================================================================
333 : // Solve Poisson's equation in 3D cylindrical coordinates by relaxation technique
334 : // Allow for different size grid spacing in R and Z directions
335 :
336 : const Int_t symmetry = 0;
337 :
338 : // Set bondaries and solve Poisson's equation --------------------------
339 :
340 0 : if ( !fInitLookUp ) {
341 :
342 0 : AliInfo(Form("Solving the poisson equation (~ %d sec)",2*10*(int)(kPhiSlices/10)));
343 :
344 0 : for ( Int_t side = 0 ; side < 2 ; side++ ) { // Solve Poisson3D twice; once for +Z and once for -Z
345 :
346 0 : for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
347 0 : TMatrixD &arrayV = *arrayofArrayV[k] ;
348 0 : TMatrixD &charge = *arrayofCharge[k] ;
349 :
350 : //Fill arrays with initial conditions. V on the boundary and Charge in the volume.
351 0 : for ( Int_t i = 0 ; i < kRows ; i++ ) {
352 0 : for ( Int_t j = 0 ; j < kColumns ; j++ ) { // Fill Vmatrix with Boundary Conditions
353 0 : arrayV(i,j) = 0.0 ;
354 0 : charge(i,j) = 0.0 ;
355 :
356 0 : Float_t radius0 = rlist[i] ;
357 0 : Float_t phi0 = gridSizePhi * k ;
358 :
359 : // To avoid problems at sector boundaries, use an average of +- 1 degree from actual phi location
360 0 : if ( j == (kColumns-1) ) {
361 0 : arrayV(i,j) = 0.5* ( GetROCVoltOffset( side, radius0, phi0+0.02 ) + GetROCVoltOffset( side, radius0, phi0-0.02 ) ) ;
362 :
363 0 : if (side==1) // C side
364 0 : arrayV(i,j) = -arrayV(i,j); // minus sign on the C side to allow a consistent usage of global z when setting the boundaries
365 : }
366 : }
367 : }
368 :
369 0 : for ( Int_t i = 1 ; i < kRows-1 ; i++ ) {
370 0 : for ( Int_t j = 1 ; j < kColumns-1 ; j++ ) {
371 0 : charge(i,j) = 0.0 ;
372 : }
373 : }
374 : }
375 :
376 : // Solve Poisson's equation in 3D cylindrical coordinates by relaxation technique
377 : // Allow for different size grid spacing in R and Z directions
378 :
379 0 : PoissonRelaxation3D( arrayofArrayV, arrayofCharge,
380 0 : arrayofEroverEz, arrayofEphioverEz, arrayofDeltaEz,
381 : kRows, kColumns, kPhiSlices, gridSizePhi, kIterations,
382 0 : symmetry, fROCdisplacement) ;
383 :
384 :
385 : //Interpolate results onto a custom grid which is used just for these calculations.
386 : Double_t r, phi, z ;
387 0 : for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
388 0 : phi = fgkPhiList[k] ;
389 :
390 0 : TMatrixF &erOverEz = *fLookUpErOverEz[k] ;
391 0 : TMatrixF &ephiOverEz = *fLookUpEphiOverEz[k];
392 0 : TMatrixF &deltaEz = *fLookUpDeltaEz[k] ;
393 :
394 0 : for ( Int_t j = 0 ; j < kNZ ; j++ ) {
395 :
396 0 : z = TMath::Abs(fgkZList[j]) ; // Symmetric solution in Z that depends only on ABS(Z)
397 :
398 0 : if ( side == 0 && fgkZList[j] < 0 ) continue; // Skip rest of this loop if on the wrong side
399 0 : if ( side == 1 && fgkZList[j] > 0 ) continue; // Skip rest of this loop if on the wrong side
400 :
401 0 : for ( Int_t i = 0 ; i < kNR ; i++ ) {
402 0 : r = fgkRList[i] ;
403 :
404 : // Interpolate basicLookup tables; once for each rod, then sum the results
405 0 : erOverEz(i,j) = Interpolate3DTable(order, r, z, phi, kRows, kColumns, kPhiSlices,
406 0 : rlist, zedlist, philist, arrayofEroverEz );
407 0 : ephiOverEz(i,j) = Interpolate3DTable(order, r, z, phi, kRows, kColumns, kPhiSlices,
408 : rlist, zedlist, philist, arrayofEphioverEz);
409 0 : deltaEz(i,j) = Interpolate3DTable(order, r, z, phi, kRows, kColumns, kPhiSlices,
410 : rlist, zedlist, philist, arrayofDeltaEz );
411 :
412 0 : if (side == 1) deltaEz(i,j) = - deltaEz(i,j); // negative coordinate system on C side
413 :
414 : } // end r loop
415 0 : }// end z loop
416 : }// end phi loop
417 :
418 0 : if ( side == 0 ) AliInfo(" A side done");
419 0 : if ( side == 1 ) AliInfo(" C side done");
420 : } // end side loop
421 0 : }
422 :
423 : // clear the temporary arrays lists
424 0 : for ( Int_t k = 0 ; k < kPhiSlices ; k++ ) {
425 0 : delete arrayofArrayV[k];
426 0 : delete arrayofCharge[k];
427 0 : delete arrayofEroverEz[k];
428 0 : delete arrayofEphioverEz[k];
429 0 : delete arrayofDeltaEz[k];
430 : }
431 :
432 :
433 0 : fInitLookUp = kTRUE;
434 :
435 0 : }
436 :
437 :
438 : Float_t AliTPCROCVoltError3D::GetROCVoltOffset(Int_t side, Float_t r0, Float_t phi0) {
439 : /// Returns the dz alignment data (in voltage equivalents) at
440 : /// the given position
441 :
442 0 : Float_t xp = r0*TMath::Cos(phi0);
443 0 : Float_t yp = r0*TMath::Sin(phi0);
444 :
445 : // phi0 should be between 0 and 2pi
446 0 : if (phi0<0) phi0+=TMath::TwoPi();
447 0 : Int_t roc = (Int_t)TMath::Floor((TMath::RadToDeg()*phi0)/20);
448 0 : if (side==1) roc+=18; // C side
449 0 : if (r0>132) roc+=36; // OROC
450 :
451 : // linear-plane data: z = z0 + kx*lx + ky*ly (rotation in local coordinates)
452 0 : TMatrixD &fitData = *fdzDataLinFit;
453 :
454 : // local coordinates
455 0 : Double_t secAlpha = TMath::DegToRad()*(10.+20.*(((Int_t)roc)%18));
456 0 : Float_t lx = xp*TMath::Cos(secAlpha)+yp*TMath::Sin(secAlpha);
457 0 : Float_t ly = yp*TMath::Cos(secAlpha)-xp*TMath::Sin(secAlpha);
458 :
459 : // reference of rotation in lx is at the intersection between OROC and IROC
460 : // necessary, since the Fitprozedure is otherwise useless
461 :
462 0 : AliTPCROC * rocInfo = AliTPCROC::Instance();
463 0 : Double_t lxRef = (rocInfo->GetPadRowRadii(0,62)+rocInfo->GetPadRowRadii(36,0))/2;
464 :
465 0 : Float_t dz = fitData(roc,0)+fitData(roc,1)*(lx-lxRef) + fitData(roc,2)*ly; // value in cm
466 :
467 : // aproximated Voltage-offset-aquivalent to the z misalignment
468 : // (linearly scaled with the z position)
469 0 : Double_t ezField = (fgkCathodeV-fgkGG)/fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm;
470 0 : Float_t voltOff = dz*ezField; // values in "Volt equivalents"
471 :
472 0 : return voltOff;
473 : }
474 :
475 : TH2F * AliTPCROCVoltError3D::CreateHistoOfZAlignment(Int_t side, Int_t nx, Int_t ny) {
476 : /// return a simple histogramm containing the input to the poisson solver
477 : /// (z positions of the Read-out chambers, linearly interpolated)
478 :
479 0 : char hname[100];
480 0 : if (side==0) snprintf(hname,100,"survey_dz_Aside");
481 0 : if (side==1) snprintf(hname,100,"survey_dz_Cside");
482 :
483 0 : TH2F *h = new TH2F(hname,hname,nx,-250.,250.,ny,-250.,250.);
484 :
485 0 : for (Int_t iy=1;iy<=ny;++iy) {
486 0 : Double_t yp = h->GetYaxis()->GetBinCenter(iy);
487 0 : for (Int_t ix=1;ix<=nx;++ix) {
488 0 : Double_t xp = h->GetXaxis()->GetBinCenter(ix);
489 :
490 0 : Float_t r0 = TMath::Sqrt(xp*xp+yp*yp);
491 0 : Float_t phi0 = TMath::ATan2(yp,xp);
492 :
493 0 : Float_t dz = GetROCVoltOffset(side,r0,phi0); // in [volt]
494 :
495 0 : Double_t ezField = (fgkCathodeV-fgkGG)/fgkTPCZ0; // = ALICE Electric Field (V/cm) Magnitude ~ -400 V/cm;
496 0 : dz = dz/ezField; // in [cm]
497 :
498 0 : if (85.<=r0 && r0<=245.) {
499 0 : h->SetBinContent(ix,iy,dz);
500 0 : } else {
501 0 : h->SetBinContent(ix,iy,0.);
502 : }
503 : }
504 : }
505 :
506 0 : h->GetXaxis()->SetTitle("x [cm]");
507 0 : h->GetYaxis()->SetTitle("y [cm]");
508 0 : h->GetZaxis()->SetTitle("dz [cm]");
509 0 : h->SetStats(0);
510 : // h->DrawCopy("colz");
511 :
512 0 : return h;
513 0 : }
514 :
515 : void AliTPCROCVoltError3D::Print(const Option_t* option) const {
516 : /// Print function to check the settings of the Rod shifts and the rotated clips
517 : /// option=="a" prints the C0 and C1 coefficents for calibration purposes
518 :
519 0 : TString opt = option; opt.ToLower();
520 0 : printf("%s\n",GetTitle());
521 0 : printf(" - z aligmnet of the TPC Read-Out chambers \n");
522 0 : printf(" (linear interpolation within the chamber: dz = z0 + kx*(lx-133) + ky*ly [cm] ) \n");
523 0 : printf(" Info: Check the following data-file for more details: %s \n",fROCDataFileName.Data());
524 0 : printf(" fROCdisplacement: %s\n", fROCdisplacement ? "kTRUE" : "kFALSE");
525 0 : printf(" fElectronArrivalCorrection: %s\n", fElectronArrivalCorrection ? "kTRUE" : "kFALSE");
526 :
527 0 : if (opt.Contains("a")) { // Print all details
528 0 : TMatrixD &fitData = *fdzDataLinFit;
529 0 : printf(" A side: IROC ROCX=(z0,kx,ky): \n");
530 0 : for (Int_t roc = 0; roc<18; roc++)
531 0 : printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
532 0 : printf("\n A side: OROC ROCX=(z0,kx,ky): \n");
533 0 : for (Int_t roc = 36; roc<54; roc++)
534 0 : printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
535 0 : printf("\n C side: IROC ROCX=(z0,kx,ky): \n");
536 0 : for (Int_t roc = 18; roc<36; roc++)
537 0 : printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
538 0 : printf("\n C side: OROC ROCX=(z0,kx,ky): \n");
539 0 : for (Int_t roc = 54; roc<72; roc++)
540 0 : printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
541 0 : printf("\n\n");
542 0 : printf(" - T1: %1.4f, T2: %1.4f \n",fT1,fT2);
543 0 : printf(" - C1: %1.4f, C0: %1.4f \n",fC1,fC0);
544 0 : }
545 :
546 0 : if (!fInitLookUp) AliError("Lookup table was not initialized! You should do InitROCVoltError3D() ...");
547 :
548 0 : }
|