// $Id$ // // File: DTrack_factory_THROWN.cc // Created: Mon Sep 3 19:57:11 EDT 2007 // Creator: davidl (on Darwin Amelia.local 8.10.1 i386) // #include using namespace std; #include "DANA/DApplication.h" #include "DTrack_factory_THROWN.h" #include "DMCThrown.h" #include "DReferenceTrajectory.h" #include "DRandom.h" #include "DMatrix.h" //------------------ // evnt //------------------ jerror_t DTrack_factory_THROWN::evnt(JEventLoop *loop, int eventnumber) { vector mcthrowns; loop->Get(mcthrowns); for(unsigned int i=0; i< mcthrowns.size(); i++){ const DMCThrown *thrown = mcthrowns[i]; const DKinematicData *kd_thrown = thrown; if(fabs(thrown->charge())<1)continue; // First, copy over the DKinematicData part DTrack *track = new DTrack; DKinematicData *kd_track = track; *kd_track = *kd_thrown; // Create and fill the covariance matrix for the track. // We need to fill this using errors estimated from the thrown // momentum and angle. //DMatrixDSym errMatrix(1,7); DMatrixDSym errMatrix(7); track->setErrorMatrix(errMatrix); // Fill in DTrack specific members. (Some of these are redundant) DVector3 pos = track->position(); DVector3 mom = track->momentum(); track->q = track->charge(); track->p = mom.Mag(); track->theta = mom.Theta(); track->phi = mom.Phi(); track->x = pos.X(); track->y = pos.Y(); track->z = pos.Z(); track->candidateid = 0; track->chisq = 0.0; track->dE = 0.0; track->ds = 0.0; track->err_dE = 0.0; track->err_ds = 0.0; // Adapted from Alex's fortran code to paramatrize the resolution // of GlueX. He developed this from a study Dave Lawrence did. //this->SmearMomentum(track); // We need to swim a reference trajectory here. To avoid the overhead // of allocating/deallocating them every event, we keep a pool and // re-use them. If the pool is not big enough, then add one to the // pool. if(rt.size()<=_data.size()){ // This is a little ugly, but only gets called a few times throughout the life of the process // Note: these never get deleted, even at the end of process. DApplication* dapp = dynamic_cast(loop->GetJApplication()); rt.push_back(new DReferenceTrajectory(dapp->GetBfield())); } rt[_data.size()]->Swim(pos, mom, track->charge()); track->rt = rt[_data.size()]; _data.push_back(track); } return NOERROR; } //------------------ // SampleGaussian //------------------ double DTrack_factory_THROWN::SampleGaussian(double sigma) { // We loop to ensure not to return values greater than 3sigma away double val; do{ double epsilon = 1.0E-10; double r1 = epsilon+((double)random()/(double)RAND_MAX); double r2 = (double)random()/(double)RAND_MAX; val = sigma*sqrt(-2.0*log(r1))*cos(2.0*M_PI*r2); }while(fabs(val/sigma) > 3.0); return val; } //------------------ // The various smearing resolutions taken // directly from Alex's smear.f code. //------------------ void DTrack_factory_THROWN::SmearMomentum(DTrack *trk) { DRandom rnd; // Track phi, theta, mag //double pmag = trk->p; //double phi = trk->phi; //double theta = trk->theta; double pmag = trk->lorentzMomentum().Rho(); double theta = trk->lorentzMomentum().Theta(); double phi = trk->lorentzMomentum().Phi(); // Alex's study used phi in degrees double theta_deg = theta*180.0/TMath::Pi(); // Set the random seed based on phi rnd.SetSeed((uint)(10000*phi)); double dp=0, dphi=0, dtheta=0, dtheta_deg=0; // Grabbed this from if(theta_deg<15) {dp=res_p1(theta_deg); dtheta_deg=res_p10(pmag); dphi=res_p9(pmag);} else if(theta_deg>=15 && theta_deg<25) {dp=res_p2(pmag); dtheta_deg=res_p10(pmag); dphi=res_p9(pmag);} else if(theta_deg>=25 && theta_deg<35) {dp=res_p3(pmag); dtheta_deg=res_p10(pmag); dphi=res_p9(pmag);} else if(theta_deg>=35 && theta_deg<45) {dp=res_p4(pmag); dtheta_deg=res_p11(pmag); dphi=res_p9(pmag);} else if(theta_deg>=45 && theta_deg<55) {dp=res_p5(pmag); dtheta_deg=res_p12(pmag); dphi=res_p9(pmag);} else if(theta_deg>=55) { dtheta_deg=res_p12(pmag); dphi=res_p9(pmag); if(pmag<2.0) dp=res_p8(theta_deg); /// Note that this is different from the FORTRAN code due to mismatch from orginal study. else if(pmag>=2.0 && pmag<3.0) dp=res_p7(theta_deg); else if(pmag>=3.0) /// Note that this is different from the FORTRAN code due to mismatch from orginal study. dp=res_p6(theta_deg); } // Both dphi and dtheta are returned in degrees, so we convert back to radians dphi *= TMath::Pi()/180.0; dtheta = dtheta_deg*TMath::Pi()/180.0; // Generate the spearing double deltap = rnd.Gaus(0.0, dp); double deltatheta = rnd.Gaus(0.0, dtheta); double deltaphi = rnd.Gaus(0.0, dphi); pmag += deltap; theta += deltatheta; phi += deltaphi; // Set the 3momentum of the track with the new parameters DVector3 mom; mom.SetMagThetaPhi(pmag, theta, phi); trk->setMomentum(mom); trk->setMass(0.0); trk->p = pmag; trk->theta = theta; trk->phi = phi; // Set up the error matrix properly DMatrixDSym errMat(7); DMatrix sphErrMat(3,3); DMatrix transformMat(3,3); DMatrix transformMat_T(3,3); DMatrix cartErrMat(3,3); // Start off with a diagonal matrix in the spherical coordinates. sphErrMat[0][0] = dp*dp; sphErrMat[1][1] = dtheta*dtheta; sphErrMat[2][2] = dphi*dphi; // Transformation matrix // T_ij = dr_i/dx_j transformMat[0][0] = sin(theta)*cos(phi); transformMat[1][0] = pmag*cos(theta)*cos(phi); transformMat[2][0] = -pmag*sin(theta)*sin(phi); transformMat[0][1] = sin(theta)*sin(phi); transformMat[1][1] = pmag*cos(theta)*sin(phi); transformMat[2][1] = pmag*sin(theta)*cos(phi); transformMat[0][2] = cos(theta); transformMat[1][2] = -pmag*sin(theta); transformMat[2][2] = 0.0; // Carry out the conversion to cartesian coordinates transformMat_T.Transpose(transformMat); cartErrMat = transformMat_T * sphErrMat * transformMat; // Set up the full error matrix. // Note that we have not smeared the energy [3] nor // the vertex [4,5,6]. errMat[0][0] = cartErrMat[0][0]; errMat[0][1] = cartErrMat[0][1]; errMat[0][2] = cartErrMat[0][2]; errMat[1][0] = cartErrMat[1][0]; errMat[1][1] = cartErrMat[1][1]; errMat[1][2] = cartErrMat[1][2]; errMat[2][0] = cartErrMat[2][0]; errMat[2][1] = cartErrMat[2][1]; errMat[2][2] = cartErrMat[2][2]; // Set the error matrix trk->setErrorMatrix(errMat); } double DTrack_factory_THROWN::res_p1(double x) { // Return dpmag/pmag(theta) // 0=5.5768) { res = 0.16847; } return res; } double DTrack_factory_THROWN::res_p10(double x) { // Return dtheta/theta(p) // 0=4) { res=0.096163; } return res; } double DTrack_factory_THROWN::res_p11(double x) { // Return dtheta/theta(p) // 35=4) { res=0.1478; } return res; } double DTrack_factory_THROWN::res_p12(double x) { // Return dtheta/theta(p) // 45=4) { res=0.20749; } return res; }