LCOV - code coverage report
Current view: top level - TPC/TPCbase - AliTPCROCVoltError3D.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 247 0.4 %
Date: 2016-06-14 17:26:59 Functions: 1 16 6.2 %

          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             : /// ![Picture from ROOT macro](AliTPCROCVoltError3D_cxx_99b6733.png)
      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 : }

Generated by: LCOV version 1.11