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