// $Id$ // // File: DTrack_factory.cc // Created: Sun Apr 3 12:28:45 EDT 2005 // Creator: davidl (on Darwin Harriet.local 7.8.0 powerpc) // #include #include #include "GlueX.h" #include "JANA/JApplication.h" #include "JANA/JEventLoop.h" #include "DMagneticFieldStepper.h" #include "DTrackCandidate.h" #include "DTrack_factory.h" #include "DTrackHit.h" #define USE_MINUIT 0 #if USE_MINUIT // This is for MINUIT which is really not suited for a multi-threaded // event processing environment. We do a few backflips here ... static void FCN(int &npar, double *derivatives, double &chisq, double *par, int iflag); static pthread_mutex_t trk_mutex = PTHREAD_MUTEX_INITIALIZER; static JEventLoop *g_loop = NULL; static const DMagneticFieldMap *g_bfield = NULL; static JFactory *g_fac_trackhit; static const DTrackCandidate *g_trackcandidate; static double min_chisq, min_par[6]; static TMinuit *minuit=NULL; typedef struct{ double x,y,z; double dxdz, dydz; double d2xdz2, d2ydz2; }trk_step_t; #endif //------------------ // init //------------------ jerror_t DTrack_factory::init(void) { #if USE_MINUIT pthread_mutex_lock(&trk_mutex); if(minuit==NULL){ int icondn; minuit = new TMinuit(); minuit->mninit(0,0,0); minuit->SetFCN(FCN); minuit->mncomd("CLEAR", icondn); minuit->mncomd("SET PRI -1", icondn); minuit->mncomd("SET NOWARNINGS", icondn); minuit->mncomd("SET BATCH", icondn); minuit->mncomd("SET STRATEGY 2", icondn); minuit->mncomd("SET PRI -1", icondn); minuit->mncomd("SET NOWARNINGS", icondn); minuit->mncomd("SET BATCH", icondn); minuit->mncomd("SET STRATEGY 2", icondn); minuit->DefineParameter(0,"p", 0.0, 0.02, 0.0, 0.0); minuit->DefineParameter(1,"theta", 0.0, 0.17, 0.0, 0.0); minuit->DefineParameter(2,"phi", 0.0, 0.17, 0.0, 0.0); minuit->DefineParameter(3,"x", 0.0, 0.50, 0.0, 0.0); minuit->DefineParameter(4,"y", 0.0, 0.50, 0.0, 0.0); minuit->DefineParameter(5,"z", 0.0, 7.0, 0.0, 0.0); minuit->mncomd("FIX 4", icondn); minuit->mncomd("FIX 5", icondn); minuit->mncomd("FIX 6", icondn); } pthread_mutex_unlock(&trk_mutex); #endif return NOERROR; } //------------------ // brun //------------------ jerror_t DTrack_factory::brun(JEventLoop *loop, int runnumber) { dgeom = loop->GetJApplication()->GetJGeometry(runnumber); bfield = NULL; //bfield = dgeom->GetDMagneticFieldMap(); return NOERROR; } //------------------ // evnt //------------------ jerror_t DTrack_factory::evnt(JEventLoop *loop, int eventnumber) { // For now, we just copy from the MCTrackCandidates. Eventually, // a track fitter will be implemented. vector trackcandidates; vector trackhits; loop->Get(trackcandidates); #if USE_MINUIT JFactory *fac_trackhit = #endif loop->Get(trackhits,"MC"); for(unsigned int i=0; iq = trackcandidate->q; track->p = trackcandidate->p; track->theta = trackcandidate->theta; track->phi = trackcandidate->phi; track->x = 0.0; track->y = 0.0; track->z = trackcandidate->z_vertex; track->candidateid = trackcandidate->id; #if USE_MINUIT // Lock mutex so only one thread at a time accesses minuit pthread_mutex_lock(&trk_mutex); g_loop = loop; g_bfield = bfield; g_fac_trackhit = fac_trackhit; g_trackcandidate = trackcandidate; // Calculate chi-square value double par[6]; par[0] = track->p; par[1] = track->theta; par[2] = track->phi; par[3] = track->x; par[4] = track->y; par[5] = track->z; int npar=6; double dfdpar[6]; double chisq=0.0;; int iflag = 2; FCN(npar, dfdpar, chisq, par, iflag); // Set the initial parameter values for(int i=0;i<6;i++){ int icondn; char cmd[256]; sprintf(cmd, "SET PAR %d %f", i+1, par[i]); min_par[i] = par[i]; minuit->mncomd(cmd, icondn); } min_chisq = 1000.0; //minuit->Migrad(); //minuit->mncomd("MINIMIZE 100", icondn); //int icondn; minuit->mncomd("SEEK 100 1", icondn); //cout<<__FILE__<<":"<<__LINE__<<" initial:"<p = min_par[0]; track->theta = min_par[1]; track->phi = min_par[2]; track->x = min_par[3]; track->y = min_par[4]; track->z = min_par[5]; } #endif _data.push_back(track); } return NOERROR; } #if USE_MINUIT //------------------ // FCN -- for MINUIT //------------------ void FCN(int &npar, double *derivatives, double &chisq, double *par, int iflag) { // Step a singley charged particle with the momentum and vertex // position given by par through the magnetic field, calculating // the chisq from the closest hits. We need to keep track of the // positions and first and second derivatives of each step along // the trajectory. We will first step through field from vertex // until we either hit the approximate BCAL, UPV, or FCAL positions. // Minuit will sometimes try zero momentum tracks. Immediately return // a large ChiSq when that happens if(par[0] < 0.050){chisq=1000.0; return;} vector chisqv; TVector3 p; p.SetMagThetaPhi(par[0],par[1],par[2]); TVector3 pos(par[3],par[4],par[5]); DMagneticFieldStepper *stepper = new DMagneticFieldStepper(g_bfield, g_trackcandidate->q, &pos, &p); stepper->SetStepSize(0.1); // Step until we hit a boundary vector trk_steps; for(int i=0; i<10000; i++){ stepper->Step(&pos); trk_step_t trk_step; trk_step.x = pos.X(); trk_step.y = pos.Y(); trk_step.z = pos.Z(); trk_steps.push_back(trk_step); //if(pos.Perp()>65.0){cout<<__FILE__<<":"<<__LINE__<<" hit BCAL"<650.0){cout<<__FILE__<<":"<<__LINE__<<" hit FCAL"<65.0){break;} // ran into BCAL if(pos.Z()>650.0){break;} // ran into FCAL if(pos.Z()<-50.0){break;} // ran into UPV } delete stepper; #if 0 // Calculate first derivatives in trk_steps for(unsigned int i=1; idxdz = ((curr->x-prev->x)/(curr->z-prev->z) + (next->x-curr->x)/(next->z-curr->z))/2.0; curr->dydz = ((curr->y-prev->y)/(curr->z-prev->z) + (next->y-curr->y)/(next->z-curr->z))/2.0; } // Calculate second derivatives in trk_steps for(unsigned int i=2; id2xdz2 = ((curr->dxdz-prev->dxdz)/(curr->z-prev->z) + (next->dxdz-curr->dxdz)/(next->z-curr->z))/2.0; curr->d2ydz2 = ((curr->dydz-prev->dydz)/(curr->z-prev->z) + (next->dydz-curr->dydz)/(next->z-curr->z))/2.0; } #endif // Loop over the track hits for this candidate using // the closest trk_step to determine the distance // from the hit to the track. vector trackhits; vector& vptrs = g_fac_trackhit->Get(); for(unsigned int i=0; iz <= 0.0)continue; if(trackhit->z > 405.0)continue; double r = sqrt(pow((double)trackhit->x,2.0) + pow((double)trackhit->y,2.0)); if(r >= 65.0)continue; // We don't really want the hit closest physically in space. // Rather, we want the distance measured in standard deviations // of detector resolutions. This depends upon the detector type // from which the hit came. Note that this also depends on the // step size used in the stepper. The FDC in particular needs // much larger sigma values due to detector resolution alone. double sigmaxy; double sigmaz; switch(trackhit->system){ case SYS_CDC: sigmaxy = 0.80; sigmaz = 7.50; break; case SYS_FDC: sigmaxy = 0.50; sigmaz = 0.50; break; default: sigmaxy = 10.00; sigmaz = 10.00; } double xh = trackhit->x; double yh = trackhit->y; double zh = trackhit->z; // Loop over all steps to find the closest one to this hit double r2_min = 1.0E6; trk_step_t *trk_step_min=NULL; for(unsigned int j=0; jx; double ys = trk_step->y; double zs = trk_step->z; double r2 = pow((xh-xs)/sigmaxy,2.0) + pow((yh-ys)/sigmaxy,2.0) + pow((zh-zs)/sigmaz,2.0); //cout<<__FILE__<<":"<<__LINE__<<" dx="<q); printcol("%3.3f", track->p); printcol("%1.3f", track->theta); printcol("%1.3f", track->phi); printcol("%2.2f", track->x); printcol("%2.2f", track->y); printcol("%2.2f", track->z); printrow(); } return _table; }