#include #include "CbmGeaneUtil.h" #include "TGeoTorus.h" #include "TMath.h" using namespace std; CbmGeaneUtil::CbmGeaneUtil() { } CbmGeaneUtil::~CbmGeaneUtil() { } void CbmGeaneUtil::FromPtToSC(Double_t PC[], Double_t RC[], // output Double_t PD[], Double_t RD[], Int_t &IERR) { // ------------------------------------------------------------- // // TRANSFORM ERROR MATRIX // // FROM SC VARIABLES (1/Pt,LAMBDA,PHI,YT,ZT) // FROM SC VARIABLES (1/P,LAMBDA,PHI,YT,ZT) // // INPUT // PC[3] (1/Pt, Lambda, Phi, Yt, Zt) // RC[15] error matrix in upper triangular form // // OUTPUT // PD[3] (1/P, Lambda, Phi, Yt, Zt) // RD[15] error matrix in upper triangular form // IERR =1 when track is perp to X-axis of Master // // Author EMC Collaboration // Translated in C/Rot by A. Rotondi (June 2007) // // ------------------------------------------------------------------- Double_t A[5][5], S[15], COSL, SINL; Double_t Vec[25]; IERR = 0; memset(RD,0,sizeof(RD)); COSL = cos(PC[1]); if(TMath::Abs(COSL) < 1.e-7) { IERR =1; return; } SINL = sin(PC[1]); PD[0] = PC[0]*COSL; PD[1] = PC[1]; PD[2] = PC[2]; for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } // copy input in an internal vector S for(Int_t I=0; I<15; I++) S[I]=RC[I]; A[0][0] = COSL; A[1][1] = 1.0; A[2][2] = 1.0; A[3][3] = 1.0; A[4][4] = 1.0; A[0][1] = -PC[0]*SINL; // transformation FromMatToVec(A,Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RD[I]=S[I]; } void CbmGeaneUtil::FromPtToSD(Double_t PD[], Double_t RD[], Double_t H[], Double_t CH, Double_t SPU, Double_t DJ[], Double_t DK[], // output Int_t &IERR, Double_t PC[], Double_t RC[]) { // // ************************************************************************** // // *** TRANSFORMS ERROR MATRIX // FROM VARIABLES (1/Pt,V',W',V,W) // FROM VARIABLES (1/P, V',W',V,W) // // input // PD[3] (1/P, Lambda, Phi, Yt, Zt) // RD[15] error matrix in upper triangular form // H[3] magnetic field // CH CHARGE OF PARTICLE // CHARGE AND MAGNETIC FIELD ARE NEEDED // FOR CORRELATION TERMS (V',YT),(V',ZT),(W',YT),(W',ZT) // THESE CORRELATION TERMS APPEAR BECAUSE RC IS ASSUMED // TO BE THE ERROR MATRIX FOR FIXED S (PATH LENGTH) // AND RD FOR FIXED U // SPU SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // spu = sign[p·(DJ x DK)] // DJ[2] UNIT VECTOR IN V-DIRECTION // DK[2] UNIT VECTOR IN W-DIRECTION OF DETECTOR SYSTEM // // output // PC[3] (1/Pt, Lambda, Phi, Yt, Zt) // RC[15] error matrix in upper triangular form // IERR =1 when track is perp to X-axis of Master // // Author EMC Collaboration // Translated in C/Rot by A. Rotondi (June 2007) // // ------------------------------------------------------------------- // Double_t A[5][5], S[15], TN[3], COSL, SINL, COSL1; Double_t PM, HM, UN[3], VN[3], DI[3], TVW[3]; Double_t UJ, UK, VJ, VK, HA, HAM, Q, SINZ, COSZ; Double_t CFACT8 = 2.997925e-04; Double_t Vec[25]; // ------------------------------------------------------------------ IERR=0; TVW[0]=1./TMath::Sqrt(1.+PD[1]*PD[1]+PD[2]*PD[2]); if(SPU < 0.) TVW[0]=-TVW[0]; TVW[1]=PD[1]*TVW[0]; TVW[2]=PD[2]*TVW[0]; DI[0]=DJ[1]*DK[2]-DJ[2]*DK[1]; DI[1]=DJ[2]*DK[0]-DJ[0]*DK[2]; DI[2]=DJ[0]*DK[1]-DJ[1]*DK[0]; for(Int_t I=0; I<3; I++) { TN[I]=TVW[0]*DI[I]+TVW[1]*DJ[I]+TVW[2]*DK[I]; } COSL=TMath::Sqrt(TMath::Abs(1.-TN[2]*TN[2])); if(COSL < 1.e-30) COSL = 1.e-30; COSL1=1./COSL; SINL = TN[2]; PC[0]=PD[0]*COSL; PC[1]=PD[1]; PC[2]=PD[2]; PM=PC[0]; if(TMath::Abs (TN[0]) < 1.E-30) TN[0] = 1.e-30; UN[0]=-TN[1]*COSL1; UN[1]=TN[0]*COSL1; UN[2]=0.; VN[0]=-TN[2]*UN[1]; VN[1]=TN[2]*UN[0]; VN[2]=COSL; UJ=UN[0]*DJ[0]+UN[1]*DJ[1]+UN[2]*DJ[2]; UK=UN[0]*DK[0]+UN[1]*DK[1]+UN[2]*DK[2]; VJ=VN[0]*DJ[0]+VN[1]*DJ[1]+VN[2]*DJ[2]; VK=VN[0]*DK[0]+VN[1]*DK[1]+VN[2]*DK[2]; for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } // copy input in an internal vector S for(Int_t I=0; I<15; I++) S[I]=RD[I]; if(CH != 0.) { HA=TMath::Sqrt(H[0]*H[0]+H[1]*H[1]+H[2]*H[2]); HAM=HA*PM; if(HAM != 0.) { HM=CH/HA; Q=-HAM*CFACT8; SINZ=-(H[0]*UN[0]+H[1]*UN[1]+H[2]*UN[2])*HM; COSZ= (H[0]*VN[0]+H[1]*VN[1]+H[2]*VN[2])*HM; A[0][3] = Q*TVW[1]*SINZ*(SINL*PD[0]); A[0][4] = Q*TVW[2]*SINZ*(SINL*PD[0]); } } A[0][0] = COSL; A[1][1] = 1.; A[2][2] = 1.; A[3][3] = 1.; A[4][4] = 1.; A[0][1] = -TVW[0]*VJ*(SINL*PD[0]); A[0][2] = -TVW[0]*VK*(SINL*PD[0]); // transformation FromMatToVec(A,Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RC[I]=S[I]; } void CbmGeaneUtil::FromSCToPt(Double_t PC[], Double_t RC[], // output Double_t PD[], Double_t RD[], Int_t &IERR) { // ------------------------------------------------------------- // // TRANSFORM ERROR MATRIX // // FROM SC VARIABLES (1/P,LAMBDA,PHI,YT,ZT) // FROM SC VARIABLES (1/Pt,LAMBDA,PHI,YT,ZT) // // INPUT // PC[3] (1/P, Lambda, Phi, Yt, Zt) // RC[15] error matrix in upper triangular form // // OUTPUT // PD[3] (1/Pt, Lambda, Phi, Yt, Zt) // RD[15] error matrix in upper triangular form // IERR =1 when track is perp to X-axis of Master // // Author EMC Collaboration // Translated in C/Rot by A. Rotondi (June 2007) // // ------------------------------------------------------------------- Double_t A[5][5], S[15], COSL, COSL1; Double_t TANL; Double_t Vec[25]; IERR = 0; memset(RD,0,sizeof(RD)); COSL = cos(PC[1]); if(TMath::Abs(COSL) < 1.e-7) { IERR = 1; return; } COSL1 = 1./COSL; TANL = tan(PC[1]); PD[0] = PC[0]*COSL1; PD[1] = PC[1]; PD[2] = PC[2]; for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } // copy input in an internal vector S for(Int_t I=0; I<15; I++) S[I]=RC[I]; A[0][0] = COSL1; A[1][1] = 1.0; A[2][2] = 1.0; A[3][3] = 1.0; A[4][4] = 1.0; A[0][1] = PD[0]*TANL; // transformation FromMatToVec(A,Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RD[I]=S[I]; } void CbmGeaneUtil::FromSCToSD(Double_t PC[], Double_t RC[], Double_t H[], Double_t CH, Double_t DJ[], Double_t DK[], // output Int_t &IERR, Double_t &SPU, Double_t PD[], Double_t RD[]) { // ---------------------------------------------------------------------- // Transform Error Matrix // FROM SC (transverse system) VARIABLES (1/P,LAMBDA,PHI,YT,ZT) // TO SD (detector system) VARIABLES (1/P,V',W',V,W) // Authors: A. Haas and W. Wittek // Translated in CRoot by A. Rotondi and A. Fontana June 2007 // INPUT // PC(3) 1/P,LAMBDA,PHI // H(3) MAGNETIC FIELD // RC(15) ERROR MATRIX IN SC VARIABLES (TRIANGLE) // CH CHARGE OF PARTICLE // CHARGE AND MAGNETIC FIELD ARE NEEDED // FOR CORRELATION TERMS (V',YT),(V',ZT),(W',YT),(W',ZT) // THESE CORRELATION TERMS APPEAR BECAUSE RC IS ASSUMED // TO BE THE ERROR MATRIX FOR FIXED S (PATH LENGTH) // AND RD FOR FIXED U // DJ(3) UNIT VECTOR IN V-DIRECTION // DK(3) UNIT VECTOR IN W-DIRECTION OF DETECTOR SYSTEM // OUTPUT // RD(15) ERROR MATRIX IN 1/P,V',W',V,W (TRIANGLE) // PD(3) 1/P,V',W' // IERR = 1 PARTICLE MOVES PERPENDICULAR TO U-AXIS // ( V',W' ARE NOT DEFINED ) // SPU SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // spu = sign[p·(DJ x DK)] // // ------------------------------------------------------------------------ Double_t A[5][5], S[15], TN[3], COSL, COSP; Double_t UN[3], VN[3], DI[3], TVW[3]; Double_t Vec[25]; Double_t CFACT8= 2.997925e-04; Double_t T1R, T2R, T3R, SINP, SINZ, COSZ, HA, HM, HAM; Double_t Q, UI, VI, UJ, UK, VJ, VK; IERR=0; memset(RD,0,sizeof(RD)); memset(PD,0,sizeof(PD)); COSL=TMath::Cos(PC[1]); SINP=TMath::Sin(PC[2]); COSP=TMath::Cos(PC[2]); TN[0]=COSL*COSP; TN[1]=COSL*SINP; TN[2]=TMath::Sin(PC[1]); // DI = DJ x DK DI[0]=DJ[1]*DK[2]-DJ[2]*DK[1]; DI[1]=DJ[2]*DK[0]-DJ[0]*DK[2]; DI[2]=DJ[0]*DK[1]-DJ[1]*DK[0]; TVW[0]=TN[0]*DI[0]+TN[1]*DI[1]+TN[2]*DI[2]; SPU=1.; if(TVW[0] < 0.) SPU=-1.; TVW[1]=TN[0]*DJ[0]+TN[1]*DJ[1]+TN[2]*DJ[2]; TVW[2]=TN[0]*DK[0]+TN[1]*DK[1]+TN[2]*DK[2]; // track lies in the detector plane: stop calculations if(TMath::Abs(TVW[0]) < 1.e-7) { IERR = 1; return; } T1R=1./TVW[0]; PD[0] = PC[0]; PD[1] = TVW[1]*T1R; PD[2] = TVW[2]*T1R; UN[0] = -SINP; UN[1] = COSP; UN[2] = 0.; VN[0] =-TN[2]*UN[1]; VN[1] = TN[2]*UN[0]; VN[2] = COSL; UJ=UN[0]*DJ[0]+UN[1]*DJ[1]+UN[2]*DJ[2]; UK=UN[0]*DK[0]+UN[1]*DK[1]+UN[2]*DK[2]; VJ=VN[0]*DJ[0]+VN[1]*DJ[1]+VN[2]*DJ[2]; VK=VN[0]*DK[0]+VN[1]*DK[1]+VN[2]*DK[2]; for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } // copy input in an internal vector S for(Int_t I=0; I<15; I++) S[I]=RC[I]; if(CH != 0.) { //charged particles HA=TMath::Sqrt(H[0]*H[0]+H[1]*H[1]+H[2]*H[2]); HAM=HA*PC[0]; if(HAM != 0.) { // ... in a magnetic field HM=CH/HA; Q=-HAM*CFACT8; SINZ=-(H[0]*UN[0]+H[1]*UN[1]+H[2]*UN[2])*HM; COSZ= (H[0]*VN[0]+H[1]*VN[1]+H[2]*VN[2])*HM; T3R=Q*pow(T1R,3); UI=UN[0]*DI[0]+UN[1]*DI[1]+UN[2]*DI[2]; VI=VN[0]*DI[0]+VN[1]*DI[1]+VN[2]*DI[2]; A[1][3] = -UI*(VK*COSZ-UK*SINZ)*T3R; A[1][4] = -VI*(VK*COSZ-UK*SINZ)*T3R; A[2][3] = UI*(VJ*COSZ-UJ*SINZ)*T3R; A[2][4] = VI*(VJ*COSZ-UJ*SINZ)*T3R; } } T2R=T1R*T1R; // Transformation matrix from SC to SD A[0][0] = 1.; A[1][1] = -UK*T2R; A[1][2] = VK*COSL*T2R; A[2][1] = UJ*T2R; A[2][2] = -VJ*COSL*T2R; A[3][3] = VK*T1R; A[3][4] = -UK*T1R; A[4][3] = -VJ*T1R; A[4][4] = UJ*T1R; // transformation FromMatToVec(A,Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RD[I]=S[I]; } void CbmGeaneUtil::FromSD1ToSD2(Double_t PD1[], Double_t RD1[],Double_t H[], Double_t CH, Double_t SP1, Double_t DJ1[], Double_t DK1[], Double_t DJ2[], Double_t DK2[], // output Int_t &IERR, Double_t &SP2, Double_t PD2[], Double_t RD2[]) { // ------------------------------------------------------------------------- // // TRANSFORMS ERROR MATRIX // FROM VARIABLES (1/P,V1',W1',V1,W1) // TO VARIABLES (1/P,V2',W2',V2,W2) // // Authors: A. Haas and W. Wittek // Translated in C/Root by A. Fontana and A. Rotondi (June 2007) // // // INPUT // PD1[2] 1/P,V1',W1' // H[2] MAGNETIC FIELD // RD1(15) ERROR MATRIX IN 1/P,V1',W1',V1,W1 (Triangular) // CH CHARGE OF PARTICLE // CHARGE AND MAGNETIC FIELD ARE NEEDED // FOR CORRELATION TERMS (V2',V1),(V2',W1),(W2',V1),(W2',W1) // THESE CORRELATION TERMS APPEAR BECAUSE RD1 IS ASSUMED // TO BE THE ERROR MATRIX FOR FIXED U1 // AND RD2 FOR FIXED U2 // SP1 SIGN OF U1-COMPONENT OF PARTICLE MOMENTUM INPUT // DJ1[2] UNIT VECTOR IN V1-DIRECTION // DK1[2] UNIT VECTOR IN W1-DIRECTION OF SYSTEM 1 // DJ2[2] UNIT VECTOR IN V2-DIRECTION // DK2[2] UNIT VECTOR IN W2-DIRECTION OF SYSTEM 2 // // // OUTPUT // PD2[3] 1/P,V2',W2' // RD2[15] ERROR MATRIX IN 1/P,V2',W2',V2,W2 (Triangular) // SP2 SIGN OF U2-COMPONENT OF PARTICLE MOMENTUM OUTPUT // IERR = 0 TRANSFORMATION OK // = 1 MOMENTUM PERPENDICULAR TO U2-DIRECTION // (V2',W2' NOT DEFINed) // = 2 MOMENTUM PERPENDICULAR TO X-AXIS // // ---------------------------------------------------------------------- Double_t A[5][5], S[15], TN[3], COSL, COSL1; Double_t SINZ, COSZ, UN[3], VN[3]; Double_t Vec[25]; Double_t PM, TR, TS, TT, HA, HM, HAM, Q; Double_t UJ1, UK1, UJ2, UK2, VJ1, VJ2, VK1, VK2; Double_t SJ1I2, SK1I2, SK2U, SK2V, SJ2U, SJ2V; Double_t DI1[3], DI2[3], TVW1[3], TVW2[3]; Double_t CFACT8= 2.997925e-04; IERR=0; memset(PD2,0,sizeof(PD2)); memset(RD2,0,sizeof(RD2)); PM=PD1[0]; TVW1[0]=1./sqrt(1.+PD1[1]*PD1[1]+PD1[2]*PD1[2]); if(SP1 < 0.) TVW1[0]=-TVW1[0]; TVW1[1]=PD1[1]*TVW1[0]; TVW1[2]=PD1[2]*TVW1[0]; DI1[0]=DJ1[1]*DK1[2]-DJ1[2]*DK1[1]; DI1[1]=DJ1[2]*DK1[0]-DJ1[0]*DK1[2]; DI1[2]=DJ1[0]*DK1[1]-DJ1[1]*DK1[0]; for(Int_t I=0; I<3; I++) { TN[I]=TVW1[0]*DI1[I]+TVW1[1]*DJ1[I]+TVW1[2]*DK1[I]; } DI2[0]=DJ2[1]*DK2[2]-DJ2[2]*DK2[1]; DI2[1]=DJ2[2]*DK2[0]-DJ2[0]*DK2[2]; DI2[2]=DJ2[0]*DK2[1]-DJ2[1]*DK2[0]; TVW2[0]=TN[0]*DI2[0]+TN[1]*DI2[1]+TN[2]*DI2[2]; TVW2[1]=TN[0]*DJ2[0]+TN[1]*DJ2[1]+TN[2]*DJ2[2]; TVW2[2]=TN[0]*DK2[0]+TN[1]*DK2[1]+TN[2]*DK2[2]; if(TMath::Abs(TVW2[0]) < 1.e-7) { // track lies in the v-w plane: stop calculations IERR = 1; return; } TR=1./TVW2[0]; SP2=1; if(TVW2[0] < 0.) SP2=-1; PD2[0]=PD1[0]; PD2[1]=TVW2[1]*TR; PD2[2]=TVW2[2]*TR; COSL=sqrt(TMath::Abs(1.-TN[2]*TN[2])); if(TMath::Abs(COSL) < 1.e-7) { // track perp to X-axis of Master: stop calculations IERR=2; return; } COSL1=1./COSL; UN[0]=-TN[1]*COSL1; UN[1]=TN[0]*COSL1; UN[2]=0.; VN[0]=-TN[2]*UN[1]; VN[1]=TN[2]*UN[0]; VN[2]=COSL; UJ1=UN[0]*DJ1[0]+UN[1]*DJ1[1]+UN[2]*DJ1[2]; UK1=UN[0]*DK1[0]+UN[1]*DK1[1]+UN[2]*DK1[2]; VJ1=VN[0]*DJ1[0]+VN[1]*DJ1[1]+VN[2]*DJ1[2]; VK1=VN[0]*DK1[0]+VN[1]*DK1[1]+VN[2]*DK1[2]; UJ2=UN[0]*DJ2[0]+UN[1]*DJ2[1]+UN[2]*DJ2[2]; UK2=UN[0]*DK2[0]+UN[1]*DK2[1]+UN[2]*DK2[2]; VJ2=VN[0]*DJ2[0]+VN[1]*DJ2[1]+VN[2]*DJ2[2]; VK2=VN[0]*DK2[0]+VN[1]*DK2[1]+VN[2]*DK2[2]; // reset working vectors and matrices for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } for(Int_t J=0; J<15; J++) S[J]=RD1[J]; if(CH != 0.) { // a charged particle HA=sqrt(H[0]*H[0]+H[1]*H[1]+H[2]*H[2]); HAM=HA*PM; if(HAM != 0.) { // ...in a magnetic field HM=CH/HA; Q=-HAM*CFACT8; TT=-Q*pow(TR,3); SJ1I2=DJ1[0]*DI2[0]+DJ1[1]*DI2[1]+DJ1[2]*DI2[2]; SK1I2=DK1[0]*DI2[0]+DK1[1]*DI2[1]+DK1[2]*DI2[2]; SK2U=DK2[0]*UN[0]+DK2[1]*UN[1]+DK2[2]*UN[2]; SK2V=DK2[0]*VN[0]+DK2[1]*VN[1]+DK2[2]*VN[2]; SJ2U=DJ2[0]*UN[0]+DJ2[1]*UN[1]+DJ2[2]*UN[2]; SJ2V=DJ2[0]*VN[0]+DJ2[1]*VN[1]+DJ2[2]*VN[2]; SINZ=-(H[0]*UN[0]+H[1]*UN[1]+H[2]*UN[2])*HM; COSZ= (H[0]*VN[0]+H[1]*VN[1]+H[2]*VN[2])*HM; A[1][3] = -TT*SJ1I2*(SK2U*SINZ-SK2V*COSZ); A[1][4] = -TT*SK1I2*(SK2U*SINZ-SK2V*COSZ); A[2][3] = TT*SJ1I2*(SJ2U*SINZ-SJ2V*COSZ); A[2][4] = TT*SK1I2*(SJ2U*SINZ-SJ2V*COSZ); } } A[0][0] = 1.; A[3][3] = TR*(UJ1*VK2-VJ1*UK2); A[3][4] = TR*(UK1*VK2-VK1*UK2); A[4][3] = TR*(VJ1*UJ2-UJ1*VJ2); A[4][4] = TR*(VK1*UJ2-UK1*VJ2); TS=TR*TVW1[0]; A[1][1] = A[3][3]*TS; A[1][2] = A[3][4]*TS; A[2][1] = A[4][3]*TS; A[2][2] = A[4][4]*TS; // transformation A*SA FromMatToVec(A,Vec); SymmProd(Vec,S,S); // final error (covariance) matrix in upper-triangular form for(Int_t J=0; J<15; J++) RD2[J]=S[J]; } void CbmGeaneUtil::FromSDToPt(Double_t PD[], Double_t RD[], Double_t H[], Double_t CH, Double_t SPU, Double_t DJ[], Double_t DK[], // output Int_t &IERR, Double_t PC[], Double_t RC[]) { // // ------------------------------------------------------------- // // TRANSFORM ERROR MATRIX // FROM VARIABLES (1/P,V',W',V,W) // FROM VARIABLES (1/Pt,V',W',V,W) // // input // PD[3] (1/P, Lambda, Phi, Yt, Zt) // RD[15] error matrix in upper triangular form // H[3] magnetic field // CH CHARGE OF PARTICLE // CHARGE AND MAGNETIC FIELD ARE NEEDED // FOR CORRELATION TERMS (V',YT),(V',ZT),(W',YT),(W',ZT) // THESE CORRELATION TERMS APPEAR BECAUSE RC IS ASSUMED // TO BE THE ERROR MATRIX FOR FIXED S (PATH LENGTH) // AND RD FOR FIXED U // SPU SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // spu = sign[p·(DJ x DK)] // DJ(3) UNIT VECTOR IN V-DIRECTION // DK(3) UNIT VECTOR IN W-DIRECTION OF DETECTOR SYSTEM // // output // PC[3] (1/Pt, Lambda, Phi, Yt, Zt) // RC[15] error matrix in upper triangular form // IERR =1 when track is perp to X-axis of Master // // Author EMC Collaboration // Translated in C/Rot by A. Rotondi (June 2007) // // ------------------------------------------------------------------- // // // Double_t A[5][5], S[15], TN[3], TANL, COSL, COSL1; Double_t PM, HM, UN[3], VN[3], DI[3], TVW[3]; Double_t CFACT8 = 2.997925e-04; Double_t UJ, UK, VJ, VK, HA, HAM, Q, SINZ, COSZ; Double_t Vec[25]; // ------------------------------------------------------------------ IERR=0; PM=PD[0]; TVW[0]=1./TMath::Sqrt(1.+PD[1]*PD[1]+PD[2]*PD[2]); if(SPU<0.)TVW[0]=-TVW[0]; TVW[1]=PD[1]*TVW[0]; TVW[2]=PD[2]*TVW[0]; DI[0]=DJ[1]*DK[2]-DJ[2]*DK[1]; DI[1]=DJ[2]*DK[0]-DJ[0]*DK[2]; DI[2]=DJ[0]*DK[1]-DJ[1]*DK[0]; for(Int_t I=0; I<3; I++) { TN[I]=TVW[0]*DI[I]+TVW[1]*DJ[I]+TVW[2]*DK[I]; } COSL=TMath::Sqrt(TMath::Abs(1.-TN[2]*TN[2])); if(COSL < 1.e-30) COSL = 1.e-30; COSL1=1./COSL; TANL = TN[2]*COSL1; PC[0]=PD[0]*COSL1; PC[1]=PD[1]; PC[2]=PD[2]; if(TMath::Abs (TN[0])< 1.e-30) TN[0] = 1.e-30; UN[0]=-TN[1]*COSL1; UN[1]=TN[0]*COSL1; UN[2]=0.; VN[0]=-TN[2]*UN[1]; VN[1]=TN[2]*UN[0]; VN[2]=COSL; UJ=UN[0]*DJ[0]+UN[1]*DJ[1]+UN[2]*DJ[2]; UK=UN[0]*DK[0]+UN[1]*DK[1]+UN[2]*DK[2]; VJ=VN[0]*DJ[0]+VN[1]*DJ[1]+VN[2]*DJ[2]; VK=VN[0]*DK[0]+VN[1]*DK[1]+VN[2]*DK[2]; for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } // copy input in an internal vector S for(Int_t I=0; I<15; I++) S[I]=RD[I]; if(CH != 0.) { HA=TMath::Sqrt(H[0]*H[0]+H[1]*H[1]+H[2]*H[2]); HAM=HA*PM; if(HAM != 0.) { HM=CH/HA; Q=-HAM*CFACT8; SINZ=-(H[0]*UN[0]+H[1]*UN[1]+H[2]*UN[2])*HM; COSZ= (H[0]*VN[0]+H[1]*VN[1]+H[2]*VN[2])*HM; A[0][3] = -Q*TVW[1]*SINZ*(TANL*PC[0]); A[0][4] = -Q*TVW[2]*SINZ*(TANL*PC[0]); } } A[0][0] = COSL1; A[1][1] = 1.; A[2][2] = 1.; A[3][3] = 1.; A[4][4] = 1.; A[0][1] = TVW[0]*VJ*(TANL*PC[0]); A[0][2] = TVW[0]*VK*(TANL*PC[0]); // transformation FromMatToVec(A,Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RC[I]=S[I]; } void CbmGeaneUtil::FromSDToSC(Double_t PD[], Double_t RD[], Double_t H[], Double_t CH, Double_t SPU, Double_t DJ[], Double_t DK[], // output Int_t &IERR, Double_t PC[], Double_t RC[]) { // ---------------------------------------------------------------------- // // Tranform error matrix // FROM SD (detector plane) VARIABLES (1/P,V',W',V,W) // TO SC (transverse system) VARIABLES (1/P,LAMBDA,PHI,YT,ZT) // // Authors: A. Haas and W. Wittek // Translated in C/Root by A. Rotondi and A. Fontana (June 2007) // // // INPUT // PD(3) 1/P,V',W' // H(3) MAGNETIC FIELD // RD(15) ERROR MATRIX IN 1/P,V',W',V,W (Triangular) // CH CHARGE OF PARTICLE // CHARGE AND MAGNETIC FIELD ARE NEEDED // FOR CORRELATION TERMS (LAMBDA,V),(LAMBDA,W),(PHI,V),(PHI,W) // THESE CORRELATION TERMS APPEAR BECAUSE RC IS ASSUMED // TO BE THE ERROR MATRIX FOR FIXED S (PATH LENGTH) // AND RD FOR FIXED U // SPU SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // spu = sign[p·(DJ x DK)] // DJ(3) UNIT VECTOR IN V-DIRECTION // DK(3) UNIT VECTOR IN W-DIRECTION OF DETECTOR SYSTEM // // OUTPUT // PC(3) 1/P,LAMBDA,PHI // RC(15) ERROR MATRIX IN SC VARIABLES // IERR NOT USED // // --------------------------------------------------------------------- Double_t A[5][5], S[15], TN[3]; Double_t SINZ, COSZ, COSL, COSL1; Double_t UN[3], VN[3], DI[3], TVW[3]; Double_t Vec[25]; Double_t CFACT8= 2.997925e-04; Double_t HA, HM, HAM, Q, UJ, UK, VJ, VK; Double_t PM; IERR=0; memset(RC,0,sizeof(RC)); memset(PC,0,sizeof(PC)); PM=PD[0]; TVW[0]=1./TMath::Sqrt(1.+PD[1]*PD[1]+PD[2]*PD[2]); if(SPU < 0.) TVW[0]=-TVW[0]; TVW[1]=PD[1]*TVW[0]; TVW[2]=PD[2]*TVW[0]; DI[0]=DJ[1]*DK[2]-DJ[2]*DK[1]; DI[1]=DJ[2]*DK[0]-DJ[0]*DK[2]; DI[2]=DJ[0]*DK[1]-DJ[1]*DK[0]; for(Int_t I=0; I<3; I++) { TN[I]=TVW[0]*DI[I]+TVW[1]*DJ[I]+TVW[2]*DK[I]; } PC[0] = PD[0]; PC[1] = TMath::ASin(TN[2]); if(TMath::Abs(TN[0]) < 1.e-30) TN[0] = 1.e-30; PC[2] = TMath::ATan2(TN[1],TN[0]); COSL=TMath::Sqrt(TMath::Abs(1.-TN[2]*TN[2])); if(COSL < 1.e-30) COSL = 1.e-30; COSL1 = 1./COSL; UN[0] = -TN[1]*COSL1; UN[1] = TN[0]*COSL1; UN[2] = 0.; VN[0] = -TN[2]*UN[1]; VN[1] = TN[2]*UN[0]; VN[2] = COSL; UJ = UN[0]*DJ[0]+UN[1]*DJ[1]+UN[2]*DJ[2]; UK = UN[0]*DK[0]+UN[1]*DK[1]+UN[2]*DK[2]; VJ = VN[0]*DJ[0]+VN[1]*DJ[1]+VN[2]*DJ[2]; VK = VN[0]*DK[0]+VN[1]*DK[1]+VN[2]*DK[2]; // prepare matrices and vectors for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<5; K++) { A[I][K]=0.; } } for(Int_t J=0; J<15; J++) S[J]=RD[J]; if(CH != 0.) { // charged particle HA=TMath::Sqrt(H[0]*H[0]+H[1]*H[1]+H[2]*H[2]); HAM=HA*PM; if(HAM != 0.) { // .... in a magnetic field HM=CH/HA; Q=-HAM*CFACT8; SINZ=-(H[0]*UN[0]+H[1]*UN[1]+H[2]*UN[2])*HM; COSZ= (H[0]*VN[0]+H[1]*VN[1]+H[2]*VN[2])*HM; A[1][3] = -Q*TVW[1]*SINZ; A[1][4] = -Q*TVW[2]*SINZ; A[2][3] = -Q*TVW[1]*COSZ*COSL1; A[2][4] = -Q*TVW[2]*COSZ*COSL1; } } A[0][0] = 1.; A[1][1] = TVW[0]*VJ; A[1][2] = TVW[0]*VK; A[2][1] = TVW[0]*UJ*COSL1; A[2][2] = TVW[0]*UK*COSL1; A[3][3] = UJ; A[3][4] = UK; A[4][3] = VJ; A[4][4] = VK; // transformation matrix FromMatToVec(A, Vec); SymmProd(Vec,S,S); // copy the result in S in the output vector for(Int_t I=0; I<15; I++) RC[I]=S[I]; } void CbmGeaneUtil::FromVec15ToMat25(Double_t V[], Double_t A[][5]) { // // ------------------------------------------------------ // Passage from a 15-dim vector to a symmetric 5x5 matrix // following the upper triangular convention // // Author A. Rotondi June 2007 // // ------------------------------------------------------ A[0][0] = V[0]; A[0][1] = V[1]; A[0][2] = V[2]; A[0][3] = V[3]; A[0][4] = V[4]; A[1][1] = V[5]; A[1][2] = V[6]; A[1][3] = V[7]; A[1][4] = V[8]; A[2][2] = V[9]; A[2][3] = V[10]; A[2][4] = V[11]; A[3][3] = V[12]; A[3][4] = V[13]; A[4][4] = V[14]; for(Int_t I=0; I<5; I++){ for(Int_t k=I; k<5; k++){ A[k][I] = A[I][k]; } } } void CbmGeaneUtil::FromVecToMat(Double_t A[][5], Double_t V[]) { // // ------------------------------------------------------ // Passage from 25-dim vector to a symmetric 5x5 matrix // (FoRTRAN column convention) // // Author A. Rotondi June 2007 // // ------------------------------------------------------ A[0][0] = V[0]; A[1][0] = V[1]; A[2][0] = V[2]; A[3][0] = V[3]; A[4][0] = V[4]; A[0][1] = V[5];; A[1][1] = V[6];; A[2][1] = V[7];; A[3][1] = V[8];; A[4][1] = V[9];; A[0][2] = V[10] ; A[1][2] = V[11] ; A[2][2] = V[12] ; A[3][2] = V[13] ; A[4][2] = V[14] ; A[0][3] = V[15] ; A[1][3] = V[16] ; A[2][3] = V[17] ; A[3][3] = V[18] ; A[4][3] = V[19] ; A[0][4] = V[20] ; A[1][4] = V[21] ; A[2][4] = V[22] ; A[3][4] = V[23] ; A[4][4] = V[24] ; } void CbmGeaneUtil::FromSCToMars(Double_t PC[], Double_t RC[], Double_t H[], Double_t CH, // output Double_t PD[], Double_t RD[][6]) { // ------------------------------------------------------------------------ // // Transform error matrix // // FROM SC (transverse system) (1/P,LAMBDA,PHI,YT,ZT) // TO MASTER Reference System (MARS) (px, py, pz, z, y, z) // // Method: the MARS system is considered as a detector system with // y-z as the detector plane. Hence, the SC to SD routine is used. // In this way the track length variation and the magnetic field // effects are correctly taken into account. // Then, eq (80) of the report CMS 2006/001 is used // to go from SD to the canonical variables of MARS. // In this passage the errors on x are zero because SD assumes // this variable as known. // // Authors: A. Rotondi and A. Fontana (June 2007) // // INPUT // PC(3) 1/p lambda phi // RC(15) ERROR MATRIX IN SC VARIABLES // H(3) Magnetic field components // CH CHARGE OF PARTICLE // // OUTPUT // PD(3) px, py, pz // RD(6,6) ERROR MATRIX in MASTER Reference System // covariances of (px, py, pz, x, y, z) // // // --------------------------------------------------------------------------- Double_t M65[6][5], M65T[5][6], AJ[5][6]; Double_t DJ[3], DK[3], RCM[5][5]; Double_t PDD[3], RDD[15]; Int_t IERR; Double_t SPU, PM, PM2, PVW, PVW3; // ------------------------------------------------------------------------- IERR=0; memset(PD,0,sizeof(PD)); // reset matrices for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<6; K++) { AJ[I][K]=0.; M65[K][I]=0.; M65T[I][K]=0.; RD[I][K] = 0.; } } for(Int_t I=0; I<6; I++) { RD[5][I] = 0.; } // GEANE routines to go on SD DJ[0] = 0.; DJ[1] = 1.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 0.; DK[2] = 1.; FromSCToSD(PC, RC, H, CH, DJ, DK, IERR, SPU, PDD, RDD); if(IERR ==1) { // track lies in he y-z plane; change detecto plane to x-y DJ[0] = 1.; DJ[1] = 0.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 1.; DK[2] = 0.; FromSCToSD(PC, RC, H, CH, DJ, DK, IERR, SPU, PDD, RDD); // from 1/p Lambda Phi to SD PM = 1./PDD[0]; PM2 = PM*PM; PVW = TMath::Sqrt(1.+PDD[1]*PDD[1]+PDD[2]*PDD[2]); PVW3 = TMath::Power(PVW,3); // output px, py, pz PD[0] = SPU*PM*PDD[1]/PVW; PD[1] = SPU*PM*PDD[2]/PVW; PD[2] = SPU*PM/PVW ; // Jacobian SD --> Mars // eq (80) of CMS note 2006/001 (Strandle and Wittek) M65[0][0] = - SPU*PM2*PDD[1]/(CH*PVW); M65[1][0] = - SPU*PM2*PDD[2]/(CH*PVW); M65[2][0] = - SPU*PM2/(CH*PVW); M65[0][1] = SPU*PM*(1.+PDD[2]*PDD[2])/PVW3; M65[1][1] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[2][1] = - SPU*PM*PDD[1]/PVW3; M65[0][2] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[1][2] = SPU*PM*(1.+PDD[1]*PDD[1])/PVW3; M65[2][2] = - SPU*PM*PDD[2]/PVW3; M65[3][3] = 1.; M65[4][4] = 1.; } else{ // general case, y-z is the detector plane // from 1/p Lambda Phi to SD PM = 1./PDD[0]; PM2 = PM*PM; PVW = TMath::Sqrt(1.+PDD[1]*PDD[1]+PDD[2]*PDD[2]); PVW3 = TMath::Power(PVW,3); // output px, py, pz PD[0] = SPU*PM/PVW; PD[1] = SPU*PM*PDD[1]/PVW; PD[2] = SPU*PM*PDD[2]/PVW;; // Jacobian SD --> Mars // eq (80) of CMS note 2006/001 (Strandle and Wittek) // modified to have y-z as the detector plane M65[0][0] = - SPU*PM2/(CH*PVW); M65[1][0] = - SPU*PM2*PDD[1]/(CH*PVW); M65[2][0] = - SPU*PM2*PDD[2]/(CH*PVW); M65[0][1] = - SPU*PM*PDD[1]/PVW3; M65[1][1] = SPU*PM*(1.+PDD[2]*PDD[2])/PVW3; M65[2][1] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[0][2] = - SPU*PM*PDD[2]/PVW3; M65[1][2] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[2][2] = SPU*PM*(1.+PDD[1]*PDD[1])/PVW3; M65[4][3] = 1.; M65[5][4] = 1.; } FromVec15ToMat25(RDD,RCM); // transposed of the jacobian for(Int_t I=0; I<6; I++) { for(Int_t K=0; K<5; K++) { M65T[K][I]=M65[I][K]; } } // product (J)(RCM)(J+) for(Int_t i=0; i<5; i++){ for(Int_t k=0; k<6; k++){ for(Int_t l=0; l<5; l++){ AJ[i][k] += RCM[i][l]*M65T[l][k]; } } } for(Int_t i=0; i<6; i++){ for(Int_t k=0; k<6; k++){ for(Int_t l=0; l<5; l++){ RD[i][k] += M65[i][l]*AJ[l][k]; } } } } void CbmGeaneUtil::FromMarsToSC(Double_t PD[], Double_t RD[][6], Double_t H[], Double_t CH, // output Double_t PC[], Double_t RC[]) { // ---------------------------------------------------------------------- // // Tranform error matrix // FROM MASTER VARIABLES (px, py,pz, x, y, z) // TO SC (transverse system) VARIABLES (1/p, lambda, phi, yt, zt) // momentum along x axis (GEANE convention) // // Method: the MARS system is considered as a detector system with // y-z as the detector plane. Hence eq (79) of the // report CMS 2006/001 is used to go from canonical to SD variables. // Then, the SD to SC routine is used. // In this way the track length variation and the magnetic field // effects are correctly taken into account. // // Authors: A. Rotondi and A. Fontana (June 2007) // // INPUT // PD(3) px, py, pz // RD(6,6) ERROR MATRIX from MASTER Reference System // covariances of (px, py, pz, x, y, z) // // CH CHARGE OF PARTICLE // H(3) MAGNETIC FIELD components // // OUTPUT // PC(3) 1/p, lamda, phi // RC(15) ERROR MATRIX IN SC VARIABLES // // // --------------------------------------------------------------------- Double_t PDD[3], RDD[15]; Double_t M56[5][6], M56T[6][5], AJ[5][5], AJT[6][5]; Double_t SPU, DJ[3], DK[3], PM, PM3, PT; Int_t IERR; // ------------------------------------------------------------------ // reset //cout << "mars" << endl; IERR=0; memset(RC,0,sizeof(RC)); memset(PC,0,sizeof(PC)); for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<6; K++) { AJT[K][I]=0.; M56[I][K]=0.; M56T[K][I]= 0.; if(K != 5) AJ[I][K]=0.; } } PM = TMath::Sqrt(PD[0]*PD[0]+PD[1]*PD[1]+PD[2]*PD[2]); PM3 = TMath::Power(PM,3); PT = TMath::Sqrt(PD[0]*PD[0]+PD[1]*PD[1]); // check if track lies in the y-z plane if(TMath::Abs(PD[0]) < 1.e-07) { // direction cosines of the x-y plane (SD system) DJ[0] = 1.; DJ[1] = 0.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 1.; DK[2] = 0.; // 1/p v' w' momentum along z PDD[0]= 1./PM; PDD[1] = PD[0]/PD[2]; PDD[2] = PD[1]/PD[2];; // Jacobian Mars --> SD parallel to Mars x-y plane // eq (79) of CMS note 2006/001 (Strandle and Wittek) M56[0][0] = - CH*PD[0]/PM3; M56[0][1] = - CH*PD[1]/PM3; M56[0][2] = - CH*PD[2]/PM3; M56[1][0] = 1./PD[2]; M56[1][1] = 0.; M56[1][2] = - PD[0]/(PD[2]*PD[2]); M56[2][0] = 0.; M56[2][1] = 1./PD[2]; M56[2][2] = - PD[1]/(PD[2]*PD[2]); M56[3][3] = 1.; M56[4][4] = 1.; } else { // direction cosines of the y-z plane (SD system) DJ[0] = 0.; DJ[1] = 1.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 0.; DK[2] = 1.; // 1/p v' w' momentum along x PDD[0] = 1./PM; PDD[1] = PD[1]/PD[0]; PDD[2] = PD[2]/PD[0];; // Jacobian Mars --> SD parallel x-y plane // modified from eq (79) of CMS note 2006/001 (Strandle and Wittek) // to take into account the convention of p along x M56[0][0] = - CH*PD[0]/PM3; M56[0][1] = - CH*PD[1]/PM3; M56[0][2] = - CH*PD[2]/PM3; M56[1][0] = - PD[1]/(PD[0]*PD[0]); M56[1][1] = 1./PD[0]; M56[1][2] = 0.; M56[2][0] = - PD[2]/(PD[0]*PD[0]); M56[2][1] = 0.; M56[2][2] = 1./PD[0]; M56[3][4] = 1.; M56[4][5] = 1.; } // matrix multiplication with the Jacobian for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ M56T[l][k]= M56[k][l]; } } for(Int_t i=0; i<6; i++){ for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ AJT[i][k] += RD[i][l]*M56T[l][k]; } } } for(Int_t i=0; i<5; i++){ for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ AJ[i][k] += M56[i][l]*AJT[l][k]; } } } // from SD to SC FromMat25ToVec15(AJ,RDD); SPU = TMath::Sign(1., PD[0]*(DJ[1]*DK[2]-DJ[2]*DK[1])+ PD[1]*(DJ[2]*DK[0]-DJ[0]*DK[2])+ PD[2]*(DJ[0]*DK[1]-DJ[1]*DK[0]) ); FromSDToSC(PDD, RDD, H, CH, SPU, DJ, DK, IERR, PC, RC); } void CbmGeaneUtil::FromMarsToSD(Double_t PD[], Double_t RD[][6], Double_t H[], Double_t CH, Double_t DJ1[], Double_t DK1[], // output Int_t &IERR, Double_t &SP1, Double_t PC[], Double_t RC[]) { // ---------------------------------------------------------------------- // // Tranform error matrix // FROM MASTER VARIABLES (px, py,pz, x, y, z) // TO SD (transverse or local system) // VARIABLES (1/p, v', w', v, w) // // Method: the MARS system is considered as a detector system SD1 with // y-z as the detector plane. Hence eq (79) of the // report CMS 2006/001 is used to go from canonical to SD1 variables. // Then, the SD1 to SD routine is used. // In this way the track length variation and the magnetic field // effects are correctly taken into account. // // Authors: A. Rotondi and A. Fontana (July 2007) // // INPUT // PD(3) px, py, pz // RD(6,6) ERROR MATRIX from MASTER Reference System // covariances of (px, py, pz, x, y, z) // // CH CHARGE OF PARTICLE // H(3) MAGNETIC FIELD components // DJ1(3) Director cosines of axis v in MARS // DK1(3) Director cosines of axis w in MARS // // OUTPUt // IERR = 0 TRANSFORMATION OK // = 1 MOMENTUM PERPENDICULAR TO U-DIRECTION // (V',W' NOT DEFINed) // = 2 MOMENTUM PERPENDICULAR TO X-AXIS // PC(3) 1/p, v', w' // RC(15) ERROR MATRIX IN SD VARIABLES // SP1 SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // SP1 = sign[p·(DJ x DK)] // // // --------------------------------------------------------------------- Double_t PDD[3], RDD[15]; Double_t M56[5][6], M56T[6][5], AJ[5][5], AJT[6][5]; Double_t SPU, DJ[3], DK[3], PM, PM3, PT; // ------------------------------------------------------------------ // reset IERR=0; memset(RC,0,sizeof(RC)); memset(PC,0,sizeof(PC)); for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<6; K++) { AJT[K][I]=0.; M56[I][K]=0.; M56T[K][I]= 0.; if(K != 5) AJ[I][K]=0.; } } PM = TMath::Sqrt(PD[0]*PD[0]+PD[1]*PD[1]+PD[2]*PD[2]); PM3 = TMath::Power(PM,3); PT = TMath::Sqrt(PD[0]*PD[0]+PD[1]*PD[1]); // check if track lies in the y-z plane if(TMath::Abs(PD[0]) < 1.e-07) { // direction cosines of the x-y plane (SD system) DJ[0] = 1.; DJ[1] = 0.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 1.; DK[2] = 0.; // 1/p v' w' momentum along z PDD[0]= 1./PM; PDD[1] = PD[0]/PD[2]; PDD[2] = PD[1]/PD[2];; // Jacobian Mars --> SD parallel to Mars x-y plane // eq (79) of CMS note 2006/001 (Strandle and Wittek) M56[0][0] = - CH*PD[0]/PM3; M56[0][1] = - CH*PD[1]/PM3; M56[0][2] = - CH*PD[2]/PM3; M56[1][0] = 1./PD[2]; M56[1][1] = 0.; M56[1][2] = - PD[0]/(PD[2]*PD[2]); M56[2][0] = 0.; M56[2][1] = 1./PD[2]; M56[2][2] = - PD[1]/(PD[2]*PD[2]); M56[3][3] = 1.; M56[4][4] = 1.; } else { // direction cosines of the y-z plane (SD system) DJ[0] = 0.; DJ[1] = 1.; DJ[2] = 0.; DK[0] = 0.; DK[1] = 0.; DK[2] = 1.; // 1/p v' w' momentum along x PDD[0] = 1./PM; PDD[1] = PD[1]/PD[0]; PDD[2] = PD[2]/PD[0];; // Jacobian Mars --> SD parallel x-y plane // modified from eq (79) of CMS note 2006/001 (Strandle and Wittek) // to take into account the convention of p along x M56[0][0] = - CH*PD[0]/PM3; M56[0][1] = - CH*PD[1]/PM3; M56[0][2] = - CH*PD[2]/PM3; M56[1][0] = - PD[1]/(PD[0]*PD[0]); M56[1][1] = 1./PD[0]; M56[1][2] = 0.; M56[2][0] = - PD[2]/(PD[0]*PD[0]); M56[2][1] = 0.; M56[2][2] = 1./PD[0]; M56[3][4] = 1.; M56[4][5] = 1.; } // matrix multiplication with the Jacobian for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ M56T[l][k]= M56[k][l]; } } for(Int_t i=0; i<6; i++){ for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ AJT[i][k] += RD[i][l]*M56T[l][k]; } } } for(Int_t i=0; i<5; i++){ for(Int_t k=0; k<5; k++){ for(Int_t l=0; l<6; l++){ AJ[i][k] += M56[i][l]*AJT[l][k]; } } } // from SD1 to SD FromMat25ToVec15(AJ,RDD); SPU = TMath::Sign(1., PD[0]*(DJ[1]*DK[2]-DJ[2]*DK[1])+ PD[1]*(DJ[2]*DK[0]-DJ[0]*DK[2])+ PD[2]*(DJ[0]*DK[1]-DJ[1]*DK[0]) ); FromSD1ToSD2(PDD, RDD, H, CH, SPU, DJ, DK, DJ1, DK1, IERR, SP1, PC, RC); } void CbmGeaneUtil::FromSDToMars(Double_t PC[], Double_t RC[], Double_t H[], Double_t CH, Double_t SP1, Double_t DJ1[], Double_t DK1[], // output Double_t PD[], Double_t RD[][6]) { // ------------------------------------------------------------------------ // // Transform error matrix // // FROM SD (detector system system) (1/P,v'.w'.v.w) // TO MASTER Reference System (MARS) (px, py, pz, z, y, z) // // Method: the MARS system is considered as a SD1 detector system with // y-z as the detector plane. Hence, the SD to SD1 routine is used. // In this way the track length variation and the magnetic field // effects are correctly taken into account. // Then, eq (80) of the report CMS 2006/001 is used // to go from SD1 to the canonical variables of MARS. // // Authors: A. Rotondi and A. Fontana (June 2007) // // INPUT // PC(3) 1/p v' w' // RC(15) ERROR MATRIX IN SD VARIABLES // covariances of (px, py, pz, x, y, z) // H(3) Magnetic field components // CH CHARGE OF PARTICLE // DJ1(3) Director cosines of axis v in MARS // DK1(3) Director cosines of axis w in MARS // SP1 SIGN OF U-COMPONENT OF PARTICLE MOMENTUM // spu = sign[p·(DJ1 x DK1)] // // OUTPUT // PD(3) px, py, pz // RD(6,6) ERROR (Covariance) MATRIX in MASTER Reference System // // // --------------------------------------------------------------------------- Double_t M65[6][5], M65T[5][6], AJ[5][6]; Double_t DJ2[3], DK2[3], RCM[5][5]; Double_t PDD[3], RDD[15]; Int_t IERR; Double_t SPU, PM, PM2, PVW, PVW3; // ------------------------------------------------------------------------- IERR=0; memset(PD,0,sizeof(PD)); // reset matrices for(Int_t I=0; I<5; I++) { for(Int_t K=0; K<6; K++) { AJ[I][K]=0.; M65[K][I]=0.; M65T[I][K]=0.; RD[I][K] = 0.; } } for(Int_t I=0; I<6; I++) { RD[5][I] = 0.; } // GEANE routines to go on SD DJ2[0] = 0.; DJ2[1] = 1.; DJ2[2] = 0.; DK2[0] = 0.; DK2[1] = 0.; DK2[2] = 1.; FromSD1ToSD2(PC, RC, H, CH, SP1, DJ1, DK1, DJ2, DK2, IERR, SPU, PDD, RDD); if(IERR ==1) { // track lies in he y-z plane; change detector plane to x-y DJ2[0] = 1.; DJ2[1] = 0.; DJ2[2] = 0.; DK2[0] = 0.; DK2[1] = 1.; DK2[2] = 0.; FromSD1ToSD2(PC, RC, H, CH, SP1, DJ1, DK1, DJ2, DK2, IERR, SPU, PDD, RDD); // from SD1 to SD2 PM = 1./PDD[0]; PM2 = PM*PM; PVW = TMath::Sqrt(1.+PDD[1]*PDD[1]+PDD[2]*PDD[2]); PVW3 = TMath::Power(PVW,3); // output px, py, pz PD[0] = SPU*PM*PDD[1]/PVW; PD[1] = SPU*PM*PDD[2]/PVW; PD[2] = SPU*PM/PVW ; // Jacobian SD --> Mars // eq (80) of CMS note 2006/001 (Strandle and Wittek) M65[0][0] = - SPU*PM2*PDD[1]/(CH*PVW); M65[1][0] = - SPU*PM2*PDD[2]/(CH*PVW); M65[2][0] = - SPU*PM2/(CH*PVW); M65[0][1] = SPU*PM*(1.+PDD[2]*PDD[2])/PVW3; M65[1][1] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[2][1] = - SPU*PM*PDD[1]/PVW3; M65[0][2] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[1][2] = SPU*PM*(1.+PDD[1]*PDD[1])/PVW3; M65[2][2] = - SPU*PM*PDD[2]/PVW3; M65[3][3] = 1.; M65[4][4] = 1.; } else{ // general case, y-z is the detector plane // from SD1 to SD2 PM = 1./PDD[0]; PM2 = PM*PM; PVW = TMath::Sqrt(1.+PDD[1]*PDD[1]+PDD[2]*PDD[2]); PVW3 = TMath::Power(PVW,3); // output px, py, pz PD[0] = SPU*PM/PVW; PD[1] = SPU*PM*PDD[1]/PVW; PD[2] = SPU*PM*PDD[2]/PVW;; // Jacobian SD --> Mars // eq (80) of CMS note 2006/001 (Strandle and Wittek) // modified to have y-z as the detector plane M65[0][0] = - SPU*PM2/(CH*PVW); M65[1][0] = - SPU*PM2*PDD[1]/(CH*PVW); M65[2][0] = - SPU*PM2*PDD[2]/(CH*PVW); M65[0][1] = - SPU*PM*PDD[1]/PVW3; M65[1][1] = SPU*PM*(1.+PDD[2]*PDD[2])/PVW3; M65[2][1] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[0][2] = - SPU*PM*PDD[2]/PVW3; M65[1][2] = - SPU*PM*PDD[1]*PDD[2]/PVW3; M65[2][2] = SPU*PM*(1.+PDD[1]*PDD[1])/PVW3; M65[4][3] = 1.; M65[5][4] = 1.; } FromVec15ToMat25(RDD,RCM); // transposed of the jacobian for(Int_t I=0; I<6; I++) { for(Int_t K=0; K<5; K++) { M65T[K][I]=M65[I][K]; } } // product (J)(RCM)(J+) for(Int_t i=0; i<5; i++){ for(Int_t k=0; k<6; k++){ for(Int_t l=0; l<5; l++){ AJ[i][k] += RCM[i][l]*M65T[l][k]; } } } for(Int_t i=0; i<6; i++){ for(Int_t k=0; k<6; k++){ for(Int_t l=0; l<5; l++){ RD[i][k] += M65[i][l]*AJ[l][k]; } } } } void CbmGeaneUtil::FromMat25ToVec15(Double_t A[][5], Double_t V[]) { // // ------------------------------------------------------ // Passage from a symmetric 5x5 matrix to a 15-dim vector // following the upper triangular convention // // Author A. Rotondi June 2007 // // ------------------------------------------------------ V[0] = A[0][0]; V[1] = A[0][1]; V[2] = A[0][2]; V[3] = A[0][3]; V[4] = A[0][4]; V[5] = A[1][1]; V[6] = A[1][2]; V[7] = A[1][3]; V[8] = A[1][4]; V[ 9] = A[2][2]; V[10] = A[2][3]; V[11] = A[2][4]; V[12] = A[3][3]; V[13] = A[3][4]; V[14] = A[4][4]; } void CbmGeaneUtil::FromMatToVec(Double_t A[][5], Double_t V[]) { // // ------------------------------------------------------ // Passage from a 5x5 matrix to a 25-dim vector // // Author A. Rotondi June 2007 // // ------------------------------------------------------ V[0] = A[0][0]; V[1] = A[1][0]; V[2] = A[2][0]; V[3] = A[3][0]; V[4] = A[4][0]; V[5] = A[0][1]; V[6] = A[1][1]; V[7] = A[2][1]; V[8] = A[3][1]; V[9] = A[4][1]; V[10] = A[0][2]; V[11] = A[1][2]; V[12] = A[2][2]; V[13] = A[3][2]; V[14] = A[4][2]; V[15] = A[0][3]; V[16] = A[1][3]; V[17] = A[2][3]; V[18] = A[3][3]; V[19] = A[4][3]; V[20] = A[0][4]; V[21] = A[1][4]; V[22] = A[2][4]; V[23] = A[3][4]; V[24] = A[4][4]; } void CbmGeaneUtil::SymmProd(Double_t A[], Double_t S[], Double_t R[]) { // // --------------------------------------------------------- // TRANSFORMATION OF SYMMETRIC 5X5 MATRIX S: // A*S*AT -> R. // A is a 25-dim vector corresonding to the 5x5 transformation // matrix // S and R ARE SYMMETRIC ERROR (COVARIANCE) MATRICES STORED // IN TRIANGULAR FORM. // // INPUT // A[25] transformation matrix 5x5 // S[15] error matrix in triangular form // // OUTPUT // R[15] error matrix in triangular form // // NB: S AND R MAY WELL BE THE SAME MATRIX. // // Author: A. Haas (Freiburg University) 5/7/81 // transported with modifications // in C/Root by A. Rotondi (June 2007) // // * ------------------------------------------------------ Double_t Q[15],T1,T2,T3,T4,T5; for(Int_t i=0; i<15; i++) Q[i]=S[i]; Int_t K =0; for(Int_t J=0; J<5; J++) { T1=A[J ]; T2=A[J+ 5]; T3=A[J+10]; T4=A[J+15]; T5=A[J+20]; for(Int_t I=J; I<5; I++) { R[K]=A[I ]*(Q[0]*T1+Q[1]*T2+Q[ 2]*T3+Q[ 3]*T4+Q[ 4]*T5) +A[I+ 5]*(Q[1]*T1+Q[5]*T2+Q[ 6]*T3+Q[ 7]*T4+Q[ 8]*T5) +A[I+10]*(Q[2]*T1+Q[6]*T2+Q[ 9]*T3+Q[10]*T4+Q[11]*T5) +A[I+15]*(Q[3]*T1+Q[7]*T2+Q[10]*T3+Q[12]*T4+Q[13]*T5) +A[I+20]*(Q[4]*T1+Q[8]*T2+Q[11]*T3+Q[13]*T4+Q[14]*T5); K++; } } } // ------------------------- modifiche 27 jul 2007 -------------------------- TVector3 CbmGeaneUtil::FromMARSToSDCoord(TVector3 xyz, TVector3 o, TVector3 di, TVector3 dj, TVector3 dk) { TMatrixT matrix(3,3); // rotation matrix (u,v,w) = (fmatrix) * (x,y,z) matrix[0][0] = di[0]; matrix[0][1] = di[1]; matrix[0][2] = di[2]; matrix[1][0] = dj[0]; matrix[1][1] = dj[1]; matrix[1][2] = dj[2]; matrix[2][0] = dk[0]; matrix[2][1] = dk[1]; matrix[2][2] = dk[2]; // cout << "matrix: " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << endl; // cout << " " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << endl; // cout << " " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << endl; TMatrixT xyzvec(3,1); xyzvec[0][0] = xyz.X(); xyzvec[1][0] = xyz.Y(); xyzvec[2][0] = xyz.Z(); // cout << "vettore " << xyzvec[0][0] << endl; // cout << " " << xyzvec[1][0] << endl; // cout << " " << xyzvec[2][0] << endl; TMatrixT origin(3,1); origin[0][0] = o.X(); origin[1][0] = o.Y(); origin[2][0] = o.Z(); // cout << "origin " << origin[0][0] << endl; // cout << " " << origin[1][0] << endl; // cout << " " << origin[2][0] << endl; xyzvec -= origin; // cout << "traslato " << xyzvec[0][0] << endl; // cout << " " << xyzvec[1][0] << endl; // cout << " " << xyzvec[2][0] << endl; TMatrixT uvwvec(matrix, TMatrixT::kMult, xyzvec); // cout << "ruotato " << uvwvec[0][0] << endl; // cout << " " << uvwvec[1][0] << endl; // cout << " " << uvwvec[2][0] << endl; TVector3 uvw = TVector3(uvwvec[0][0], uvwvec[1][0], uvwvec[2][0]); return uvw; } TVector3 CbmGeaneUtil::FromSDToMARSCoord(TVector3 uvw, TVector3 o, TVector3 di, TVector3 dj, TVector3 dk) { TMatrixT matrix(3,3); matrix[0][0] = di[0]; matrix[0][1] = di[1]; matrix[0][2] = di[2]; matrix[1][0] = dj[0]; matrix[1][1] = dj[1]; matrix[1][2] = dj[2]; matrix[2][0] = dk[0]; matrix[2][1] = dk[1]; matrix[2][2] = dk[2]; // cout << "matrix: " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << endl; // cout << " " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << endl; // cout << " " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << endl; TMatrixT uvwvec(3,1); uvwvec[0][0] = uvw.X(); uvwvec[1][0] = uvw.Y(); uvwvec[2][0] = uvw.Z(); // cout << "vettore " << uvwvec[0][0] << endl; // cout << " " << uvwvec[1][0] << endl; // cout << " " << uvwvec[2][0] << endl; TMatrixT uvwrot(matrix, TMatrixT::kTransposeMult, uvwvec); // cout << "ruotato " << uvwrot[0][0] << endl; // cout << " " << uvwrot[1][0] << endl; // cout << " " << uvwrot[2][0] << endl; TMatrixT origin(3,1); origin[0][0] = o.X(); origin[1][0] = o.Y(); origin[2][0] = o.Z(); // cout << "origin " << origin[0][0] << endl; // cout << " " << origin[1][0] << endl; // cout << " " << origin[2][0] << endl; TMatrixT xyzvec(3,1); xyzvec = uvwrot + origin; // cout << "traslato " << xyzvec[0][0] << endl; // cout << " " << xyzvec[1][0] << endl; // cout << " " << xyzvec[2][0] << endl; TVector3 xyz = TVector3(xyzvec[0][0], xyzvec[1][0], xyzvec[2][0]); return xyz; } ClassImp(CbmGeaneUtil)