* provided "as is" without express or implied warranty. *
**************************************************************************/
-//////////////////////////////////////////////////////////////////////////////
-// //
-// AliTPCROCVoltError3D class //
-// The class calculates the space point distortions due to residual voltage //
-// errors on Read Out Chambers of the TPC in 3D. //
-// //
-// The class allows "effective Omega Tau" corrections. //
-// //
-// NOTE: This class is capable of calculating z distortions due to //
-// misalignment and the vd dependency on the residual drift field //
-// //
-// date: 08/08/2010 //
-// Authors: Jim Thomas, Stefan Rossegger //
-// //
-// Example usage : //
-// AliTPCROCVoltError3D ROCerror; //
-//////////////////////////////////////////////////////////////////////////////
+// _________________________________________________________________
+//
+// Begin_Html
+// <h2> AliTPCROCVoltError3D class </h2>
+// The class calculates the space point distortions due to z offsets of the
+// ROCs via the residual voltage technique (Poisson relaxation) in 3D.
+// Since the GG (part of the ROCs) represents the closure of the FC in z direction,
+// every misalignment in z produces not only dz distortions but also electrical
+// field inhomogeneities throughout the volume, which produces additional dr and rd$\phi$ distortions.
+// <p>
+// Each ROC can be misaligned (in z direction) in three ways. A general z0 offset,
+// an inclination along the x and an inclination along the y axis. The z-misalignment's
+// can be set via the function SetROCData(TMatrixD *mat) for each single chamber (ROC).
+// The array size has to be (72,3) representing the 72 chambers according to the
+// offline numbering scheme (IROC: roc$<$36; OROC: roc$\geq$36) and the three misalignment's
+// (see the source code for further details).
+// <p>
+// Internally, these z offsets (unit is cm) are recalculated into residual voltage
+// equivalents in order to make use of the relaxation technique.
+// <p>
+// One has two possibilities when calculating the $dz$ distortions. The resulting
+// distortions are purely due to the change of the drift velocity (along with the
+// change of the drift field) when the SetROCDisplacement is FALSE. <br>
+// For this class, this is a rather unphysical setting and should be avoided. <br>
+// When the flag is set to TRUE, the corresponding offset in z is added to the dz
+// calculation of the outer ROCs. <br>
+// For the Alice TPC gas, both effects are of similar magnitude. This means, if the
+// drift length is sufficiently large, a z-offset of a chamber appears to have (approx.)
+// twice the magnitude when one looks at the actual dz distortions.
+// <p>
+// In addition, this class allows a correction regarding the different arrival times
+// of the electrons due to the geometrical difference of the inner and outer chambers.
+// The impact was simulated via Garfield. If the flag is set via the
+// function SetElectronArrivalCorrection, the electron-arrival correction is added to the dz calculation.
+// End_Html
+//
+// Begin_Macro(source)
+// {
+// gROOT->SetStyle("Plain"); gStyle->SetPalette(1);
+// TCanvas *c2 = new TCanvas("cAliTPCROCVoltError3D","cAliTPCROCVoltError3D",500,400);
+// AliTPCROCVoltError3D roc;
+// roc.SetElectronArrivalCorrection(kFALSE); // Correction for electron arrival offset, IROC vs OROC
+// roc.SetROCDisplacement(kTRUE); // include the chamber offset in z when calculating the dz
+// roc.SetOmegaTauT1T2(0,1,1); // B=0
+// roc.CreateHistoDZinXY(1.,300,300)->Draw("colz");
+// return c2;
+// }
+// End_Macro
+//
+// Begin_Html
+// <p>
+// Date: 08/08/2010 <br>
+// Authors: Jim Thomas, Stefan Rossegger
+// End_Html
+// _________________________________________________________________
+
#include "AliMagF.h"
#include "TGeoGlobalMagField.h"
: AliTPCCorrection("ROCVoltErrors","ROC z alignment Errors"),
fC0(0.),fC1(0.),
fROCdisplacement(kTRUE),
+ fElectronArrivalCorrection(kTRUE),
fInitLookUp(kFALSE),
- fROCDataFileName("$(ALICE_ROOT)/TPC/Calib/maps/TPCROCdzSurvey.root"), // standard file name of ROC survey
+ fROCDataFileName(""),
fdzDataLinFit(0)
{
//
// main input: z alignment of the Read Out chambers
// see InitROCVoltError3D() function
for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
- fLookUpErOverEz[k] = new TMatrixD(kNR,kNZ);
- fLookUpEphiOverEz[k] = new TMatrixD(kNR,kNZ);
- fLookUpDeltaEz[k] = new TMatrixD(kNR,kNZ);
+ fLookUpErOverEz[k] = new TMatrixF(kNR,kNZ);
+ fLookUpEphiOverEz[k] = new TMatrixF(kNR,kNZ);
+ fLookUpDeltaEz[k] = new TMatrixF(kNR,kNZ);
}
-
- SetROCDataFileName(fROCDataFileName); // initialization of fdzDataLinFit is included
+ fROCDataFileName="$ALICE_ROOT/TPC/Calib/maps/TPCROCdzSurvey.root";
+ SetROCDataFileName(fROCDataFileName.Data()); // initialization of fdzDataLinFit is included
}
delete fdzDataLinFit;
}
+void AliTPCROCVoltError3D::SetROCData(TMatrixD * matrix){
+ //
+ // Set a z alignment map of the chambers not via a file, but
+ // directly via a TMatrix(72,3), where dz = p0 + p1*(lx-133.4) + p2*ly (all in cm)
+ //
+ if (!fdzDataLinFit) fdzDataLinFit=new TMatrixD(*matrix);
+ else *fdzDataLinFit = *matrix;
+}
+
+
void AliTPCROCVoltError3D::Init() {
//
// Initialization funtion
// Correction Terms for effective omegaTau; obtained by a laser calibration run
SetOmegaTauT1T2(wt,fT1,fT2);
- InitROCVoltError3D();
+ if (!fInitLookUp) InitROCVoltError3D();
}
void AliTPCROCVoltError3D::Update(const TTimeStamp &/*timeStamp*/) {
}
-void AliTPCROCVoltError3D::SetROCDataFileName(char *const fname) {
+void AliTPCROCVoltError3D::SetROCDataFileName(const char * fname) {
//
// Set / load the ROC data (linear fit of ROC misalignments)
//
fROCDataFileName = fname;
- TFile f(fROCDataFileName,"READ");
+ TFile f(fROCDataFileName.Data(),"READ");
TMatrixD *m = (TMatrixD*) f.Get("dzSurveyLinFitData");
TMatrixD &mf = *m;
//
// Calculates the correction due e.g. residual voltage errors on the TPC boundaries
//
-
+ const Double_t kEpsilon=Double_t(FLT_MIN);
if (!fInitLookUp) {
AliInfo("Lookup table was not initialized! Perform the inizialisation now ...");
InitROCVoltError3D();
- return;
+ }
+ static Bool_t forceInit=kTRUE; //temporary needed for back compatibility with old OCDB entries
+ if (forceInit&&fLookUpErOverEz[0]){
+ if (TMath::Abs(fLookUpErOverEz[0]->Sum())<kEpsilon){//temporary needed for back compatibility with old OCDB entries
+ ForceInitROCVoltError3D();
+ }
+ forceInit=kFALSE;
}
- Int_t order = 1 ; // FIXME: hardcoded? Linear interpolation = 1, Quadratic = 2
+
+ Int_t order = 1 ; // FIXME: hardcoded? Linear interpolation = 1, Quadratic = 2
- Double_t intEr, intEphi, intDeltaEz;
+ Float_t intEr, intEphi, intDeltaEz;
Double_t r, phi, z ;
Int_t sign;
dx[2] = intDeltaEz; // z distortion - (internally scaled with driftvelocity dependency
// on the Ez field plus the actual ROC misalignment (if set TRUE)
+
+ if (fElectronArrivalCorrection) {
+
+ // correction for the OROC (in average, a 0.014usec longer drift time
+ // due to different position of the anode wires) -> vd*dt -> 2.64*0.014 = 0.0369 cm
+ // FIXME: correction are token from Magboltz simulations
+ // should be loaded from a database
+
+ AliTPCROC * rocInfo = AliTPCROC::Instance();
+ Double_t rCrossingROC = (rocInfo->GetPadRowRadii(0,62)+rocInfo->GetPadRowRadii(36,0))/2;
+
+ if (r>rCrossingROC) {
+ if (sign==1)
+ dx[2] += 0.0369; // A side - negative correction
+ else
+ dx[2] -= 0.0369; // C side - positive correction
+ }
+
+ }
+
}
void AliTPCROCVoltError3D::InitROCVoltError3D() {
Float_t phi0 = gridSizePhi * k ;
// To avoid problems at sector boundaries, use an average of +- 1 degree from actual phi location
- if ( j == (kColumns-1) )
+ if ( j == (kColumns-1) ) {
arrayV(i,j) = 0.5* ( GetROCVoltOffset( side, radius0, phi0+0.02 ) + GetROCVoltOffset( side, radius0, phi0-0.02 ) ) ;
+ if (side==1) // C side
+ arrayV(i,j) = -arrayV(i,j); // minus sign on the C side to allow a consistent usage of global z when setting the boundaries
+ }
}
}
for ( Int_t k = 0 ; k < kNPhi ; k++ ) {
phi = fgkPhiList[k] ;
- TMatrixD &erOverEz = *fLookUpErOverEz[k] ;
- TMatrixD &ephiOverEz = *fLookUpEphiOverEz[k];
- TMatrixD &deltaEz = *fLookUpDeltaEz[k] ;
+ TMatrixF &erOverEz = *fLookUpErOverEz[k] ;
+ TMatrixF &ephiOverEz = *fLookUpEphiOverEz[k];
+ TMatrixF &deltaEz = *fLookUpDeltaEz[k] ;
for ( Int_t j = 0 ; j < kNZ ; j++ ) {
if (side==1) roc+=18; // C side
if (r0>132) roc+=36; // OROC
- // linear-plane data: z = z0 + kx*x + ky*y
+ // linear-plane data: z = z0 + kx*lx + ky*ly (rotation in local coordinates)
TMatrixD &fitData = *fdzDataLinFit;
- Float_t dz = fitData(roc,0)+fitData(roc,1)*xp + fitData(roc,2)*yp; // value in cm
+
+ // local coordinates
+ Double_t secAlpha = TMath::DegToRad()*(10.+20.*(((Int_t)roc)%18));
+ Float_t lx = xp*TMath::Cos(secAlpha)+yp*TMath::Sin(secAlpha);
+ Float_t ly = yp*TMath::Cos(secAlpha)-xp*TMath::Sin(secAlpha);
+
+ // reference of rotation in lx is at the intersection between OROC and IROC
+ // necessary, since the Fitprozedure is otherwise useless
+
+ AliTPCROC * rocInfo = AliTPCROC::Instance();
+ Double_t lxRef = (rocInfo->GetPadRowRadii(0,62)+rocInfo->GetPadRowRadii(36,0))/2;
+
+ Float_t dz = fitData(roc,0)+fitData(roc,1)*(lx-lxRef) + fitData(roc,2)*ly; // value in cm
// aproximated Voltage-offset-aquivalent to the z misalignment
// (linearly scaled with the z position)
return voltOff;
}
-TH2F * AliTPCROCVoltError3D::CreateHistoOfZSurvey(Int_t side, Int_t nx, Int_t ny) {
+TH2F * AliTPCROCVoltError3D::CreateHistoOfZAlignment(Int_t side, Int_t nx, Int_t ny) {
//
// return a simple histogramm containing the input to the poisson solver
// (z positions of the Read-out chambers, linearly interpolated)
char hname[100];
- if (side==0) sprintf(hname,"survey_dz_Aside");
- if (side==1) sprintf(hname,"survey_dz_Cside");
+ if (side==0) snprintf(hname,100,"survey_dz_Aside");
+ if (side==1) snprintf(hname,100,"survey_dz_Cside");
TH2F *h = new TH2F(hname,hname,nx,-250.,250.,ny,-250.,250.);
TString opt = option; opt.ToLower();
printf("%s\n",GetTitle());
- printf(" - Voltage settings on the TPC Read-Out chambers - linearly interpolated\n");
- printf(" info: Check the following data-file for more details: %s \n",fROCDataFileName);
+ printf(" - z aligmnet of the TPC Read-Out chambers \n");
+ printf(" (linear interpolation within the chamber: dz = z0 + kx*(lx-133) + ky*ly [cm] ) \n");
+ printf(" Info: Check the following data-file for more details: %s \n",fROCDataFileName.Data());
if (opt.Contains("a")) { // Print all details
+ TMatrixD &fitData = *fdzDataLinFit;
+ printf(" A side: IROC ROCX=(z0,kx,ky): \n");
+ for (Int_t roc = 0; roc<18; roc++)
+ printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
+ printf("\n A side: OROC ROCX=(z0,kx,ky): \n");
+ for (Int_t roc = 36; roc<54; roc++)
+ printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
+ printf("\n C side: IROC ROCX=(z0,kx,ky): \n");
+ for (Int_t roc = 18; roc<36; roc++)
+ printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
+ printf("\n C side: OROC ROCX=(z0,kx,ky): \n");
+ for (Int_t roc = 54; roc<72; roc++)
+ printf("ROC%d:(%.2e,%.2e,%.2e) ",roc,fitData(roc,0),fitData(roc,1),fitData(roc,2));
+ printf("\n\n");
printf(" - T1: %1.4f, T2: %1.4f \n",fT1,fT2);
printf(" - C1: %1.4f, C0: %1.4f \n",fC1,fC0);
}