#include "hmdckickcor.h" ClassImp(HMdcKickCor) // author: W. Koenig, creation date: Aug 2013, version 3 // use parameters to calculate position correction in outer MDC from displacement rKick perpendicular // to wires in a given layer (nLayer). rKick is measured with respect to a straight line trajectoriy. // parameters were calculated on a grid in theta phi of inner segment. // Linear interpolation of parameters (6 parameter polynomial fit) is used. // Done for all layers of outer MDC's. Reference hit point is middle of MDC plane III. // All coordinates in Mdc coordinate system (ideal aligment: x=0, phi=0 is center of sector). // Only differences between point coordinates are used, alignment drops out in first order. // Grid points in theta and phi (inner segment). // Parameters were obtained from GEANT simulation for momenta between 90 MeV/c 3 GeV/c // No multiple scattering nor energy loss activated. // parameters calculated for high field setting (3200A, 92.235% of max field). // mdc = 2 (plane III), = 3 (plane IV). void HMdcKickCor::interpolateAngles(const Float_t thetaRad, const Float_t phiRad) { // thetaRad,phiRad - in sector coor. system Float_t theta = thetaRad*TMath::RadToDeg(); Float_t phi = 90. - phiRad*TMath::RadToDeg(); Float_t absPhi = TMath::Abs(phi); indexOffset = phi < 0. ? 2:0; iPhi=1; while (absPhi > phiPar[iPhi] && iPhi < iPhiMax-1) ++iPhi; nTheta=1; while (theta > thetaPar[nTheta] && nTheta < nThetaMax-1) ++nTheta; dThetaPar = thetaPar[nTheta]-thetaPar[nTheta-1]; dThetaLow = theta-thetaPar[nTheta-1]; dThetaHigh = thetaPar[nTheta]-theta; for (Int_t k=0; k<2; ++k) { Int_t j=iPhi-k; tmpPhiPar[k] = (phiPar[j]*dThetaLow + phiPar[j]*dThetaHigh)/dThetaPar; } dPhiPar = tmpPhiPar[0]-tmpPhiPar[1]; dPhiLow = absPhi-tmpPhiPar[1]; dPhiHigh = tmpPhiPar[0]-absPhi; } Float_t HMdcKickCor::calcCorrection(Float_t rKick, const Int_t mdc, const Int_t layerNo) { if(mdc<2 || mdc>3) return 0.; Int_t nMdc = (mdc&1) + indexOffset; // indexOffset: left or right half of MDC Float_t shift, powRKick; if((layerNo==0 && indexOffset==0)||(layerNo==5 && indexOffset==2)) { if(rKick < 0.0 && iPhi>6 && nTheta>3) { Float_t rMax0 = -(rMaxPar[iPhi-6][nTheta-3][nMdc]*dThetaLow + rMaxPar[iPhi-6][nTheta-4][nMdc]*dThetaHigh)/dThetaPar; Float_t rMax1 = -(rMaxPar[iPhi-7][nTheta-3][nMdc]*dThetaLow + rMaxPar[iPhi-7][nTheta-4][nMdc]*dThetaHigh)/dThetaPar; Float_t rMax = (rMax0*dPhiLow + rMax1*dPhiHigh)/dPhiPar; if(rKick < rMax) rKick = rMax; // rKick < 0 ! } } for (Int_t nPar=0; nPar < parMax; ++nPar) { for (Int_t k=0; k<2; ++k) { Int_t j=iPhi-k; if(rKick < 0.0) { tmpKickPar[k] = (drParPos[nMdc][layerNo][nPar][j][nTheta]*dThetaLow + drParPos[nMdc][layerNo][nPar][j][nTheta-1]*dThetaHigh)/dThetaPar; } else { tmpKickPar[k] = (drParNeg[nMdc][layerNo][nPar][j][nTheta]*dThetaLow + drParNeg[nMdc][layerNo][nPar][j][nTheta-1]*dThetaHigh)/dThetaPar; } } par[nPar] = (tmpKickPar[0]*dPhiLow + tmpKickPar[1]*dPhiHigh)/dPhiPar; } shift = par[0]; powRKick=1.0F; for (Int_t nPar=1; nPar < parMax; ++nPar) { powRKick *= rKick; shift += par[nPar]*powRKick; } return shift; } // initParam copies all the parameter arrays from an initialization set instantiated in this routine to the arrays // defined in the header file. The helper array allows to set values of multi dimensional arrays in an efficient way. // Should or could be replaced by a parameter container. It is a workaround. void HMdcKickCor::initParam() { { const Double_t yMdc[4] = {392.354,585.842,1040.677,1267.451}; const Double_t zMdc[4] = {380.529,425.723,920.253,1116.645}; const Double_t thetaMdc[4] = {44.196,53.995,49.107,49.107}; for (Int_t n=0; n<4; ++n) { y0Mdc[n]=yMdc[n]; z0Mdc[n]=zMdc[n]; theta0Mdc[n]=thetaMdc[n]; } const Float_t thPar[nThetaMax] = {20,24,28,36,44,52,60,68,76,80}; for (Int_t n=0; n