// $Id$ // // File: DParticle_factory.cc // Created: Thu Sep 4 14:02:44 EDT 2008 // Creator: davidl (on Darwin harriet.jlab.org 8.11.1 i386) // #include #include using namespace std; #include "DParticle_factory.h" #include #include #include #include using namespace jana; //------------------ // init //------------------ jerror_t DParticle_factory::init(void) { fitter = NULL; DEBUG_LEVEL = 0; gPARMS->SetDefaultParameter("TRKFIT:DEBUG_LEVEL", DEBUG_LEVEL); return NOERROR; } //------------------ // brun //------------------ jerror_t DParticle_factory::brun(jana::JEventLoop *loop, int runnumber) { // Get pointer to TrackFitter object that actually fits a track vector fitters; loop->Get(fitters); if(fitters.size()<1){ _DBG_<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<(fitters[0]); // Warn user if something happened that caused us NOT to get a fitter object pointer if(!fitter){ _DBG_<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<SetDefaultParameter("TRKFIT:MASS_HYPOTHESES", MASS_HYPOTHESES); // Reserve the first mass hypothesis slot for the one decided on by the wire-base fit mass_hypotheses.push_back(0.0); // Parse MASS_HYPOTHESES string to make list of masses to try if(MASS_HYPOTHESES.length()>0){ string &str = MASS_HYPOTHESES; unsigned int cutAt; while( (cutAt = str.find(",")) != (unsigned int)str.npos ){ if(cutAt > 0)mass_hypotheses.push_back(atof(str.substr(0,cutAt).c_str())); str = str.substr(cutAt+1); } if(str.length() > 0)mass_hypotheses.push_back(atof(str.c_str())); } return NOERROR; } //------------------ // evnt //------------------ jerror_t DParticle_factory::evnt(JEventLoop *loop, int eventnumber) { if(!fitter)return NOERROR; // Get candidates and hits vector tracks; loop->Get(tracks); // Loop over candidates for(unsigned int i=0; iGetDMagneticFieldMap())); DReferenceTrajectory *rt = rtv[_data.size()]; // Copy in the mass from the wire-based fit as the first one to try mass_hypotheses[0] = track->mass(); // Loop over potential particle masses until one is found that gives a chisq/Ndof<3.0 // If none does, then use the one with the smallest chisq DParticle *best_track = NULL; double best_fom = 0.0; for(unsigned int j=0; j1.0E-5)break; // Don't try the same mass twice! if(j!=0 && mass_hypotheses[j]==mass_hypotheses[0])continue; if(DEBUG_LEVEL>1){_DBG__;_DBG_<<"---- Starting time based fit with mass: "<SetFitType(DTrackFitter::kTimeBased); DTrackFitter::fit_status_t status = fitter->FindHitsAndFitTrack(*track, rt, loop, mass_hypotheses[j]); DParticle *dparticle = NULL; switch(status){ case DTrackFitter::kFitNotDone: _DBG_<<"Fitter returned kFitNotDone. This should never happen!!"<Ndof < 1){ if(DEBUG_LEVEL>1)_DBG_<<"-- new track with mass "<1)_DBG_<<"-- first successful fit this candidate with mass: "< best_fom){ if(DEBUG_LEVEL>1)_DBG_<<"-- new best track with mass "<1)_DBG_<<"-- keeping best track with mass "<mass()<<" (old chisq/Ndof="<<(best_track->chisq/best_track->Ndof)<<" , new chisq/Ndof="<<(dparticle->chisq/dparticle->Ndof)<<") (old fom="<GetDMagneticFieldMap())); DReferenceTrajectory *rt = rtv[_data.size()]; DParticle *particle = new DParticle; // Copy over DKinematicData part DKinematicData *track_kd = particle; *track_kd = fitter->GetFitParameters(); rt->SetMass(track_kd->mass()); rt->Swim(particle->position(), particle->momentum(), particle->charge()); particle->rt = rt; particle->chisq = fitter->GetChisq(); particle->Ndof = fitter->GetNdof(); particle->trackid = track->id; // Add hits used as associated objects const vector &cdchits = fitter->GetCDCFitHits(); const vector &fdchits = fitter->GetFDCFitHits(); for(unsigned int i=0; iAddAssociatedObject(cdchits[i]); for(unsigned int i=0; iAddAssociatedObject(fdchits[i]); // Add DTrack object as associate object particle->AddAssociatedObject(track); return particle; } //------------------ // GetFOM //------------------ double DParticle_factory::GetFOM(DParticle *dparticle) { //double range_out_fom = GetRangeOutFOM(dtrack); double chisq_per_dof = dparticle->chisq/(double)dparticle->Ndof; return chisq_per_dof; //double total_fom = exp(-pow(range_out_fom/0.5, 2.0))*exp(-pow(chisq_per_dof/2.0, 2.0)); //return total_fom; } //------------------ // GetRangeOutFOM //------------------ double DParticle_factory::GetRangeOutFOM(DParticle *dparticle) { /// Calculate a figure of merit for the track ranging out within the /// detector. If the particle does range out (lose all of its energy) /// then the value returned would be essentially zero. If it does not, /// then the value will be greater than zero. /// /// The FOM is ratio of the total pathlength of the track to the /// pathlength to the outermost wire associated with the track. /// Therefore, FOM=1 corresponds to a track that goes just /// as far after it hit the last wire as before, before finally /// hitting the BCAL, FCAL, etc... // We want the pathlength to the last wire that is on this track // (as determined by the DParticleHitSelector??? class). Since the // tracks can curl back in toward the beamline, we have to check every // wire to see what the pathlength to it is // Need the reference trajectory to find pathlengths DReferenceTrajectory *rt = const_cast(dparticle->rt); // Look first at FDC hits vector fdchits; dparticle->Get(fdchits); const DCoordinateSystem *outermost_wire = NULL; double s_to_outermost_wire=-1.0; for(unsigned int i=0; iFindClosestSwimStep(fdchits[i]->wire); if(step->s > s_to_outermost_wire){ s_to_outermost_wire = step->s; outermost_wire = fdchits[i]->wire; } } // Check CDC if no FDC wire was found if(!outermost_wire){ vector cdchits; dparticle->Get(cdchits); for(unsigned int i=0; iFindClosestSwimStep(cdchits[i]->wire); if(step->s > s_to_outermost_wire){ s_to_outermost_wire = step->s; outermost_wire = cdchits[i]->wire; } } } // Make sure *a* wire was found. (This is just a dummy check) if(!outermost_wire){ _DBG_<<"ERROR: No outermost wire found for track!"<rt->swim_steps[dparticle->rt->Nswim_steps-1].s; // Calculate figure of merit double fom = (total_s - s_to_outermost_wire)/s_to_outermost_wire; return fom; }