#include #include "hparticlebtangletrafo.h" ClassImp(HParticleBtAngleTrafo) //_HADES_CLASS_DESCRIPTION ///////////////////////////////////////////////////////////////////////////// // // calculate x,y (xPad,yPad) of a ring center on the Rich Padplane for a given theta and phi // of a lepton track, Phi = 0: middle of the sector, sector edge: +-30° // theta, phi in degree, x,y in mm, xPad, yPad in fraction of a pad // target-center 5 mm downstream of rich-center (the latter normally shifted by about 35 mm upstream) // Some transformations (angles2x, angles2xPad, xy2Phi,xy2yPad, xy2Theta, xy2yPadPad2x, zY2dTheta, zYPad2dTheta) // are inline code implemented in hrichangles2xy.h. Refer to the '.h' file for full set of implemented transformations. // Dependence on vertex position along the beam axis gives correction terms dy, dx or dyPad, dxPad. // dx, dxPad are calculated simultaneously with dy, dyPad but called by special inline functions. // The latter (zTheta2dx(), ztheta2dxPad() need a call to the corresponding functions zTheta2dy(), zTheta2dyPad() before. // To correct for the vertex dependence of the theta, phi to y, x conversion requires to set the Rich Lab position (default -35 mm). // This can be done via 'setRichPos(richLabPos)' function or by specifying a beamtime 'setRichPos("apr12")' // Only Rich alignment for apr12, aug11 and sep08 is implemented by refering to beamtimes. // The inverse Vertex correction deltaTheta calculated from z-vertex and x,y padplane is available as well. // Version 2.0, Nov. 2013, W.Koenig // V2.1: debugged V2.0, zTheta2dTheta added: // correct Rich theta to match Track Theta as function of Vertex , Dec. 2013, W.Koenig // ///////////////////////////////////////////////////////////////////////////// Float_t HParticleBtAngleTrafo::yPhi2yPad(const Float_t y, const Float_t phi) { //Converts y position and phi angle to y pad number Float_t yPad = yPadYPar[0]; Float_t yPower = 1.0F; for (Int_t i=1; i yOffset[0]) { Float_t dy = y - yOffset[0]; yPad += dyPadSlope[1]*phi2*dy*dy; Float_t yOff = yOffset[1] - 0.050*phi2; // yPadYOffset[1]-0.050*phi2 = cos(phi)*yPadYOffset[1] if(y > yOff) { dy = y - yOff; yPad += dyPadSlope[2]*phi2*dy*dy; yOff = yOffset[2] - 0.072*phi2; // yPadYOffset[2]-0.072*phi2 = cos(phi)*yPadYOffset[2] if(y > yOff) { dy = y - yOff; yPad += dyPadSlope[3]*phi2*dy*dy; } } } return yPad; } Float_t HParticleBtAngleTrafo::yPadPhi2y(const Float_t yPad, const Float_t phi) { //Converts y pad number and phi angle to y position Float_t y = yYPadPar[0]; Float_t yPower = 1.0F; for (Int_t i=1; i 0.0F) { y -= 6.85e-6F*dyPad*dyPad*phi2; Float_t y0 = 48.6F*(1.0F - 4.9e-4*phi2); Float_t dy0 = y0 - yPadOffset[2]; dyPad = yPad - y0; y += 7.7e-7F*(dy0*dy0 - dyPad*dyPad)*phi2; } else { y -= 3.5e-6F*dyPad*dyPad*phi2; } return y; } Float_t HParticleBtAngleTrafo::angles2yPad(const Float_t theta, const Float_t phi) { //Convertes theta and phi angle to y pad number Float_t yPad = yPadThetaPar[0]; Float_t thetaPower = 1.0F; for (Int_t i=1; i thetaOffset[1]) { Float_t dTheta = theta-thetaOffset[1]; yPad += ((thetaPadSlope[2]*dTheta+thetaPadSlope[3])*dTheta+phiPadSlope[2])*phi2; if(theta > thetaOffset[2]) { dTheta = theta - thetaOffset[2]; yPad += (thetaPadSlope[4]*dTheta*dTheta)*phi2; } } else { yPad += (phiPadSlope[0] + (thetaPadSlope[0]+thetaPadSlope[5]*theta)*theta)*phi2; } Float_t dPhi = fabs(phi) - phiOffset; if(dPhi>0) yPad -= (phiPadSlope[1] + thetaPadSlope[1]*theta)*dPhi*dPhi; return yPad*cos(phi/rad2deg); } Float_t HParticleBtAngleTrafo::angles2y(const Float_t theta, const Float_t phi) { //Converts theta and phi angle to y position Float_t y = yThetaPar[0]; Float_t thetaPower = 1.0F; for (Int_t i=1; i thetaOffset[0]) { Float_t dTheta = theta-thetaOffset[0]; y += (phiSlope[1] + thetaSlope[1]*dTheta*dTheta)*phi2; } else { y += (phiSlope[0]+thetaSlope[0]*theta)*phi2; } return y*cos(phi/rad2deg); } Float_t HParticleBtAngleTrafo::xPadyPad2Phi(const Float_t xPad, const Float_t yPad) { //Converts x and y pad number to phi angle Float_t x = fabs(xPad2x(xPad)); Float_t y = yPad2y(yPad); Float_t xyRatio = x/y; // tan(8°) = 0.1405 Float_t fac = xyRatio - 0.1405F; // reference fit of xPadPar's at xyRatio = 0.1405 if(fac > 0) { x -= 2.8F*fac*fac; } Float_t dx = x - xyRatio*yOffset[3]; if(dx > 0.0F && xyRatio > 5.0e-4F) { // phi = 0.03 cuttoff: avoid division by nearly zero x += (8.0e-4F + 9.2e-5/xyRatio)*dx*dx*fac; } xyRatio = x/y; if(xPad > xPadOffset) xyRatio *= -1.0F; return atan(xyRatio)*rad2deg; } Float_t HParticleBtAngleTrafo::yPhi2Theta(const Float_t y, const Float_t phi) { //Converts y position and phi angle to theta angle Float_t theta = thetaYPar[0]; Float_t yPower = 1.0F; Float_t yProj = y/cos(phi/rad2deg); for (Int_t i=1; i 0.0F) { theta += yThetaSlope[1]*dy*dy*phi2; dy = yProj - yProjOffset[1]; if(dy > 0.0F) { theta += yThetaSlope[2]*dy*dy*phi2; } } Float_t dPhi = fabs(phi)- phiOffset; if(dPhi>0.0F) theta += (phiThetaSlope[1] + yThetaSlope[3]*yProj)*dPhi*dPhi; return theta; } Float_t HParticleBtAngleTrafo::yPadPhi2Theta(const Float_t yPad, const Float_t phi) { //Converts y pad number and phi angle to theta angle Float_t theta = thetaYPadPar[0]; Float_t yPower = 1.0F; Float_t yProj = yPad/cos(phi/rad2deg); for (Int_t i=1; i0.0F) theta += padThetaSlope[2]*dyPad*dyPad*phi2; } Float_t dPhi = fabs(phi) - phiOffset; if(dPhi>0.0F) theta += phiThetaSlope[4]*dPhi*dPhi; return theta; } Float_t HParticleBtAngleTrafo::zTheta2dY(const Float_t z, const Float_t theta, const Float_t phi) { // calculate deviation of the y position of the ring-center as function of vertex position. // depends on theta but not on phi. Float_t dz = (z - zRef)/zNorm;; Float_t dz2 = dz*dz; Float_t dy = dzPar[0]*dz + dz2Par[0]*dz2; Float_t theta0 = theta - thetaRef; Float_t thetaPower = 1.0F; for (Int_t n=1; n 0.0F) dxPadVertex -= 4.330e-9*theta0*theta0*theta0*phi2dz; if (dz > 0.0F) { if(absPhi > 16.0F) absPhi = 32.0F - absPhi; dxPadVertex += (4.72e-4 + 2.08e-5*theta0)*absPhi*dz; } if(phi < 0) dxPadVertex = -dxPadVertex; return dyPad*cos(phi0); } Float_t HParticleBtAngleTrafo::zYPhi2dTheta(const Float_t z, const Float_t y, const Float_t phi) { //Calculates theta correction for different vertices //for y position and phi angle as input Float_t dz = (z - zRef)/zNorm;; Float_t dz2 = dz*dz; Float_t dTheta = dzYPar[0]*dz + dz2YPar[0]*dz2; Float_t cosPhi = cos(phi/rad2deg); Float_t y0 = (y - yRef)/cosPhi; Float_t yPower = 1.0F; for (Int_t n=1; n yOffset[4]) { Float_t dyPhi = (y-yOffset[4])/cosPhi*phi; dTheta += 1.72e-8F*dyPhi*dyPhi*dz; } } else { dTheta -= 1.41e-4F*phi*phi*dz; if (y > yOffset[5]) { Float_t dyPhi = (y-yOffset[5])/cosPhi*phi; dTheta += 2.25e-8F*dyPhi*dyPhi*dz; } } return -dTheta; } Float_t HParticleBtAngleTrafo::zTheta2dTheta(const Float_t z, const Float_t theta, const Float_t phi) { //Calculates theta correction for different vertices //for theta and phi angle as input Float_t dz = (z - zRef)/zNorm;; Float_t dz2 = dz*dz; Float_t theta0 = theta - thetaRef; Float_t dTheta = dzThetaPar[0]*dz + dz2ThetaPar[0]*dz2; Float_t thetaPower = 1.0F; for (Int_t n=1; nyPad thetaSlope[0] =-9.0e-6F; thetaSlope[1] = 6.2e-6F; phiSlope[0] = -0.00265; phiSlope[1] = phiSlope[0]+thetaOffset[0]*thetaSlope[0]; phiPadSlope[0] = -0.00156; //for theta, phi to yPad phiPadSlope[1] = 0.00033; phiPadSlope[2] = phiPadSlope[0] + (thetaPadSlope[0]+thetaPadSlope[5]*thetaOffset[1])*thetaOffset[1]; phiPadSlope[3] = -8.2e-5F; // for y to yPad } yOffset[0] = 190.0F; // used for y,phi -> yPad yOffset[1] = 350.0F; // used for y,phi -> yPad yOffset[2] = 470.0F; // used for y,phi -> yPad yOffset[3] = 234.7F; // used for xPad,yPad -> phi; yOffset[4] = 300.0F; // used for z,Y -> deltaTheta (vertex correction) yOffset[5] = 325.0F; // used for z,Y -> deltaTheta (vertex correction) xPadSize = 6.6F; xPadOffset = 47.5F; yProjOffset[0] =350.0F; // startpoints of y,phi**2 dependend theta correction yProjOffset[1] =500.0F; yPadOffset[0] = 40.0F; // startpoints of yPad,phi**2 dependend theta correction yPadOffset[1] = 64.5F; yPadOffset[2] = 18.0F; // yPad, phi -> y , (yPad-offset)**2 * phi**2 correction yThetaSlope[0] = 6.4e-7; yThetaSlope[1] = -1.57e-8F; // parametrisation to calculate theta from y yThetaSlope[2] = -6.125e-8F; yThetaSlope[3] = -9.01e-7F; padThetaSlope[0] = 1.188e-5F; // parametrisation to calculate theta from yPad padThetaSlope[1] = -1.191e-6F; padThetaSlope[2] = -2.05e-6F; phiThetaSlope[0] = 0.000214; // phi**2 dependent correction of theta calculated from y,yPad phiThetaSlope[1] = 0.000335; phiThetaSlope[2] = 0.00159; phiThetaSlope[3] = padThetaSlope[0] * yPadOffset[0]; phiThetaSlope[4] = 0.00059; { // Parametrization of vertex dependance at zVertex - zRichCenter = +-20 mm as function of theta const Float_t dzParam[zParMax] = {5.6788,0.0958689,-0.00465984,-0.000112338,3.45014e-7,2.29705e-8}; for (Int_t n=0; n