]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TPC/AliTPCGGVoltError.cxx
macro to run on alien
[u/mrichter/AliRoot.git] / TPC / AliTPCGGVoltError.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 //                                                                        //
18 // AliTPCGGVoltError class                                                //
19 // The class calculates the electric field and space point distortions    //
20 // due a Gating Grid (GG) Error voltage. It uses the exact calculation    //
21 // technique based on bessel functions. (original code from STAR)         //
22 // The class allows "effective Omega Tau" corrections.                    // 
23 //                                                                        //
24 // date: 27/04/2010                                                       //
25 // Authors: Jim Thomas, Stefan Rossegger, Magnus Mager                    //
26 //                                                                        //
27 // Example usage:                                                         //
28 //  AliTPCGGVoltError GGerror;                                            //
29 //  GGerror.SetOmegaTauT1T2(0.32,1.,1.); // values ideally from OCDB      //
30 //  GGerror.SetDeltaVGGA(50.);           // voltage offset A-side         //
31 //  GGerror.SetDeltaVGGC(50.);           // voltage offset C-side         //
32 //  GGerror.InitGGVoltErrorDistortion(); // initialization of the look up //
33 //  // plot dRPhi distortions ...                                         //
34 //  GGerror.CreateHistoDRPhiinZR(1.,100,100)->Draw("surf2");              //
35 ////////////////////////////////////////////////////////////////////////////
36
37
38 #include "AliMagF.h"
39 #include "TGeoGlobalMagField.h"
40 #include "AliTPCcalibDB.h"
41 #include "AliTPCParam.h"
42 #include "AliLog.h"
43
44 #include "AliTPCGGVoltError.h"
45 #include <TMath.h>
46
47 AliTPCGGVoltError::AliTPCGGVoltError()
48   : AliTPCCorrection("GGVoltError","GatingGrid (GG) Voltage Error"),
49     fC0(0.),fC1(0.),
50     fDeltaVGGA(0.),fDeltaVGGC(0.),
51     fInitLookUp(kFALSE)
52 {
53   //
54   // default constructor
55   //
56 }
57
58 AliTPCGGVoltError::~AliTPCGGVoltError() {
59   //
60   // default destructor
61   //
62 }
63
64 void AliTPCGGVoltError::Init() {
65   //
66   // Init function
67   //
68   AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
69   if (!magF) AliError("Magneticd field - not initialized");
70   Double_t bzField = magF->SolenoidField()/10.; //field in T
71   AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
72   if (!param) AliError("Parameters - not initialized");
73   Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us]   // From dataBase: to be updated: per second (ideally)
74   Double_t ezField = 400; // [V/cm]   // to be updated: never (hopefully)
75   Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ; 
76   //
77   SetOmegaTauT1T2(wt,fT1,fT2);
78   InitGGVoltErrorDistortion();
79   //SetDeltaVGGA(0.0);//  ideally from the database
80   //SetDeltaVGGC(0.0);//  ideally from the database
81 }
82
83 void AliTPCGGVoltError::Update(const TTimeStamp &/*timeStamp*/) {
84   //
85   // Update function
86   //
87   AliMagF* magF= (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
88   if (!magF) AliError("Magneticd field - not initialized");
89   Double_t bzField = magF->SolenoidField()/10.; //field in T
90   AliTPCParam *param= AliTPCcalibDB::Instance()->GetParameters();
91   if (!param) AliError("Parameters - not initialized");
92   Double_t vdrift = param->GetDriftV()/1000000.; // [cm/us]   // From dataBase: to be updated: per second (ideally)
93   Double_t ezField = 400; // [V/cm]   // to be updated: never (hopefully)
94   Double_t wt = -10.0 * (bzField*10) * vdrift / ezField ; 
95
96   SetOmegaTauT1T2(wt,fT1,fT2);
97   //  InitGGVoltErrorDistortion(); // not necessary in here since the Voltage should not change!
98 }
99
100
101
102 void AliTPCGGVoltError::GetCorrection(const Float_t x[],const Short_t roc,Float_t dx[]) {
103
104   //
105   // Gated Grid Voltage Error
106   //
107   // Calculates the effect of having an incorrect voltage on the A or C end plate Gated Grids.
108   //
109   // Electrostatic Equations from StarNote SN0253 by Howard Wieman.
110   //
111   
112   if (!fInitLookUp) AliError("Lookup table was not initialized! You should do InitGGVoltErrorDistortion() ...");
113   
114   Int_t   order     = 1 ;               // FIXME: hardcoded? Linear interpolation = 1, Quadratic = 2         
115  
116   Double_t intEr, intEphi ;
117   Double_t r, phi, z ;
118   Int_t    sign ;
119
120   Double_t deltaVGG;
121   
122   r   = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] );
123   phi = TMath::ATan2(x[1],x[0]);
124   if ( phi < 0 ) phi += TMath::TwoPi();                   // Table uses phi from 0 to 2*Pi
125   z   = x[2] ;
126
127   if ( (roc%36) < 18 ) {
128     sign =  1; 
129     deltaVGG = fDeltaVGGA;           // (TPC End A)
130   } else {
131     sign = -1;                       // (TPC End C)
132     deltaVGG = fDeltaVGGC; 
133   }
134
135   if ( sign==1  && z <  fgkZOffSet ) z =  fgkZOffSet;    // Protect against discontinuity at CE
136   if ( sign==-1 && z > -fgkZOffSet ) z = -fgkZOffSet;    // Protect against discontinuity at CE
137
138   Interpolate2DEdistortion( order, r, z, fGGVoltErrorER, intEr );
139   intEphi = 0.0;  // Efield is symmetric in phi
140
141   // Calculate distorted position
142   if ( r > 0.0 ) {
143     phi =  phi + deltaVGG*( fC0*intEphi - fC1*intEr ) / r;      
144     r   =  r   + deltaVGG*( fC0*intEr   + fC1*intEphi );  
145   }
146   
147   // Calculate correction in cartesian coordinates
148   dx[0] = r * TMath::Cos(phi) - x[0];
149   dx[1] = r * TMath::Sin(phi) - x[1]; 
150   dx[2] = 0.; // z distortion not implemented (1st order distortions)
151
152
153
154 }
155
156
157 Float_t AliTPCGGVoltError::GetIntErOverEz(const Float_t x[],const Short_t roc) {
158   //
159   // This function is purely for calibration purposes
160   // Calculates the integral (int Er/Ez dz) for the setted GG voltage offset 
161   // 
162
163   if (!fInitLookUp) AliError("Lookup table was not initialized! You should do InitGGVoltErrorDistortion() ...");
164
165   Int_t   order     = 1 ;     // FIXME: so far hardcoded? Linear interpolation = 1, Quadratic = 2         
166   
167   Double_t intEr;
168   Double_t r, phi, z ;
169   Int_t    sign ;
170   
171   Double_t deltaVGG;
172   
173   r   = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] );
174   phi = TMath::ATan2(x[1],x[0]);
175   if ( phi < 0 ) phi += TMath::TwoPi();        // Table uses phi from 0 to 2*Pi
176   z   = x[2] ;
177
178   if ( (roc%36) < 18 ) {
179     sign =  1; 
180     deltaVGG = fDeltaVGGA;           // (TPC End A)
181   } else {
182     sign = -1;                       // (TPC End C)
183     deltaVGG = fDeltaVGGC; 
184   }
185
186   if ( sign==1  && z <  fgkZOffSet ) z =  fgkZOffSet;    // Protect against discontinuity at CE
187   if ( sign==-1 && z > -fgkZOffSet ) z = -fgkZOffSet;    // Protect against discontinuity at CE
188
189   Interpolate2DEdistortion(order, r, z, fGGVoltErrorER, intEr );
190
191   return (intEr*deltaVGG);
192
193 }
194
195 void AliTPCGGVoltError::InitGGVoltErrorDistortion() {
196   //
197   // Initialization of the Lookup table which contains the solutions of the GG Error problem
198   //
199
200   Double_t r,z;
201   Int_t nterms = 100 ;
202   for ( Int_t i = 0 ; i < kNZ ; ++i ) {
203     z = fgkZList[i] ;
204     for ( Int_t j = 0 ; j < kNR ; ++j ) {
205       r = fgkRList[j] ;
206       fGGVoltErrorER[i][j] = 0.0 ;          
207       Double_t intz = 0.0 ;
208       for ( Int_t n = 1 ; n < nterms ; ++n ) {
209         Double_t k    =  n * TMath::Pi() / fgkTPCZ0 ;
210         Double_t ein  =  0 ;                    // Error potential on the IFC
211         Double_t eout =  0 ;                    // Error potential on the OFC
212         if ( z < 0 ) {
213           ein   =  -2.0 / ( k * (fgkCathodeV - fgkGG) ) ;       
214           eout  =  -2.0 / ( k * (fgkCathodeV - fgkGG) ) ;       
215         }
216         if ( z == 0 ) continue ;
217         if ( z > 0 ) {
218           ein   =  -2.0 / ( k * (fgkCathodeV - fgkGG) ) ;       
219           eout  =  -2.0 / ( k * (fgkCathodeV - fgkGG) ) ;       
220         }
221         Double_t an   =  ein  * TMath::BesselK0( k*fgkOFCRadius ) - eout * TMath::BesselK0( k*fgkIFCRadius ) ;
222         Double_t bn   =  eout * TMath::BesselI0( k*fgkIFCRadius ) - ein  * TMath::BesselI0( k*fgkOFCRadius ) ;
223         Double_t numerator =
224           an * TMath::BesselI1( k*r ) - bn * TMath::BesselK1( k*r ) ;
225         Double_t denominator =
226           TMath::BesselK0( k*fgkOFCRadius ) * TMath::BesselI0( k*fgkIFCRadius ) -
227           TMath::BesselK0( k*fgkIFCRadius ) * TMath::BesselI0( k*fgkOFCRadius ) ;
228         Double_t zterm = TMath::Cos( k*(fgkTPCZ0-TMath::Abs(z)) ) - 1 ;
229         intz += zterm * numerator / denominator ;
230         // Assume series converges, break if small terms
231         if ( n>10 && TMath::Abs(intz)*1.e-10 > TMath::Abs(numerator/denominator) ) break;   
232       }
233       fGGVoltErrorER[i][j] = (Double_t) intz ;
234
235     }
236   }
237   
238   fInitLookUp = kTRUE;
239 }
240
241
242
243 void AliTPCGGVoltError::Print(const Option_t* option) const {
244   //
245   // Print function to check the settings (e.g. voltage offsets)
246   // option=="a" prints the C0 and C1 coefficents for calibration purposes
247   //
248
249   TString opt = option; opt.ToLower();
250   printf("%s\n",GetTitle());
251   printf(" - GG Voltage offset: A-side: %3.1f V, C-side: %3.1f V \n",fDeltaVGGA,fDeltaVGGC);  
252   if (opt.Contains("a")) { // Print all details
253     printf(" - T1: %1.4f, T2: %1.4f \n",fT1,fT2);
254     printf(" - C1: %1.4f, C0: %1.4f \n",fC1,fC0);
255   }    
256
257   if (!fInitLookUp) AliError("Lookup table was not initialized! You should do InitGGVoltErrorDistortion() ...");
258
259   
260 }