Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackCandidate_factory_FDCCathodes.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTrackCandidate_factory_FDCCathodes.cc
4 // Created: Tue Nov 6 13:37:08 EST 2007
5 // Creator: staylor (on Linux ifarml1.jlab.org 2.4.21-47.0.1.ELsmp i686)
6 //
7 /// This factory links segments in the FDC packages into track candidates
8 /// by swimming through the field from one package to the next.
9 
11 #include "DANA/DApplication.h"
12 #include <JANA/JCalibration.h>
13 #include "FDC/DFDCPseudo_factory.h"
15 #include "DHelicalFit.h"
16 #include "DHoughFind.h"
17 #include <TROOT.h>
18 #include <TH1F.h>
19 #include <TH2F.h>
20 
21 ///
22 /// DTrackCandidate_factory_FDCCathodes::brun():
23 ///
24 jerror_t DTrackCandidate_factory_FDCCathodes::brun(JEventLoop* eventLoop,
25  int32_t runnumber) {
26  DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
27  bfield = dapp->GetBfield(runnumber);
28  FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.;
29 
30  const DGeometry *dgeom = dapp->GetDGeometry(runnumber);
31 
32  USE_FDC=true;
33  if (!dgeom->GetFDCZ(z_wires)){
34  _DBG_<< "FDC geometry not available!" <<endl;
35  USE_FDC=false;
36  }
37 
38  JCalibration *jcalib = dapp->GetJCalibration(runnumber);
39  map<string, double> targetparms;
40  if (jcalib->Get("TARGET/target_parms",targetparms)==false){
41  TARGET_Z = targetparms["TARGET_Z_POSITION"];
42  }
43  else{
44  dgeom->GetTargetZ(TARGET_Z);
45  }
46 
47  DEBUG_HISTS=false;
48  gPARMS->SetDefaultParameter("TRKFIND:DEBUG_HISTS", DEBUG_HISTS);
49 
50  BEAM_VAR=1.;
51  gPARMS->SetDefaultParameter("TRKFIND:BEAM_VAR",BEAM_VAR);
52 
54  gPARMS->SetDefaultParameter("TRKFIND:FDC_HOUGH_THRESHOLD",FDC_HOUGH_THRESHOLD);
55 
56  if(DEBUG_HISTS) {
57  dapp->Lock();
58  match_dist_fdc=(TH2F*)gROOT->FindObject("match_dist_fdc");
59  if (!match_dist_fdc){
60  match_dist_fdc=new TH2F("match_dist_fdc",
61  "Matching distance for connecting FDC segments",
62  50,0.,7,500,0,100.);
63  }
64  match_center_dist2=(TH2F*)gROOT->FindObject("match_center_dist2");
65  if (!match_center_dist2){
66  match_center_dist2=new TH2F("match_center_dist2","matching distance squared between two circle centers vs p",50,0,1.5,100,0,100);
67  match_center_dist2->SetXTitle("p [GeV/c]");
68  match_center_dist2->SetYTitle("(#Deltad)^{2} [cm^{2}]");
69  }
70 
71  dapp->Unlock();
72  }
73 
74  // Initialize the stepper
76  stepper->SetStepSize(1.0);
77 
78  return NOERROR;
79 }
80 
81 
82 //------------------
83 // erun
84 //------------------
86 {
87  if (stepper) {
88  delete stepper;
89  stepper = nullptr;
90  }
91 
92  return NOERROR;
93 }
94 //------------------
95 // fini
96 //------------------
98 {
99  if (stepper) {
100  delete stepper;
101  stepper = nullptr;
102  }
103 
104  return NOERROR;
105 }
106 
107 
108 // Local routine for sorting segments by charge and curvature
109 inline bool DTrackCandidate_segment_cmp(const DFDCSegment *a, const DFDCSegment *b){
110  // double k1=a->S(0,0),k2=b->S(0,0);
111  //double q1=k1/fabs(k1),q2=k2/fabs(k2);
112  //if (q1!=q2) return q1<q2;
113  //return fabs(k1)<fabs(k2);
114  if (a->q!=b->q) return a->q<b->q;
115  return a->rc>b->rc;
116 }
117 
118 
120  const DFDCSegment *b){
121  return (a->hits[0]->wire->origin.z()<b->hits[0]->wire->origin.z());
122 }
123 
124 
125 //------------------
126 // evnt: main segment linking routine
127 //------------------
128 jerror_t DTrackCandidate_factory_FDCCathodes::evnt(JEventLoop *loop, uint64_t eventnumber)
129 {
130  if (!USE_FDC) return NOERROR;
131 
132  vector<const DFDCSegment*>segments;
133  eventLoop->Get(segments);
134 
135  // abort if there are no segments
136  if (segments.size()==0.) return NOERROR;
137 
138  std::stable_sort(segments.begin(), segments.end(), DTrackCandidate_segment_cmp);
139 
140  // Group segments by package
141  vector<DFDCSegment*>packages[4];
142  for (unsigned int i=0;i<segments.size();i++){
143  const DFDCSegment *segment=segments[i];
144  packages[segment->package].push_back((DFDCSegment*)segment);
145  }
146  // Keep track of the segments in each package that have been paired with
147  // other segments
148  vector<vector<int> >is_paired;
149  for (unsigned int i=0;i<4;i++){
150  vector<int>temp(packages[i].size());
151  is_paired.push_back(temp);
152  }
153  // Loop over all the packages to match to segments in packages downstream
154  // of the current package
155  vector<pair<const DFDCSegment*,const DFDCSegment*> >paired_segments;
156  for (unsigned int i=0;i<3;i++){
157  if (packages[i].size()>0) LinkSegments(i,packages,paired_segments,is_paired);
158  }
159 
160  // Link pairs of segments into groups of three linked segments
161  vector<vector<const DFDCSegment *> >triplets;
162  vector<int>is_tripled(paired_segments.size());
163  for (unsigned int i=0;i<paired_segments.size();i++){
164  for (unsigned int j=0;j<paired_segments.size();j++){
165  if (i==j) continue;
166  if (is_tripled[i] || is_tripled[j]) continue;
167  if (paired_segments[i].second==paired_segments[j].first){
168  is_tripled[i]=1;
169  is_tripled[j]=1;
170 
171  vector<const DFDCSegment *>triplet;
172  triplet.push_back(paired_segments[i].first);
173  triplet.push_back(paired_segments[i].second);
174  triplet.push_back(paired_segments[j].second);
175  triplets.push_back(triplet);
176  }
177  }
178  }
179 
180 
181  // Link triplets with pairs to form groups of four linked segments
182  vector<int>is_quadrupled(triplets.size());
183  vector<vector<const DFDCSegment *> >quadruplets;
184  for (unsigned int i=0;i<triplets.size();i++){
185  for (unsigned int j=0;j<paired_segments.size();j++){
186  if (is_tripled[j] || is_quadrupled[i]) continue;
187  if (triplets[i][2]==paired_segments[j].first){
188  is_quadrupled[i]=1;
189  is_tripled[j]=1;
190 
191  vector<const DFDCSegment*>quadruplet=triplets[i];
192  quadruplet.push_back(paired_segments[j].second);
193  quadruplets.push_back(quadruplet);
194  }
195  }
196  }
197 
198  // Start gathering groups into a list of linked segments to elevate to track
199  // candidates
200  vector<vector<const DFDCSegment *> >mytracks;
201  for (unsigned int i=0;i<quadruplets.size();i++){
202  mytracks.push_back(quadruplets[i]);
203  }
204  // If we could not link some of the pairs together, create two-segment
205  // "tracks"
206  for (unsigned int i=0;i<is_tripled.size();i++){
207  if (is_tripled[i]==0){
208  vector<const DFDCSegment *>mytrack;
209  mytrack.push_back(paired_segments[i].first);
210  mytrack.push_back(paired_segments[i].second);
211  mytracks.push_back(mytrack);
212  }
213  }
214  // if we could not link some of the triplets to other segments, create
215  // three-segment "tracks"
216  for (unsigned int i=0;i<triplets.size();i++){
217  if (is_quadrupled[i]==0){
218  mytracks.push_back(triplets[i]);
219  }
220  }
221 
222  // For each set of matched segments, redo the helical fit with all the hits
223  // and create a new track candidate
224  for (unsigned int i=0;i<mytracks.size();i++){
225  // Create the fit object and add the hits
226  DHelicalFit fit;
227  // Fake point at origin
228  fit.AddHitXYZ(0.,0.,TARGET_Z,BEAM_VAR,BEAM_VAR,0.);
229  double max_r=0.;
230  rc=0.,xc=0.,yc=0.,tanl=0.; //initialize helix variables
231  q=mytracks[i][0]->q;
232  // create a guess for rc and add hits
233  for (unsigned int m=0;m<mytracks[i].size();m++){
234  rc+=mytracks[i][m]->rc;
235  xc+=mytracks[i][m]->xc;
236  yc+=mytracks[i][m]->yc;
237  tanl+=mytracks[i][m]->tanl;
238  for (unsigned int n=0;n<mytracks[i][m]->hits.size();n++){
239  const DFDCPseudo *hit=mytracks[i][m]->hits[n];
240  fit.AddHit(hit);
241 
242  double r=hit->xy.Mod();
243  if (r>max_r){
244  max_r=r;
245  }
246  }
247  }
248  double mysize=double(mytracks[i].size());
249  rc/=mysize;
250  xc/=mysize;
251  yc/=mysize;
252  tanl/=mysize;
253 
254  // Do the fit
255  if (fit.FitTrackRiemann(rc)==NOERROR){
256  // New track parameters
257  tanl=fit.tanl;
258  xc=fit.x0;
259  yc=fit.y0;
260  rc=fit.r0;
262 
263  // Look for cases where the momentum is unrealistically large...
264  const DFDCPseudo *myhit=mytracks[0][0]->hits[0];
265  double Bz=fabs(bfield->GetBz(myhit->xy.X(),myhit->xy.Y(),myhit->wire->origin.z()));
266  double p=0.003*fit.r0*Bz/cos(atan(fit.tanl));
267 
268  // Prune the fake hit at the origin in case we need to use an alternate
269  // fit
270  fit.PruneHit(0);
271  if (p>10.){//... try alternate circle fit
272  fit.FitCircle();
273  rc=fit.r0;
274  xc=fit.x0;
275  yc=fit.y0;
276  }
277  if (rc<0.5*max_r && max_r<10.0){
278  // ... we can also have issues near the beam line:
279  // Try to fix relatively high momentum tracks in the very forward
280  // direction that look like low momentum tracks due to small pt.
281  // Assume that the particle came from the center of the target.
283  tanl=fit.tanl;
284  rc=fit.r0;
285  xc=fit.x0;
286  yc=fit.y0;
287  fit.FindSenseOfRotation();
289  }
290  }
291 
292  // Create new track, starting with the most upstream segment
294  //circle fit parameters
295  track->rc=rc;
296  track->xc=xc;
297  track->yc=yc;
298 
299  // Get the momentum and position just upstream of first hit
300  DVector3 mom,pos;
301  GetPositionAndMomentum(mytracks[i],pos,mom);
302 
303  track->chisq=fit.chisq;
304  track->Ndof=fit.ndof;
305  track->setPID((q > 0.0) ? PiPlus : PiMinus);
306  track->setPosition(pos);
307  track->setMomentum(mom);
308 
309  for (unsigned int m=0;m<mytracks[i].size();m++){
310  track->AddAssociatedObject(mytracks[i][m]);
311  }
312 
313  _data.push_back(track);
314 
315  }
316 
317 
318  // Now try to attach stray segments to existing tracks
319  for (unsigned int i=0;i<4;i++){
320  for (unsigned int k=0;k<packages[i].size();k++){
321  DFDCSegment *segment=packages[i][k];
322  if (is_paired[i][k]==0 && LinkStraySegment(segment)) is_paired[i][k]=1;
323  }
324  }
325 
326  vector<pair<unsigned int,unsigned int> >unused_segments;
327  for (unsigned int j=0;j<4;j++){
328  for (unsigned int i=0;i<packages[j].size();i++){
329  if (is_paired[j][i]==0){
330  unused_segments.push_back(make_pair(j,i));
331  }
332  }
333  }
334 
335  // Find track candidates using Hough transform
336  if (unused_segments.size()>1){
337  if (LinkSegmentsHough(unused_segments,packages,is_paired)){
338  unused_segments.clear();
339  for (unsigned int j=0;j<4;j++){
340  for (unsigned int i=0;i<packages[j].size();i++){
341  if (is_paired[j][i]==0){
342  unused_segments.push_back(make_pair(j,i));
343  }
344  }
345  }
346  if (unused_segments.size()>1){
347  LinkSegmentsHough(unused_segments,packages,is_paired);
348  }
349  }
350  }
351 
352  // Create track stubs for unused segments
353  for (unsigned int j=0;j<4;j++){
354  for (unsigned int i=0;i<packages[j].size();i++){
355  if (is_paired[j][i]==0){
356  const DFDCSegment* segment=packages[j][i];
357 
358  // Get the momentum and position at a specific z position
359  DVector3 mom, pos;
360  GetPositionAndMomentum(segment,pos,mom);
361 
362  // Create new track, starting with the current segment
364  track->rc=segment->rc;
365  track->xc=segment->xc;
366  track->yc=segment->yc;
367 
368  track->setPosition(pos);
369  track->setMomentum(mom);
370  track->setPID((segment->q > 0.0) ? PiPlus : PiMinus);
371  track->Ndof=segment->Ndof;
372  track->chisq=segment->chisq;
373 
374  track->AddAssociatedObject(segment);
375 
376  _data.push_back(track);
377  }
378  }
379  }
380 
381  return NOERROR;
382 }
383 
384 
385 // Routine to do a crude match between fdc points and a helical approximation to
386 // the trajectory
388  double sperp=(hit->wire->origin.z()-zs)*cotl;
389  double twoks=twokappa*sperp;
390  double sin2ks=sin(twoks);
391  double cos2ks=cos(twoks);
392  double one_minus_cos2ks=1.-cos2ks;
393  double one_over_twokappa=1./twokappa;
394 
395  double x=xs+(cosphi*sin2ks-sinphi*one_minus_cos2ks)*one_over_twokappa;
396  double y=ys+(sinphi*sin2ks+cosphi*one_minus_cos2ks)*one_over_twokappa;
397  double dx=x-hit->xy.X();
398  double dy=y-hit->xy.Y();
399 
400  return (dx*dx+dy*dy);
401 }
402 
403 // Propagate track from one package to the next and look for a match to a
404 // segment in the new package
406  vector<DFDCSegment*>package,
407  unsigned int &match_id){
408  DFDCSegment *match=NULL;
409 
410  // Get the position and momentum at the exit of the package for the
411  // current segment
412  GetPositionAndMomentum(segment);
413 
414  // Match to the next package
415  double doca2_min=1e6,doca2;
416  for (unsigned int j=0;j<package.size();j++){
417  DFDCSegment *segment2=package[j];
418  doca2=DocaSqToHelix(segment2->hits[0]);
419 
420  if (doca2<doca2_min){
421  doca2_min=doca2;
422  if(doca2<Match(p)){
423  match=segment2;
424  match_id=j;
425  }
426  }
427  }
428 
429  if(DEBUG_HISTS){
430  match_dist_fdc->Fill(p,doca2_min);
431  }
432  if (match!=NULL) return match;
433 
434  // If matching in the forward direction did not work, try
435  // matching backwards...
436  doca2_min=1e6;
437  for (unsigned int i=0;i<package.size();i++){
438  DFDCSegment *segment2=package[i];
439  GetPositionAndMomentum(segment2);
440  doca2=DocaSqToHelix(segment->hits[segment->hits.size()-1]);
441  if (doca2<doca2_min){
442  doca2_min=doca2;
443  if (doca2<Match(p)){
444  match=segment2;
445  match_id=i;
446  }
447  }
448  }
449  if (match!=NULL) return match;
450 
451  // Match by centers of circles
452  double circle_center_diff2_min=1e6;
453  for (unsigned int j=0;j<package.size();j++){
454  DFDCSegment *segment2=package[j];
455 
456  double dx=segment->xc-segment2->xc;
457  double dy=segment->yc-segment2->yc;
458  double circle_center_diff2=dx*dx+dy*dy;
459 
460  if (circle_center_diff2<circle_center_diff2_min){
461  circle_center_diff2_min=circle_center_diff2;
462  if (circle_center_diff2_min<9.0){
463  match=segment2;
464  match_id=j;
465  }
466  }
467  }
468  if (DEBUG_HISTS){
469  match_center_dist2->Fill(p,circle_center_diff2_min);
470  }
471  return match;
472 }
473 
474 // Obtain position and momentum at the exit of a given package using the
475 // helical track model.
476 //
478  // Position of track segment at last hit plane of package
479  xs=segment->xc+segment->rc*cos(segment->Phi1);
480  ys=segment->yc+segment->rc*sin(segment->Phi1);
481  zs=segment->hits[0]->wire->origin.z();
482 
483  // Track parameters
484  //double kappa=segment->q/(2.*segment->rc);
485  double my_phi0=segment->phi0;
486  double my_tanl=segment->tanl;
487  double z0=segment->z_vertex;
488  twokappa=FactorForSenseOfRotation*segment->q/segment->rc;
489 
490  cotl=1./my_tanl;
491 
492  // Useful intermediate variables
493  double cosp=cos(my_phi0);
494  double sinp=sin(my_phi0);
495  double twoks=twokappa*(zs-z0)*cotl;
496  double sin2ks=sin(twoks);
497  double cos2ks=cos(twoks);
498 
499  // Get Bfield
500  double Bz=fabs(bfield->GetBz(xs,ys,zs));
501 
502  // Momentum
503  p=0.003*Bz*segment->rc/cos(atan(my_tanl));
504 
505  cosphi=cosp*cos2ks-sinp*sin2ks;
506  sinphi=sinp*cos2ks+cosp*sin2ks;
507 
508  return NOERROR;
509 }
510 
511 // Routine to return momentum and position given the helical parameters and the
512 // z-component of the magnetic field
513 jerror_t
515  vector<const DFDCSegment *>segments,
516  DVector3 &pos,
517  DVector3 &mom){
518  // Hit in the most upstream package
519  const DFDCPseudo *hit=segments[0]->hits[segments[0]->hits.size()-1];
520  double zhit=hit->wire->origin.z();
521  double xhit=hit->xy.X();
522  double yhit=hit->xy.Y();
523 
524  // Position
525  double dz=1.;
526  double zmin=zhit-dz;
527  double phi1=atan2(yhit-yc,xhit-xc);
528  double q_over_rc_tanl=q/(rc*tanl);
529  double dphi_s=dz*q_over_rc_tanl;
530  double dphi1=phi1-dphi_s;// was -
531  double x=xc+rc*cos(dphi1);
532  double y=yc+rc*sin(dphi1);
533  pos.SetXYZ(x,y,zmin);
534 
535  dphi1*=-1.;
536  if (FactorForSenseOfRotation*q<0) dphi1+=M_PI;
537 
538  // Find the average Bz
539  double Bz=0.;
540  double z=zmin;
541  unsigned int num_segments=segments.size();
542  double zmax=segments[num_segments-1]->hits[0]->wire->origin.z();
543  unsigned int num_samples=20*num_segments;
544  double one_over_denom=1./double(num_samples);
545  dz=(zmax-zmin)*one_over_denom;
546  for (unsigned int i=0;i<num_samples;i++){
547  double my_dphi=phi1+(z-zmin)*q_over_rc_tanl;
548  x=xc+rc*cos(my_dphi);
549  y=yc+rc*sin(my_dphi);
550  Bz+=bfield->GetBz(x,y,z);
551 
552  z+=dz;
553  }
554  Bz=fabs(Bz)*one_over_denom;
555 
556 
557  // Momentum
558  double pt=0.003*Bz*rc;
559  double px=pt*sin(dphi1);
560  double py=pt*cos(dphi1);
561  double pz=pt*tanl;
562  mom.SetXYZ(px,py,pz);
563 
564  return NOERROR;
565 }
566 
567 // Routine to return momentum and position given the helical parameters and the
568 // z-component of the magnetic field
569 jerror_t
571  const DFDCSegment *segment,
572  DVector3 &pos,
573  DVector3 &mom){
574  // Hit in the most upstream package
575  const DFDCPseudo *hit=segment->hits[segment->hits.size()-1];
576  double zhit=hit->wire->origin.z();
577  double xhit=hit->xy.X();
578  double yhit=hit->xy.Y();
579 
580  // Position
581  double dz=1.;
582  double zmin=zhit-dz;
583  double phi1=atan2(yhit-segment->yc,xhit-segment->xc);
584  double q_over_rc_tanl=segment->q/(segment->rc*segment->tanl);
585  double dphi_s=dz*q_over_rc_tanl;
586  double dphi1=phi1-dphi_s;// was -
587  double x=segment->xc+segment->rc*cos(dphi1);
588  double y=segment->yc+segment->rc*sin(dphi1);
589  pos.SetXYZ(x,y,zmin);
590 
591  dphi1*=-1.;
592  if (FactorForSenseOfRotation*segment->q<0) dphi1+=M_PI;
593 
594  // Find Bz at x,y,zmin
595  double Bz=bfield->GetBz(x,y,zmin);
596 
597  // Momentum
598  double pt=0.003*Bz*segment->rc;
599  double px=pt*sin(dphi1);
600  double py=pt*cos(dphi1);
601  double pz=pt*segment->tanl;
602  mom.SetXYZ(px,py,pz);
603 
604  return NOERROR;
605 }
606 
607 
608 // Routine to loop over segments in one of the packages, linking them with
609 // segments in the package downstream of this package
611  vector<DFDCSegment *>packages[4], vector<pair<const DFDCSegment*,const DFDCSegment*> >&paired_segments,
612  vector<vector<int> >&is_paired){
613  unsigned int match_id=0;
614  unsigned int pack2=pack1+1;
615 
616  // Loop over the segments in package "pack1"
617  for (unsigned int i=0;i<packages[pack1].size();i++){
618  DFDCSegment *segment=packages[pack1][i];
619  DFDCSegment *match2=NULL;
620 
621  // Try matching to the next package
622  if (packages[pack2].size()>0
623  && (match2=GetTrackMatch(segment,packages[pack2],match_id))!=NULL){
624  if (is_paired[pack2][match_id]) continue;
625 
626  pair<const DFDCSegment*,const DFDCSegment*> mypair;
627  mypair.first=segment;
628  mypair.second=match2;
629  paired_segments.push_back(mypair);
630  is_paired[pack2][match_id]=1;
631  is_paired[pack1][i]=1;
632  }
633 
634  }
635 }
636 
637 // Routine for matching to a segment using the stepper
639  DVector3 &pos,
640  DVector3 &mom,
641  const DFDCSegment *segment){
642  const DVector3 norm(0,0,1.);
643  stepper->SetCharge(q);
644 
645  const DFDCPseudo *hit=segment->hits[0];
646  if (stepper->SwimToPlane(pos,mom,hit->wire->origin,norm,NULL)==false){
647  double dx=hit->xy.X()-pos.x();
648  double dy=hit->xy.Y()-pos.y();
649  double d2=dx*dx+dy*dy;
650  if (d2<Match(mom.Mag())) return true;
651  }
652  return false;
653 }
654 
655 // Routine that tries to link a stray segment with an already existing track
656 // candidate
658  // Loop over existing candidates looking for potential holes
659  for (unsigned int i=0;i<_data.size();i++){
660  bool got_segment_in_package=false;
661 
662  // Get the segments already associated with this track
663  vector<const DFDCSegment*>segments;
664  _data[i]->GetT(segments);
665  // Flag if segment is in a package that has already been used for this
666  // candidate
667  for (unsigned int j=0;j<segments.size();j++){
668  if (segments[j]->package==segment->package){
669  got_segment_in_package=true;
670  break;
671  }
672  }
673  if (got_segment_in_package==false){
674  // Try to link this segment to an existing candidate
675  DVector3 pos=_data[i]->position();
676  DVector3 mom=_data[i]->momentum();
677 
678  // Switch the direction of the momentum if we would need to backtrack to
679  // get to the segment
680  if (segment->hits[0]->wire->origin.z()<pos.z()){
681  mom=-1.0*mom;
682  }
683  // Match by swimming to a plane in the stray segment
684  bool got_match=GetTrackMatch(_data[i]->charge(),pos,mom,segment);
685  // if this does not work, try to match using the centers of the circles
686  if (got_match==false){
687  double dx=segment->xc-_data[i]->xc;
688  double dy=segment->yc-_data[i]->yc;
689  if (dx*dx+dy*dy<9.0) got_match=true;
690  }
691  if (got_match){
692  // Add the segment as an associated object to _data[i]
693  _data[i]->AddAssociatedObject(segment);
694 
695  // Add the new segment and sort by z
696  segments.push_back(segment);
697  stable_sort(segments.begin(),segments.end(),DTrackCandidate_segment_cmp_by_z);
698 
699  // Create fit object and add hits
700  DHelicalFit fit;
701  // Fake point at origin
702  fit.AddHitXYZ(0.,0.,TARGET_Z,BEAM_VAR,BEAM_VAR,0.);
703  double max_r=0.;
704  for (unsigned int m=0;m<segments.size();m++){
705  for (unsigned int k=0;k<segments[m]->hits.size();k++){
706  const DFDCPseudo *hit=segments[m]->hits[k];
707  fit.AddHit(hit);
708 
709  double r=hit->xy.Mod();
710  if (r>max_r){
711  max_r=r;
712  }
713  }
714  }
715 
716  // Redo the helical fit with the additional hits
717  if (fit.FitTrackRiemann(_data[i]->rc)==NOERROR){
718  rc=fit.r0;
719  tanl=fit.tanl;
720  xc=fit.x0;
721  yc=fit.y0;
723 
724  // Look for cases where the momentum is unrealistically large...
725  const DFDCPseudo *myhit=segments[0]->hits[0];
726  double Bz=fabs(bfield->GetBz(myhit->xy.X(),myhit->xy.Y(),myhit->wire->origin.z()));
727  double p=0.003*fit.r0*Bz/cos(atan(fit.tanl));
728 
729  // Prune the fake hit at the origin in case we need to use an
730  // alternate fit
731  fit.PruneHit(0);
732  if (p>10.){//... try alternate circle fit
733  fit.FitCircle();
734  rc=fit.r0;
735  xc=fit.x0;
736  yc=fit.y0;
737  }
738  if (rc<0.5*max_r && max_r<10.0){
739  // ... we can also have issues near the beam line:
740  // Try to fix relatively high momentum tracks in the very forward
741  // direction that look like low momentum tracks due to small pt.
742  // Assume that the particle came from the center of the target.
743  fit.FitTrack_FixedZvertex(TARGET_Z);
744  tanl=fit.tanl;
745  rc=fit.r0;
746  xc=fit.x0;
747  yc=fit.y0;
748  fit.FindSenseOfRotation();
750  }
751 
752  // Get position and momentum just upstream of first hit
753  GetPositionAndMomentum(segments,pos,mom);
754 
755  _data[i]->chisq=fit.chisq;
756  _data[i]->Ndof=fit.ndof;
757  _data[i]->setPID((q > 0.0) ? PiPlus : PiMinus);
758  _data[i]->setPosition(pos);
759  _data[i]->setMomentum(mom);
760  }
761 
762  return true;
763  }
764  }
765  }
766  return false;
767 }
768 
769 // Find circles using Hough transform
770 bool DTrackCandidate_factory_FDCCathodes::LinkSegmentsHough(vector<pair<unsigned int,unsigned int> >&unused_segments,
771  vector<DFDCSegment *>packages[4],
772  vector<vector<int> >&is_paired){
773  DHoughFind hough(-400.0, +400.0, -400.0, +400.0, 100, 100);
774 
775  vector<pair<unsigned int, unsigned int> >associated_segments;
776  for (unsigned int i=0;i<unused_segments.size();i++){
777  unsigned int packNum=unused_segments[i].first;
778  unsigned int segmentNum=unused_segments[i].second;
779  const DFDCSegment* segment=packages[packNum][segmentNum];
780  for (unsigned int m=0;m<segment->hits.size();m++){
781  hough.AddPoint(segment->hits[m]->xy);
782  associated_segments.push_back(unused_segments[i]);
783  }
784  }
785 
786  DVector2 Ro = hough.Find();
788  // Zoom in on resonance a little
789  double width = 60.0;
790  hough.SetLimits(Ro.X()-width, Ro.X()+width, Ro.Y()-width, Ro.Y()+width,
791  100, 100);
792  Ro = hough.Find();
793 
794  // Zoom in on resonance once more
795  width = 8.0;
796  hough.SetLimits(Ro.X()-width, Ro.X()+width, Ro.Y()-width, Ro.Y()+width, 100, 100);
797  Ro = hough.Find();
798 
799  vector<DVector2> points=hough.GetPoints();
800  set<pair<unsigned int, unsigned int> >associated_segments_to_use;
801  unsigned int num_hits_to_use=0;
802  for (unsigned int m=0;m<points.size();m++){
803  // Calculate distance between Hough transformed line (i.e.
804  // the line on which a circle that passes through both the
805  // origin and the point at hit->pos) and the circle center.
806  DVector2 h=0.5*points[m];
807  DVector2 g(h.Y(), -h.X());
808  g /= g.Mod();
809  DVector2 Ro_minus_h=Ro-h;
810  double dist = fabs(g.X()*Ro_minus_h.Y() - g.Y()*Ro_minus_h.X());
811 
812  // If this is not close enough to the found circle's center,
813  // reject it for this track candidate
814  if(dist < 2.0){
815  num_hits_to_use++;
816  associated_segments_to_use.emplace(associated_segments[m]);
817  }
818  }
819  if (num_hits_to_use>5&&associated_segments_to_use.size()>1){
820  bool same_package=false;
821  set<pair<unsigned int,unsigned int> >::iterator it=associated_segments_to_use.begin();
822  for (; it!=associated_segments_to_use.end(); ++it){
823  unsigned int first_packNo=(*it).first;
824  unsigned int first_segmentNo=(*it).second;
825  set<pair<unsigned int,unsigned int> >::iterator it2=associated_segments_to_use.begin();
826  for (; it2!=associated_segments_to_use.end(); ++it2){
827  unsigned int packNo=(*it2).first;
828  unsigned int segmentNo=(*it2).second;
829  if (packNo==first_packNo){
830  if (segmentNo==first_segmentNo) continue;
831 
832  same_package=true;
833  break;
834  }
835  }
836  }
837  if (same_package==false){
838  DHelicalFit fit;
839 
840  set<pair<unsigned int,unsigned int> >::iterator it=associated_segments_to_use.begin();
841  const DFDCSegment *first_segment=NULL;
842  bool got_first_segment=false;
843  for (; it!=associated_segments_to_use.end(); ++it){
844  unsigned int packNo=(*it).first;
845  unsigned int segmentNo=(*it).second;
846  DFDCSegment *segment=packages[packNo][segmentNo];
847  if (got_first_segment==false){
848  first_segment=segment;
849  got_first_segment=true;
850  }
851  for (unsigned int m=0;m<segment->hits.size();m++){
852  fit.AddHit(segment->hits[m]);
853  }
854 
855  }
856  if (fit.FitTrackRiemann(Ro.Mod())==NOERROR){
857  rc=fit.r0;
858  tanl=fit.tanl;
859  xc=fit.x0;
860  yc=fit.y0;
862 
863  // Get the momentum and position at a specific z position
864  DVector3 mom, pos;
865  GetPositionAndMomentum(first_segment,pos,mom);
866 
867  // Create new track
869  track->rc=rc;
870  track->xc=xc;
871  track->yc=yc;
872 
873  track->setPosition(pos);
874  track->setMomentum(mom);
875  track->setPID((q > 0.0) ? PiPlus : PiMinus);
876  track->Ndof=fit.ndof;
877  track->chisq=fit.chisq;
878 
879  for (it=associated_segments_to_use.begin();
880  it!=associated_segments_to_use.end(); ++it){
881  unsigned int packNo=(*it).first;
882  unsigned int segmentNo=(*it).second;
883  DFDCSegment *segment=packages[packNo][segmentNo];
884  track->AddAssociatedObject(segment);
885  is_paired[packNo][segmentNo]=1;
886  }
887 
888  _data.push_back(track);
889 
890  return true;
891  }
892  }
893  }
894  } // got resonance
895 
896  return false;
897 }
Definition: track.h:16
void setMomentum(const DVector3 &aMomentum)
DVector2 xy
rough x,y coordinates in lab coordinate system
Definition: DFDCPseudo.h:100
DApplication * dapp
double chisq
Definition: DFDCSegment.h:55
bool GetFDCZ(vector< double > &z_wires) const
z-locations for each of the FDC wire planes in cm
Definition: DGeometry.cc:1221
double rc
Definition: DFDCSegment.h:59
double z_vertex
Definition: DFDCSegment.h:65
bool SwimToPlane(DVector3 &pos, DVector3 &mom, const DVector3 &origin, const DVector3 &norm, double *pathlen=NULL)
TVector2 DVector2
Definition: DVector2.h:9
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
bool LinkSegmentsHough(vector< pair< unsigned int, unsigned int > > &unused_segements, vector< DFDCSegment * >packages[4], vector< vector< int > > &is_paired)
double phi0
Definition: DFDCSegment.h:65
#define y
DMagneticFieldMap * GetBfield(unsigned int run_number=1)
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
double zmax
DVector2 Find(void)
Definition: DHoughFind.cc:124
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
void AddPoint(const DVector2 &point)
Definition: DHoughFind.cc:321
DMagneticFieldStepper class.
double xc
Definition: DFDCSegment.h:59
bool DTrackCandidate_segment_cmp(const DFDCSegment *a, const DFDCSegment *b)
jerror_t AddHitXYZ(float x, float y, float z)
Definition: DHelicalFit.cc:200
unsigned int package
Definition: DFDCSegment.h:73
jerror_t AddHit(float r, float phi, float z)
Definition: DHelicalFit.cc:190
vector< const DFDCPseudo * > hits
Definition: DFDCSegment.h:76
double Phi1
Definition: DFDCSegment.h:63
void SetLimits(double xmin, double xmax, double ymin, double ymax, unsigned int Nbinsx, unsigned int Nbinsy)
Definition: DHoughFind.cc:44
DGeometry * GetDGeometry(unsigned int run_number)
#define _DBG_
Definition: HDEVIO.h:12
jerror_t FitCircle(void)
Definition: DHelicalFit.cc:385
vector< DVector2 > GetPoints(void)
Definition: DHoughFind.h:49
jerror_t evnt(JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
jerror_t FitTrackRiemann(float rc)
Definition: DHelicalFit.cc:973
TH1D * py[NCHANNELS]
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
&lt;A href=&quot;index.html#legend&quot;&gt; &lt;IMG src=&quot;CORE.png&quot; width=&quot;100&quot;&gt; &lt;/A&gt;
void setPID(Particle_t locPID)
virtual double GetBz(double x, double y, double z) const =0
double tanl
Definition: DFDCSegment.h:67
jerror_t brun(JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
double sin(double)
float chisq
Chi-squared for the track (not chisq/dof!)
void FindSenseOfRotation(void)
double GetMaxBinContent(void)
Definition: DHoughFind.cc:100
jerror_t GetPositionAndMomentum(const DFDCSegment *segment)
jerror_t FitTrack_FixedZvertex(float z_vertex)
Definition: DHelicalFit.cc:997
jerror_t fini(void)
Called after last event of last event source has been processed.
jerror_t PruneHit(int idx)
Definition: DHelicalFit.cc:330
double q
Definition: DFDCSegment.h:69
int Ndof
Number of degrees of freedom in the fit.
void setPosition(const DVector3 &aPosition)
bool DTrackCandidate_segment_cmp_by_z(const DFDCSegment *a, const DFDCSegment *b)
class DFDCSegment: definition for a track segment in the FDC
Definition: DFDCSegment.h:31
double zmin
jerror_t SetStepSize(double step)
TH2F * temp
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
void LinkSegments(unsigned int pack1, vector< DFDCSegment * >packages[4], vector< pair< const DFDCSegment *, const DFDCSegment * > > &paired_segments, vector< vector< int > > &is_paired)
DFDCSegment * GetTrackMatch(DFDCSegment *segment, vector< DFDCSegment * >package, unsigned int &match_id)
double yc
Definition: DFDCSegment.h:59