#ifndef FitFunctional_H #define FitFunctional_H /// Abstract class. Contains discription of basic Fit Functional, which is used by any fit method ( Fit, Smother, DAF ) #include #include "FitClasses.h" #define cnst static const Single_t // with Fvec_t 15% slower cnst INF = .01; cnst INF2 = .0001; cnst ZERO = 0.0; cnst ONE = 1.; cnst c_light = 0.000299792458; cnst c_light_i = 1./c_light; cnst PipeRadThick = 0.0009; class Jacobian_t{ // jacobian elements // j[0][0] - j[3][2] are j02 - j34 public: Fvec_t &operator()(int i, int j) { assert( i>=0 && j>=2 ); return fj[i][j-2]; }; private: // 1 0 ? ? ? // 0 1 ? ? ? // j = 0 0 ? ? ? // 0 0 ? ? ? // 0 0 0 0 1 Fvec_t fj[4][3]; }; class FitFunctional { // base class for all approaches public: /// extrapolates track parameters virtual void ExtrapolateALight( Fvec_t T[], CovV &C, const Fvec_t &z_out, Fvec_t& qp0, FieldRegion &F, Fvec_t w = ZERO) const = 0; protected: /// initial aproximation void GuessVec( TrackV &t, Station *vStations, int NStations, bool dir = 0 ) const; virtual void Filter( TrackV &track, HitInfo &info, Fvec_t &u, Fvec_t w = ONE ) const = 0; // filter first mesurement virtual void FilterFirst( TrackV &track, HitV &hit, Station &st ) const = 0; void AddMaterial( TrackV &track, Station &st, Fvec_t &qp0, bool isPipe = ZERO ) const; void AddPipeMaterial( TrackV &track, Fvec_t &qp0) const; void AddHalfMaterial( TrackV &track, Station &st, Fvec_t &qp0) const; virtual void ExtrapolateWithMaterial( TrackV &track, const Fvec_t &z_out, Fvec_t& qp0, FieldRegion &F, Station &st, bool isPipe = 0, Fvec_t w = ZERO) const = 0; // ------------ help functions ------------ virtual void AddMaterial( CovV &C, Fvec_t Q22, Fvec_t Q32, Fvec_t Q33 ) const = 0; /// extrapolates track parameters and returns jacobian for extrapolation of CovMatrix void ExtrapolateJ ( Fvec_t *T, // input track parameters (x,y,tx,ty,Q/p) and cov.matrix Fvec_t z_out , // extrapolate to this z position Fvec_t qp0 , // use Q/p linearisation at this value const FieldRegion &F, Jacobian_t &j, Fvec_t w = 0.f ) const; /// calculate covMatrix for Multiple Scattering void GetMSMatrix( const Fvec_t &tx, const Fvec_t &ty, const Fvec_t &radThick, const Fvec_t &logRadThick, Fvec_t qp0, Fvec_t &Q22, Fvec_t &Q32, Fvec_t &Q33 ) const; private: /// extrapolates track parameters and returns jacobian for extrapolation of CovMatrix #if defined(ANALYTIC_EXTRAPOLATION) void ExtrapolateJAnalytic #elif defined(RK4_EXTRAPOLATION) void ExtrapolateJRK4 #endif ( Fvec_t T [], // input track parameters (x,y,tx,ty,Q/p) Fvec_t z_out , // extrapolate to this z position Fvec_t qp0 , // use Q/p linearisation at this value const FieldRegion &F, Jacobian_t &j, Fvec_t w = 0.f ) const; }; inline void FitFunctional::GuessVec( TrackV &t, Station *vStations, int nStations, bool dir ) const { Fvec_t *T = t.T; Int_t NHits = nStations; Fvec_t A0, A1=ZERO, A2=ZERO, A3=ZERO, A4=ZERO, A5=ZERO, a0, a1=ZERO, a2=ZERO, b0, b1=ZERO, b2=ZERO; Fvec_t z0, x, y, z, S, w, wz, wS; Int_t i=NHits-1; if(dir) i=0; z0 = vStations[i].zhit; HitV *hlst = &(t.vHits[i]); w = hlst->w; A0 = w; a0 = w*hlst->x; b0 = w*hlst->y; HitV *h = t.vHits; Station *st = vStations; int st_add = 1; if(dir) { st_add = -1; h += NHits-1; st += NHits-1; } for( ; h!=hlst; h+=st_add, st+=st_add ){ x = h->x; y = h->y; w = h->w; z = st->zhit - z0; if(!dir) S = st->SyL; else S = st->SyF; wz = w*z; wS = w*S; A0+=w; A1+=wz; A2+=wz*z; A3+=wS; A4+=wS*z; A5+=wS*S; a0+=w*x; a1+=wz*x; a2+=wS*x; b0+=w*y; b1+=wz*y; b2+=wS*y; } Fvec_t A3A3 = A3*A3; Fvec_t A3A4 = A3*A4; Fvec_t A1A5 = A1*A5; Fvec_t A2A5 = A2*A5; Fvec_t A4A4 = A4*A4; Fvec_t det = rcp(-A2*A3A3 + A1*( A3A4+A3A4 - A1A5) + A0*(A2A5-A4A4)); Fvec_t Ai0 = ( -A4A4 + A2A5 ); Fvec_t Ai1 = ( A3A4 - A1A5 ); Fvec_t Ai2 = ( -A3A3 + A0*A5 ); Fvec_t Ai3 = ( -A2*A3 + A1*A4 ); Fvec_t Ai4 = ( A1*A3 - A0*A4 ); Fvec_t Ai5 = ( -A1*A1 + A0*A2 ); Fvec_t L, L1; T[0] = (Ai0*a0 + Ai1*a1 + Ai3*a2)*det; T[2] = (Ai1*a0 + Ai2*a1 + Ai4*a2)*det; Fvec_t txtx1 = 1.f+T[2]*T[2]; L = (Ai3*a0 + Ai4*a1 + Ai5*a2)*det *rcp(txtx1); L1 = L*T[2]; A1 = A1 + A3*L1; A2 = A2 + ( A4 + A4 + A5*L1 )*L1; b1+= b2 * L1; det = rcp(-A1*A1+A0*A2); T[1] = ( A2*b0 - A1*b1 )*det; T[3] = ( -A1*b0 + A0*b1 )*det; T[4] = -L*c_light_i*rsqrt(txtx1 +T[3]*T[3]); T[5] = z0; } #if defined(ANALYTIC_EXTRAPOLATION) inline void FitFunctional::ExtrapolateJAnalytic // extrapolates track parameters and returns jacobian for extrapolation of CovMatrix ( Fvec_t T [], // input track parameters (x,y,tx,ty,Q/p) Fvec_t z_out , // extrapolate to this z position Fvec_t qp0 , // use Q/p linearisation at this value const FieldRegion &F, Jacobian_t &j, Fvec_t w ) const { //cout<<"Extrapolation..."< 1.e4 ) return 1; Fvec_t I_tx2ty21 = 1.f / tx2ty21 * qp0; Fvec_t tx2ty2 = sqrt(tx2ty21 ) ; // Fvec_t I_tx2ty2 = qp0 * hC / tx2ty2 ; unsused ??? tx2ty2 *= hC; Fvec_t tx2ty2qp = tx2ty2 * qp0; Ax[step] = ( txty*B[step][0] + ty*B[step][2] - ( 1.f + tx2 )*B[step][1] ) * tx2ty2; Ay[step] = (-txty*B[step][1] - tx*B[step][2] + ( 1.f + ty2 )*B[step][0] ) * tx2ty2; Ax_tx[step] = Ax[step]*tx*I_tx2ty21 + ( ty*B[step][0]-2.f*tx*B[step][1])*tx2ty2qp; Ax_ty[step] = Ax[step]*ty*I_tx2ty21 + ( tx*B[step][0]+ B[step][2])*tx2ty2qp; Ay_tx[step] = Ay[step]*tx*I_tx2ty21 + (-ty*B[step][1]- B[step][2])*tx2ty2qp; Ay_ty[step] = Ay[step]*ty*I_tx2ty21 + (-tx*B[step][1]+2.f*ty*B[step][0])*tx2ty2qp; step4 = step * 4; k[step4 ] = tx * h; k[step4+1] = ty * h; k[step4+2] = Ax[step] * qp0; k[step4+3] = Ay[step] * qp0; } // end of Runge-Kutta steps { T[0] = (x0[0]+c[0]*k[0]+c[1]*k[4+0]+c[2]*k[8+0]+c[3]*k[12+0]); T[1] = (x0[1]+c[0]*k[1]+c[1]*k[4+1]+c[2]*k[8+1]+c[3]*k[12+1]); T[2] = (x0[2]+c[0]*k[2]+c[1]*k[4+2]+c[2]*k[8+2]+c[3]*k[12+2]); T[3] = (x0[3]+c[0]*k[3]+c[1]*k[4+3]+c[2]*k[8+3]+c[3]*k[12+3]); T[5] = z_out; } // // Derivatives dx/dqp // x0[0] = 0.f; x0[1] = 0.f; x0[2] = 0.f; x0[3] = 0.f; // // Runge-Kutta step for derivatives dx/dqp for (step = 0; step < 4; ++step) { for(i=0; i < 4; ++i) { if(step == 0) { x[i] = x0[i]; } else { x[i] = x0[i] + b[step] * k1[step*4-4+i]; } } step4 = step * 4; k1[step4 ] = x[2] * h; k1[step4+1] = x[3] * h; k1[step4+2] = Ax[step] + Ax_tx[step] * x[2] + Ax_ty[step] * x[3]; k1[step4+3] = Ay[step] + Ay_tx[step] * x[2] + Ay_ty[step] * x[3]; } // end of Runge-Kutta steps for derivatives dx/dqp Fvec_t J[25]; for (i = 0; i < 4; ++i ) { J[20+i]=x0[i]+c[0]*k1[i]+c[1]*k1[4+i]+c[2]*k1[8+i]+c[3]*k1[12+i]; } J[24] = 1.; // // end of derivatives dx/dqp // // Derivatives dx/tx // x0[0] = 0.f; x0[1] = 0.f; x0[2] = 1.f; x0[3] = 0.f; // // Runge-Kutta step for derivatives dx/dtx // for (step = 0; step < 4; ++step) { for(i=0; i < 4; ++i) { if(step == 0) { x[i] = x0[i]; } else if ( i!=2 ) { x[i] = x0[i] + b[step] * k1[step*4-4+i]; } } step4 = step * 4; k1[step4 ] = x[2] * h; k1[step4+1] = x[3] * h; // k1[step4+2] = Ax_tx[step] * x[2] + Ax_ty[step] * x[3]; k1[step4+3] = Ay_tx[step] * x[2] + Ay_ty[step] * x[3]; } // end of Runge-Kutta steps for derivatives dx/dtx for (i = 0; i < 4; ++i ) { if(i != 2) { J[10+i]=x0[i]+c[0]*k1[i]+c[1]*k1[4+i]+c[2]*k1[8+i]+c[3]*k1[12+i]; } } // end of derivatives dx/dtx J[12] = 1.f; J[14] = 0.f; // Derivatives dx/ty // x0[0] = 0.f; x0[1] = 0.f; x0[2] = 0.f; x0[3] = 1.f; // // Runge-Kutta step for derivatives dx/dty // for (step = 0; step < 4; ++step) { for(i=0; i < 4; ++i) { if(step == 0) { x[i] = x0[i]; // ty fixed } else if(i!=3) { x[i] = x0[i] + b[step] * k1[step*4-4+i]; } } step4 = step * 4; k1[step4 ] = x[2] * h; k1[step4+1] = x[3] * h; k1[step4+2] = Ax_tx[step] * x[2] + Ax_ty[step] * x[3]; // k1[step4+3] = Ay_tx[step] * x[2] + Ay_ty[step] * x[3]; } // end of Runge-Kutta steps for derivatives dx/dty for (i = 0; i < 3; ++i ) { J[15+i]=x0[i]+c[0]*k1[i]+c[1]*k1[4+i]+c[2]*k1[8+i]+c[3]*k1[12+i]; } // end of derivatives dx/dty J[18] = 1.; J[19] = 0.; // // derivatives dx/dx and dx/dy for(i = 0; i < 10; ++i){ J[i] = 0.;} J[0] = 1.; J[6] = 1.; Fvec_t dqp = qp_in - qp0; { // update parameters T[0] +=(J[5*4+0]*dqp); T[1] +=(J[5*4+1]*dqp); T[2] +=(J[5*4+2]*dqp); T[3] +=(J[5*4+3]*dqp); } // covariance matrix transport // if ( C_in&&C_out ) CbmKFMath::multQtSQ( 5, J, C_in, C_out); // TODO j(0,2) = J[5*2 + 0]; j(1,2) = J[5*2 + 1]; j(2,2) = J[5*2 + 2]; j(3,2) = J[5*2 + 3]; j(0,3) = J[5*3 + 0]; j(1,3) = J[5*3 + 1]; j(2,3) = J[5*3 + 2]; j(3,3) = J[5*3 + 3]; j(0,4) = J[5*4 + 0]; j(1,4) = J[5*4 + 1]; j(2,4) = J[5*4 + 2]; j(3,4) = J[5*4 + 3]; } #endif // _EXTRAPOLATION inline void FitFunctional::ExtrapolateJ // extrapolates track parameters and returns jacobian for extrapolation of CovMatrix ( Fvec_t *T, // input track parameters (x,y,tx,ty,Q/p) and cov.matrix Fvec_t z_out , // extrapolate to this z position Fvec_t qp0 , // use Q/p linearisation at this value const FieldRegion &F, Jacobian_t &j, Fvec_t w ) const { #if defined(ANALYTIC_EXTRAPOLATION) ExtrapolateJAnalytic( T, z_out, qp0, F, j, w ); #elif defined(RK4_EXTRAPOLATION) ExtrapolateJRK4( T, z_out, qp0, F, j, w ); #endif // _EXTRAPOLATION } /// calculate covMatrix for Multiple Scattering inline void FitFunctional::GetMSMatrix( const Fvec_t &tx, const Fvec_t &ty, const Fvec_t &radThick, const Fvec_t &logRadThick, Fvec_t qp0, Fvec_t &Q22, Fvec_t &Q32, Fvec_t &Q33 ) const { cnst mass2 = 0.1396f*0.1396f; Fvec_t txtx = tx*tx; Fvec_t tyty = ty*ty; Fvec_t txtx1 = txtx + ONE; Fvec_t h = txtx + tyty; Fvec_t t = sqrt(txtx1 + tyty); Fvec_t h2 = h*h; Fvec_t qp0t = qp0*t; cnst c1=0.0136f, c2=c1*0.038f, c3=c2*0.5f, c4=-c3/2.0f, c5=c3/3.0f, c6=-c3/4.0f; Fvec_t s0 = (c1+c2*logRadThick + c3*h + h2*(c4 + c5*h +c6*h2) )*qp0t; Fvec_t a = (ONE+mass2*qp0*qp0t)*radThick*s0*s0; Q22 = txtx1*a; Q32 = tx*ty*a; Q33 = (ONE + tyty)*a; } inline void FitFunctional::AddMaterial( TrackV &track, Station &st, Fvec_t &qp0, bool isPipe ) const { Fvec_t Q22, Q32, Q33; if (isPipe) GetMSMatrix( track.T[2], track.T[3], st.RadThick + PipeRadThick, log(st.RadThick + PipeRadThick), qp0, Q22, Q32, Q33 ); else GetMSMatrix( track.T[2], track.T[3], st.RadThick, st.logRadThick, qp0, Q22, Q32, Q33 ); AddMaterial( track.C, Q22, Q32, Q33 ); } inline void FitFunctional::AddPipeMaterial( TrackV &track, Fvec_t &qp0 ) const { Fvec_t Q22, Q32, Q33; GetMSMatrix( track.T[2], track.T[3], PipeRadThick, log(PipeRadThick), qp0, Q22, Q32, Q33 ); AddMaterial( track.C, Q22, Q32, Q33 ); } inline void FitFunctional::AddHalfMaterial( TrackV &track, Station &st, Fvec_t &qp0 ) const { Fvec_t Q22, Q32, Q33; GetMSMatrix( track.T[2], track.T[3], st.RadThick*0.5f, st.logRadThick+log(0.5f), qp0, Q22, Q32, Q33 ); AddMaterial( track.C, Q22, Q32, Q33 ); } #endif