Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackWireBased_factory.cc
Go to the documentation of this file.
1 // $Id: DTrackWireBased_factory.cc 5612 2009-10-15 20:51:25Z staylor $
2 //
3 // File: DTrackWireBased_factory.cc
4 // Created: Wed Sep 3 09:33:40 EDT 2008
5 // Creator: davidl (on Darwin harriet.jlab.org 8.11.1 i386)
6 //
7 
8 
9 #include <iostream>
10 #include <iomanip>
11 #include <set>
12 #include <cmath>
13 #include <mutex>
14 using namespace std;
15 
19 #include <CDC/DCDCTrackHit.h>
20 #include <FDC/DFDCPseudo.h>
21 #include <SplitString.h>
22 
23 #include <TROOT.h>
24 
25 using namespace jana;
26 
27 //------------------
28 // CDCSortByRincreasing
29 //------------------
30 bool CDCSortByRincreasing(const DCDCTrackHit* const &hit1, const DCDCTrackHit* const &hit2) {
31  // use the ring number to sort by R(decreasing) and then straw(increasing)
32  if(hit1->wire->ring == hit2->wire->ring){
33  return hit1->wire->straw < hit2->wire->straw;
34  }
35  return hit1->wire->ring < hit2->wire->ring;
36 }
37 
38 //------------------
39 // FDCSortByZincreasing
40 //------------------
41 bool FDCSortByZincreasing(const DFDCPseudo* const &hit1, const DFDCPseudo* const &hit2) {
42  // use the layer number to sort by Z(decreasing) and then wire(increasing)
43  if(hit1->wire->layer == hit2->wire->layer){
44  return hit1->wire->wire < hit2->wire->wire;
45  }
46  return hit1->wire->layer < hit2->wire->layer;
47 }
48 
49 
50 //------------------
51 // count_common_members
52 //------------------
53  template<typename T>
54 static unsigned int count_common_members(vector<T> &a, vector<T> &b)
55 {
56  unsigned int n=0;
57  for(unsigned int i=0; i<a.size(); i++){
58  for(unsigned int j=0; j<b.size(); j++){
59  if(a[i]==b[j])n++;
60  }
61  }
62 
63  return n;
64 }
65 
67  if (a->candidateid==b->candidateid) return a->mass()<b->mass();
68  return a->candidateid<b->candidateid;
69 }
70 
71 //------------------
72 // init
73 //------------------
75 {
76  fitter = NULL;
77 
78  //DEBUG_HISTS = true;
79  DEBUG_HISTS = false;
80  DEBUG_LEVEL = 0;
81 
82  gPARMS->SetDefaultParameter("TRKFIT:DEBUG_LEVEL",DEBUG_LEVEL);
83 
84  SKIP_MASS_HYPOTHESES_WIRE_BASED=true;
85  gPARMS->SetDefaultParameter("TRKFIT:SKIP_MASS_HYPOTHESES_WIRE_BASED",
86  SKIP_MASS_HYPOTHESES_WIRE_BASED);
87  PROTON_MOM_THRESH=0.8; // GeV
88  gPARMS->SetDefaultParameter("TRKFIT:PROTON_MOM_THRESH",
89  PROTON_MOM_THRESH);
90 
91  // Make list of mass hypotheses to use in fit
92  vector<int> hypotheses;
93  hypotheses.push_back(Positron);
94  hypotheses.push_back(PiPlus);
95  hypotheses.push_back(KPlus);
96  hypotheses.push_back(Proton);
97  hypotheses.push_back(Electron);
98  hypotheses.push_back(PiMinus);
99  hypotheses.push_back(KMinus);
100  hypotheses.push_back(AntiProton);
101 
102  ostringstream locMassStream;
103  for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i)
104  {
105  locMassStream << hypotheses[loc_i];
106  if(loc_i != (hypotheses.size() - 1))
107  locMassStream << ",";
108  }
109 
110  string HYPOTHESES = locMassStream.str();
111  gPARMS->SetDefaultParameter("TRKFIT:HYPOTHESES", HYPOTHESES);
112 
113  // Parse MASS_HYPOTHESES strings to make list of masses to try
114  hypotheses.clear();
115  SplitString(HYPOTHESES, hypotheses, ",");
116  for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i)
117  {
118  if(ParticleCharge(Particle_t(hypotheses[loc_i])) > 0)
119  mass_hypotheses_positive.push_back(hypotheses[loc_i]);
120  else if(ParticleCharge(Particle_t(hypotheses[loc_i])) < 0)
121  mass_hypotheses_negative.push_back(hypotheses[loc_i]);
122  }
123 
124  if(mass_hypotheses_positive.empty()){
125  static once_flag pwarn_flag;
126  call_once(pwarn_flag, [](){
127  jout << endl;
128  jout << "############# WARNING !! ################ " <<endl;
129  jout << "There are no mass hypotheses for positive tracks!" << endl;
130  jout << "Be SURE this is what you really want!" << endl;
131  jout << "######################################### " <<endl;
132  jout << endl;
133  });
134  }
135  if(mass_hypotheses_negative.empty()){
136  static once_flag nwarn_flag;
137  call_once(nwarn_flag, [](){
138  jout << endl;
139  jout << "############# WARNING !! ################ " <<endl;
140  jout << "There are no mass hypotheses for negative tracks!" << endl;
141  jout << "Be SURE this is what you really want!" << endl;
142  jout << "######################################### " <<endl;
143  jout << endl;
144  });
145  }
146  mNumHypPlus=mass_hypotheses_positive.size();
147  mNumHypMinus=mass_hypotheses_negative.size();
148 
149  return NOERROR;
150 }
151 
152 //------------------
153 // brun
154 //------------------
155 jerror_t DTrackWireBased_factory::brun(jana::JEventLoop *loop, int32_t runnumber)
156 {
157  // Get the geometry
158  DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication());
159  geom = dapp->GetDGeometry(runnumber);
160  // Check for magnetic field
161  const DMagneticFieldMap *bfield=dapp->GetBfield(runnumber);
162  dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(bfield) != NULL);
163 
164  if(dIsNoFieldFlag){
165  //Setting this flag makes it so that JANA does not delete the objects in
166  //_data. This factory will manage this memory.
167  //This is all of these pointers are just copied from the "StraightLine"
168  //factory, and should not be re-deleted.
169  SetFactoryFlag(NOT_OBJECT_OWNER);
170  }
171  else{
172  ClearFactoryFlag(NOT_OBJECT_OWNER); //This factory will create it's own obje
173  }
174 
175  // set up reference trajectory
176  rt = new DReferenceTrajectory(bfield);
177  rt->SetDGeometry(geom);
178 
179  // Get pointer to DTrackFitter object that actually fits a track
180  vector<const DTrackFitter *> fitters;
181  loop->Get(fitters);
182 
183  if(fitters.size()<1){
184  _DBG_<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl;
185  return RESOURCE_UNAVAILABLE;
186  }
187 
188  // Drop the const qualifier from the DTrackFitter pointer (I'm surely going to hell for this!)
189  fitter = const_cast<DTrackFitter*>(fitters[0]);
190 
191  // Warn user if something happened that caused us NOT to get a fitter object pointer
192  if(!fitter){
193  _DBG_<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl;
194  return RESOURCE_UNAVAILABLE;
195  }
196 
197  USE_HITS_FROM_CANDIDATE=false;
198  gPARMS->SetDefaultParameter("TRKFIT:USE_HITS_FROM_CANDIDATE",
199  USE_HITS_FROM_CANDIDATE);
200 
201  MIN_FIT_P = 0.050; // GeV
202  gPARMS->SetDefaultParameter("TRKFIT:MIN_FIT_P", MIN_FIT_P, "Minimum fit momentum in GeV/c for fit to be considered successful");
203 
204  if(DEBUG_HISTS){
205  dapp->Lock();
206 
207  // Histograms may already exist. (Another thread may have created them)
208  // Try and get pointers to the existing ones.
209 
210 
211  dapp->Unlock();
212  }
213 
214  // Get the particle ID algorithms
215  loop->GetSingle(dPIDAlgorithm);
216 
217  // Outer detector geometry parameters
218  if (geom->GetDIRCZ(dDIRCz)==false) dDIRCz=1000.;
219  geom->GetFCALZ(dFCALz);
220  vector<double>tof_face;
221  geom->Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z",
222  tof_face);
223  vector<double>tof_plane;
224  geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", tof_plane);
225  dTOFz=tof_face[2]+tof_plane[2];
226  geom->Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", tof_plane);
227  dTOFz+=tof_face[2]+tof_plane[2];
228  dTOFz*=0.5; // mid plane between tof planes
229 
230  // Get start counter geometry;
231  if (geom->GetStartCounterGeom(sc_pos,sc_norm)){
232  // Create vector of direction vectors in scintillator planes
233  for (int i=0;i<30;i++){
234  vector<DVector3>temp;
235  for (unsigned int j=0;j<sc_pos[i].size()-1;j++){
236  double dx=sc_pos[i][j+1].x()-sc_pos[i][j].x();
237  double dy=sc_pos[i][j+1].y()-sc_pos[i][j].y();
238  double dz=sc_pos[i][j+1].z()-sc_pos[i][j].z();
239  temp.push_back(DVector3(dx/dz,dy/dz,1.));
240  }
241  sc_dir.push_back(temp);
242  }
243  SC_END_NOSE_Z=sc_pos[0][12].z();
244  SC_BARREL_R=sc_pos[0][0].Perp();
245  SC_PHI_SECTOR1=sc_pos[0][0].Phi();
246  }
247 
248  return NOERROR;
249 }
250 
251 //------------------
252 // evnt
253 //------------------
254 jerror_t DTrackWireBased_factory::evnt(JEventLoop *loop, uint64_t eventnumber)
255 {
256 
257  if(!fitter)return NOERROR;
258 
259  if(dIsNoFieldFlag){
260  //Clear previous objects:
261  //JANA doesn't do it because NOT_OBJECT_OWNER was set
262  //It DID delete them though, in the "StraightLine" factory
263  _data.clear();
264 
265  vector<const DTrackWireBased*> locWireBasedTracks;
266  loop->Get(locWireBasedTracks, "StraightLine");
267  for(size_t loc_i = 0; loc_i < locWireBasedTracks.size(); ++loc_i)
268  _data.push_back(const_cast<DTrackWireBased*>(locWireBasedTracks[loc_i]));
269  return NOERROR;
270  }
271 
272  // Get candidates and hits
273  vector<const DTrackCandidate*> candidates;
274  loop->Get(candidates);
275 
276  if (candidates.size()==0) return NOERROR;
277 
278  // Loop over candidates
279  for(unsigned int i=0; i<candidates.size(); i++){
280  const DTrackCandidate *candidate = candidates[i];
281 
282  // Skip candidates with momentum below some cutoff
283  if (candidate->momentum().Mag()<MIN_FIT_P){
284  continue;
285  }
286 
287  if (SKIP_MASS_HYPOTHESES_WIRE_BASED){
288  rt->Reset();
289  rt->q = candidate->charge();
290 
291  DoFit(i,candidate,rt,loop,ParticleMass(PiPlus));
292  // Only do fit for proton mass hypothesis for low momentum particles
293  if (candidate->momentum().Mag()<PROTON_MOM_THRESH){
294  rt->Reset();
295  DoFit(i,candidate,rt,loop,ParticleMass(Proton));
296  }
297  }
298  else{
299  // Choose list of mass hypotheses based on charge of candidate
300  vector<int> mass_hypotheses;
301  if(candidate->charge()<0.0){
302  mass_hypotheses = mass_hypotheses_negative;
303  }else{
304  mass_hypotheses = mass_hypotheses_positive;
305  }
306 
307  if ((!isfinite(candidate->momentum().Mag())) || (!isfinite(candidate->position().Mag())))
308  _DBG_ << "Invalid seed data for event "<< eventnumber <<"..."<<endl;
309 
310  // Loop over potential particle masses
311  for(unsigned int j=0; j<mass_hypotheses.size(); j++){
312  if(DEBUG_LEVEL>1){_DBG__;_DBG_<<"---- Starting wire based fit with id: "<<mass_hypotheses[j]<<endl;}
313 
314  rt->Reset();
315  rt->q = candidate->charge();
316  DoFit(i,candidate,rt,loop,ParticleMass(Particle_t(mass_hypotheses[j])));
317  }
318 
319  }
320  }
321 
322  // Filter out duplicate tracks
323  FilterDuplicates();
324 
325  // Add any missing hypotheses
326  if (SKIP_MASS_HYPOTHESES_WIRE_BASED==false){
327  InsertMissingHypotheses();
328  }
329 
330  return NOERROR;
331 }
332 
333 
334 //------------------
335 // erun
336 //------------------
338 {
339  if (rt) delete rt;
340  return NOERROR;
341 }
342 
343 //------------------
344 // fini
345 //------------------
347 {
348 
349  return NOERROR;
350 }
351 
352 //------------------
353 // FilterDuplicates
354 //------------------
356 {
357  /// Look through all current DTrackWireBased objects and remove any
358  /// that have all of their hits in common with another track
359 
360  if(_data.size()==0)return;
361 
362  if(DEBUG_LEVEL>2)_DBG_<<"Looking for clones of wire-based tracks ..."<<endl;
363 
364  set<unsigned int> indexes_to_delete;
365  for(unsigned int i=0; i<_data.size()-1; i++){
366  DTrackWireBased *dtrack1 = _data[i];
367 
368  vector<const DCDCTrackHit*> cdchits1;
369  vector<const DFDCPseudo*> fdchits1;
370  dtrack1->Get(cdchits1);
371  dtrack1->Get(fdchits1);
372 
373  JObject::oid_t cand1=dtrack1->candidateid;
374  for(unsigned int j=i+1; j<_data.size(); j++){
375  DTrackWireBased *dtrack2 = _data[j];
376  if (dtrack2->candidateid==cand1) continue;
377  if (dtrack2->mass() != dtrack1->mass())continue;
378 
379  vector<const DCDCTrackHit*> cdchits2;
380  vector<const DFDCPseudo*> fdchits2;
381  dtrack2->Get(cdchits2);
382  dtrack2->Get(fdchits2);
383 
384  // Count number of cdc and fdc hits in common
385  unsigned int Ncdc = count_common_members(cdchits1, cdchits2);
386  unsigned int Nfdc = count_common_members(fdchits1, fdchits2);
387  unsigned int total = Ncdc + Nfdc;
388 
389  if (total==0) continue;
390  if(Ncdc!=cdchits1.size() && Ncdc!=cdchits2.size())continue;
391  if(Nfdc!=fdchits1.size() && Nfdc!=fdchits2.size())continue;
392 
393  unsigned int total1 = cdchits1.size()+fdchits1.size();
394  unsigned int total2 = cdchits2.size()+fdchits2.size();
395  if(total!=total1 && total!=total2)continue;
396 
397  if(total1<total2){
398  // The two track candidates actually correspond to
399  // a single track. Set the candidate id for this
400  // track to the candidate id from the clone match to
401  // prevent multiple clone tracks confusing matters
402  // at a later stage of the reconstruction...
403  _data[j]->candidateid=cand1;
404  indexes_to_delete.insert(i);
405  }else{
406  indexes_to_delete.insert(j);
407  }
408 
409  }
410  }
411 
412  if(DEBUG_LEVEL>2)_DBG_<<"Found "<<indexes_to_delete.size()<<" wire-based clones"<<endl;
413 
414  // Return now if we're keeping everyone
415  if(indexes_to_delete.size()==0)return;
416 
417  // Copy pointers that we want to keep to a new container and delete
418  // the clone objects
419  vector<DTrackWireBased*> new_data;
420  for(unsigned int i=0; i<_data.size(); i++){
421  if(indexes_to_delete.find(i)==indexes_to_delete.end()){
422  new_data.push_back(_data[i]);
423  }else{
424  delete _data[i];
425  if(DEBUG_LEVEL>1)_DBG_<<"Deleting clone wire-based track "<<i<<endl;
426  }
427  }
428  _data = new_data;
429 }
430 
431 // Routine to find the hits, do the fit, and fill the list of wire-based tracks
432 void DTrackWireBased_factory::DoFit(unsigned int c_id,
433  const DTrackCandidate *candidate,
435  JEventLoop *loop, double mass){
436  // Get the hits from the candidate
437  vector<const DFDCPseudo*>myfdchits;
438  candidate->GetT(myfdchits);
439  vector<const DCDCTrackHit *>mycdchits;
440  candidate->GetT(mycdchits);
441 
442  // Do the fit
444  if (USE_HITS_FROM_CANDIDATE) {
445  fitter->Reset();
447 
448  fitter->AddHits(myfdchits);
449  fitter->AddHits(mycdchits);
450 
451  status=fitter->FitTrack(candidate->position(),candidate->momentum(),
452  candidate->charge(),mass,0.);
453  }
454  else{
455  fitter->Reset();
457  // Swim a reference trajectory using the candidate starting momentum
458  // and position
459  rt->SetMass(mass);
460  //rt->Swim(candidate->position(),candidate->momentum(),candidate->charge());
461  rt->FastSwimForHitSelection(candidate->position(),candidate->momentum(),candidate->charge());
462 
463  status=fitter->FindHitsAndFitTrack(*candidate,rt,loop,mass,
464  mycdchits.size()+2*myfdchits.size());
465  if (/*false && */status==DTrackFitter::kFitNotDone){
466  if (DEBUG_LEVEL>1)_DBG_ << "Using hits from candidate..." << endl;
467  fitter->Reset();
468 
469  fitter->AddHits(myfdchits);
470  fitter->AddHits(mycdchits);
471 
472  status=fitter->FitTrack(candidate->position(),candidate->momentum(),
473  candidate->charge(),mass,0.);
474  }
475  }
476 
477  // if the fit returns chisq=-1, something went terribly wrong...
478  if (fitter->GetChisq()<0){
480  }
481 
482  // Check the status of the fit
483  switch(status){
485  //_DBG_<<"Fitter returned kFitNotDone. This should never happen!!"<<endl;
487  break;
490  if(!isfinite(fitter->GetFitParameters().position().X())) break;
491  {
492  // Make a new wire-based track
494  *static_cast<DTrackingData*>(track) = fitter->GetFitParameters();
495 
496  track->chisq = fitter->GetChisq();
497  track->Ndof = fitter->GetNdof();
498  track->FOM = TMath::Prob(track->chisq, track->Ndof);
499  track->pulls =std::move(fitter->GetPulls());
500  track->extrapolations=std::move(fitter->GetExtrapolations());
501  track->candidateid = c_id+1;
502 
503  // Add hits used as associated objects
504  vector<const DCDCTrackHit*> cdchits = fitter->GetCDCFitHits();
505  vector<const DFDCPseudo*> fdchits = fitter->GetFDCFitHits();
506  sort(cdchits.begin(), cdchits.end(), CDCSortByRincreasing);
507  sort(fdchits.begin(), fdchits.end(), FDCSortByZincreasing);
508  for(unsigned int m=0; m<cdchits.size(); m++)track->AddAssociatedObject(cdchits[m]);
509  for(unsigned int m=0; m<fdchits.size(); m++)track->AddAssociatedObject(fdchits[m]);
510 
511  // Set CDC ring & FDC plane hit patterns before candidate tracks are associated
512  vector<const DCDCTrackHit*> tempCDCTrackHits;
513  vector<const DFDCPseudo*> tempFDCPseudos;
514  track->Get(tempCDCTrackHits);
515  track->Get(tempFDCPseudos);
516  track->dCDCRings = dPIDAlgorithm->Get_CDCRingBitPattern(tempCDCTrackHits);
517  track->dFDCPlanes = dPIDAlgorithm->Get_FDCPlaneBitPattern(tempFDCPseudos);
518 
519  // Add DTrackCandidate as associated object
520  track->AddAssociatedObject(candidate);
521 
522  _data.push_back(track);
523  break;
524  }
525  default:
526  break;
527  }
528 }
529 
530 // If the fit failed for certain hypotheses, fill in the gaps using data from
531 // successful fits for each candidate.
533  if (_data.size()==0) return false;
534 
535  // Make sure the tracks are ordered by candidate id
536  sort(_data.begin(),_data.end(),DTrackWireBased_cmp);
537 
538  JObject::oid_t old_id=_data[0]->candidateid;
539  unsigned int mass_bits=0;
540  double q=_data[0]->charge();
541  vector<DTrackWireBased*>myhypotheses;
542  vector<DTrackWireBased*>tracks_to_add;
543  for (size_t i=0;i<_data.size();i++){
544  if (_data[i]->candidateid!=old_id){
545  int num_hyp=myhypotheses.size();
546  if ((q<0 && num_hyp!=mNumHypMinus)||(q>0 && num_hyp!=mNumHypPlus)){
547  AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q);
548  }
549 
550  // Clear the myhypotheses vector for the next track
551  myhypotheses.clear();
552  // Reset charge
553  q=_data[i]->charge();
554 
555  // Set the bit for this mass hypothesis
556  mass_bits = 1<<_data[i]->PID();
557 
558  // Add the data to the myhypotheses vector
559  myhypotheses.push_back(_data[i]);
560  }
561  else{
562  myhypotheses.push_back(_data[i]);
563 
564  // Set the bit for this mass hypothesis
565  mass_bits |= 1<< _data[i]->PID();
566  }
567 
568  old_id=_data[i]->candidateid;
569  }
570  // Deal with last track candidate
571  int num_hyp=myhypotheses.size();
572  if ((q<0 && num_hyp!=mNumHypMinus)||(q>0 && num_hyp!=mNumHypPlus)){
573  AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q);
574  }
575 
576  // Add the new list of tracks to the output list
577  if (tracks_to_add.size()>0){
578  for (size_t i=0;i<tracks_to_add.size();i++){
579  _data.push_back(tracks_to_add[i]);
580  }
581  // Make sure the tracks are ordered by candidate id
582  sort(_data.begin(),_data.end(),DTrackWireBased_cmp);
583  }
584 
585  return true;
586 }
587 
588 // Create a track with a mass hypothesis that was not present in the list of
589 // fitted tracks from an existing fitted track.
590 void DTrackWireBased_factory::AddMissingTrackHypothesis(vector<DTrackWireBased*>&tracks_to_add,
591  const DTrackWireBased *src_track,
592  double my_mass,
593  double q){
594  // Create a new wire-based track object
595  DTrackWireBased *wirebased_track = new DTrackWireBased();
596  *static_cast<DTrackingData*>(wirebased_track) = *static_cast<const DTrackingData*>(src_track);
597 
598  // Copy over DKinematicData part from the result of a successful fit
599  wirebased_track->setPID(IDTrack(q, my_mass));
600  wirebased_track->chisq = src_track->chisq;
601  wirebased_track->Ndof = src_track->Ndof;
602  wirebased_track->pulls = src_track->pulls;
603  wirebased_track->extrapolations = src_track->extrapolations;
604  wirebased_track->candidateid=src_track->candidateid;
605  wirebased_track->FOM=src_track->FOM;
606  wirebased_track->IsSmoothed=src_track->IsSmoothed;
607  wirebased_track->dCDCRings=src_track->dCDCRings;
608  wirebased_track->dFDCPlanes=src_track->dFDCPlanes;
609 
610  // (Partially) compensate for the difference in energy loss between the
611  // source track and a particle of mass my_mass
612  DVector3 position,momentum;
613  if (wirebased_track->extrapolations.at(SYS_CDC).size()>0){
614  unsigned int index=wirebased_track->extrapolations.at(SYS_CDC).size()-1;
615  position=wirebased_track->extrapolations[SYS_CDC][index].position;
616  momentum=wirebased_track->extrapolations[SYS_CDC][index].momentum;
617  }
618  else if (wirebased_track->extrapolations.at(SYS_FDC).size()>0){
619  unsigned int index=wirebased_track->extrapolations.at(SYS_FDC).size()-1;
620  position=wirebased_track->extrapolations[SYS_FDC][index].position;
621  momentum=wirebased_track->extrapolations[SYS_FDC][index].momentum;
622  }
623  if (momentum.Mag()>0.){
624  CorrectForELoss(position,momentum,q,my_mass);
625 
626  wirebased_track->setMomentum(momentum);
627  wirebased_track->setPosition(position);
628  }
629 
630  // Get the hits used in the fit and add them as associated objects
631  vector<const DCDCTrackHit *>cdchits;
632  src_track->GetT(cdchits);
633  vector<const DFDCPseudo *>fdchits;
634  src_track->GetT(fdchits);
635  for(unsigned int m=0; m<fdchits.size(); m++)
636  wirebased_track->AddAssociatedObject(fdchits[m]);
637  for(unsigned int m=0; m<cdchits.size(); m++)
638  wirebased_track->AddAssociatedObject(cdchits[m]);
639 
640  tracks_to_add.push_back(wirebased_track);
641 }
642 
643 // Use the FastSwim method in DReferenceTrajectory to propagate back to the
644 // POCA to the beam line, adding a bit of energy at each step that would have
645 // been lost had the particle emerged from the target.
646 void DTrackWireBased_factory::CorrectForELoss(DVector3 &position,DVector3 &momentum,double q,double my_mass){
647  rt->Reset();
648  rt->q = q;
649  rt->SetMass(my_mass);
650  rt->SetPLossDirection(DReferenceTrajectory::kBackward);
651  DVector3 last_pos,last_mom;
652  DVector3 origin(0.,0.,65.);
653  DVector3 dir(0.,0.,1.);
654  rt->FastSwim(position,momentum,last_pos,last_mom,rt->q,origin,dir,300.);
655  position=last_pos;
656  momentum=last_mom;
657 }
658 
659 
660 // Fill in all missing hypotheses for a given track candidate
662  vector<DTrackWireBased*>&tracks_to_add,
663  vector<DTrackWireBased *>&myhypotheses,
664  double q){
665  Particle_t negative_particles[3]={KMinus,PiMinus,Electron};
666  Particle_t positive_particles[3]={KPlus,PiPlus,Positron};
667 
668  unsigned int last_index=myhypotheses.size()-1;
669  if (q>0){
670  if ((mass_bits & (1<<Proton))==0){
671  AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
672  ParticleMass(Proton),+1.);
673  }
674  for (int i=0;i<3;i++){
675  if ((mass_bits & (1<<positive_particles[i]))==0){
676  AddMissingTrackHypothesis(tracks_to_add,myhypotheses[0],
677  ParticleMass(positive_particles[i]),+1.);
678  }
679  }
680  }
681  else{
682  if ((mass_bits & (1<<AntiProton))==0){
683  AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index],
684  ParticleMass(Proton),-1.);
685  }
686  for (int i=0;i<3;i++){
687  if ((mass_bits & (1<<negative_particles[i]))==0){
688  AddMissingTrackHypothesis(tracks_to_add,myhypotheses[0],
689  ParticleMass(negative_particles[i]),-1.);
690  }
691  }
692  }
693 }
map< DetectorSystem_t, vector< DTrackFitter::Extrapolation_t > > extrapolations
int GetNdof(void) const
Definition: DTrackFitter.h:155
Definition: track.h:16
void AddMissingTrackHypothesis(vector< DTrackWireBased * > &tracks_to_add, const DTrackWireBased *src_track, double my_mass, double q)
void setMomentum(const DVector3 &aMomentum)
DApplication * dapp
vector< pull_t > & GetPulls(void)
Definition: DTrackFitter.h:162
float chisq
Chi-squared for the track (not chisq/dof!)
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
The DTrackFitter class is a base class for different charged track fitting algorithms. It does not actually fit the track itself, but provides the interface and some common support features most algorthims will need to implement.
Definition: DTrackFitter.h:61
TVector3 DVector3
Definition: DVector3.h:14
double total
Definition: FitGains.C:151
void AddHits(vector< const DCDCTrackHit * > cdchits)
DMagneticFieldMap * GetBfield(unsigned int run_number=1)
void SetMass(double mass)
const DVector3 & position(void) const
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
unsigned int dFDCPlanes
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
jerror_t brun(jana::JEventLoop *loop, int32_t runnumber)
Called everytime a new run number is detected.
jerror_t fini(void)
Called after last event of last event source has been processed.
static int ParticleCharge(Particle_t p)
static char index(char c)
Definition: base64.cpp:115
Definition: GlueX.h:17
int layer
1-24
Definition: DFDCWire.h:16
void AddMissingTrackHypotheses(unsigned int mass_bits, vector< DTrackWireBased * > &tracks_to_add, vector< DTrackWireBased * > &hypotheses, double q)
fit_status_t FindHitsAndFitTrack(const DKinematicData &starting_params, const DReferenceTrajectory *rt, JEventLoop *loop, double mass=-1.0, int N=0, double t0=QuietNaN, DetectorSystem_t t0_det=SYS_NULL)
mass&lt;0 means get it from starting_params
void Reset(void)
Definition: DTrackFitter.cc:94
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
vector< DTrackFitter::pull_t > pulls
Holds pulls used in chisq calc. (not including off-diagonals)
void FastSwimForHitSelection(const DVector3 &pos, const DVector3 &mom, double q)
const map< DetectorSystem_t, vector< Extrapolation_t > > & GetExtrapolations(void) const
Definition: DTrackFitter.h:163
jerror_t init(void)
Called once at program start.
void CorrectForELoss(DVector3 &position, DVector3 &momentum, double q, double mass)
double GetChisq(void) const
Definition: DTrackFitter.h:154
Definition: GlueX.h:18
int straw
Definition: DCDCWire.h:81
void SetFitType(fit_type_t type)
Definition: DTrackFitter.h:170
void SplitString(string str, vector< T > &vec, const string &delim=" ")
Definition: SplitString.h:7
DGeometry * GetDGeometry(unsigned int run_number)
#define _DBG_
Definition: HDEVIO.h:12
bool FDCSortByZincreasing(DTrackCandidate_factory_FDC::DFDCTrkHit *const &hit1, DTrackCandidate_factory_FDC::DFDCTrkHit *const &hit2)
double charge(void) const
#define _DBG__
Definition: HDEVIO.h:13
const vector< const DCDCTrackHit * > & GetCDCFitHits(void) const
Definition: DTrackFitter.h:139
static unsigned int count_common_members(vector< T > &a, vector< T > &b)
jerror_t evnt(jana::JEventLoop *loop, uint64_t eventnumber)
Called every event.
&lt;A href=&quot;index.html#legend&quot;&gt; &lt;IMG src=&quot;CORE.png&quot; width=&quot;100&quot;&gt; &lt;/A&gt;
int Ndof
Number of degrees of freedom in the fit.
void setPID(Particle_t locPID)
const vector< const DFDCPseudo * > & GetFDCFitHits(void) const
Definition: DTrackFitter.h:140
static double ParticleMass(Particle_t p)
unsigned int dCDCRings
const DVector3 & momentum(void) const
void DoFit(unsigned int c_id, const DTrackCandidate *candidate, DReferenceTrajectory *rt, jana::JEventLoop *loop, double mass)
fit_status_t FitTrack(const DVector3 &pos, const DVector3 &mom, double q, double mass, double t0=QuietNaN, DetectorSystem_t t0_det=SYS_NULL)
const DTrackFitter * fitter
int wire
1-N
Definition: DFDCWire.h:17
bool DTrackWireBased_cmp(DTrackWireBased *a, DTrackWireBased *b)
int ring
Definition: DCDCWire.h:80
oid_t candidateid
which DTrackCandidate this came from
void setPosition(const DVector3 &aPosition)
TDirectory * dir
Definition: bcal_hist_eff.C:31
static Particle_t IDTrack(float locCharge, float locMass)
bool CDCSortByRincreasing(const DCDCTrackHit *const &hit1, const DCDCTrackHit *const &hit2)
TH2F * temp
double mass(void) const
Particle_t
Definition: particleType.h:12
const DTrackingData & GetFitParameters(void) const
Definition: DTrackFitter.h:153