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