Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackFinder.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTrackFinder.cc
4 // Created: Fri Aug 15 09:43:08 EDT 2014
5 // Creator: staylor (on Linux ifarm1102 2.6.32-220.7.1.el6.x86_64 x86_64)
6 //
7 
8 #include "DTrackFinder.h"
9 
11  return(a->wire->origin.Y()>b->wire->origin.Y());
12 }
13 
15  return (a->wire->ring<b->wire->ring);
16 }
17 
19  const DTrackFinder::fdc_hit_t &b){
20  return (a.hit->wire->origin.z()>b.hit->wire->origin.z());
21 }
22 
23 
24 //---------------------------------
25 // DTrackFinder (Constructor)
26 //---------------------------------
28 {
29 
30  COSMICS=false;
31  gPARMS->SetDefaultParameter("TRKFIND:COSMICS",COSMICS);
32 
33  DEBUG_HISTS=false;
34  gPARMS->SetDefaultParameter("TRKFIND:DEBUG_HISTS", DEBUG_HISTS);
35 
36  VERBOSE=0;
37  gPARMS->SetDefaultParameter("TRKFIND:VERBOSE", VERBOSE);
38 
39  CDC_MATCH_RADIUS=2.5;
40  gPARMS->SetDefaultParameter("TRKFIND:CDC_MATCH_RADIUS", CDC_MATCH_RADIUS);
41 
42  CDC_MATCH_PHI=0.04;
43  gPARMS->SetDefaultParameter("TRKFIND:CDC_MATCH_PHI", CDC_MATCH_PHI);
44 
46  gPARMS->SetDefaultParameter("TRKFIND:CDC_COSMIC_MATCH_PHI", CDC_COSMIC_MATCH_PHI);
47 
48  if (DEBUG_HISTS){
49  hCDCMatch_PairD = new TH1F("CDC Pair distance", "CDC Pair distance", 100, 0.0, 20.0);
50  hCDCMatch_Axial = new TH1F("CDC Match Axial", "CDC Match Axial", 360, -M_PI_2, M_PI_2);
51 
52  hFDCLayerRaw = new TH1I("FDC Layer Raw", "Layer of FDC hit before track finding", 24, 0.5 , 24.5);
53  hFDCLayer = new TH1I("FDC Layer", "Layer of FDC hit after segment finding", 24, 0.5 , 24.5);
54  hFDCLayerFirst = new TH1I("First FDC Layer", "First Layer of FDC segment finding", 24, 0.5 , 24.5);
55  }
56 }
57 
58 //---------------------------------
59 // ~DTrackFinder (Destructor)
60 //---------------------------------
62 {
63 
64 }
65 
67 
68  axial_hits.clear();
69  stereo_hits.clear();
70 
71  for (unsigned int i=0;i<axial_segments.size();i++){
72  axial_segments[i].hits.clear();
73  }
74  axial_segments.clear();
75 
76  for (unsigned int i=0;i<cdc_tracks.size();i++){
77  cdc_tracks[i].axial_hits.clear();
78  cdc_tracks[i].stereo_hits.clear();
79  }
80  cdc_tracks.clear();
81 
82  fdc_hits.clear();
83  for (unsigned int i=0;i<4;i++){
84  for (unsigned int j=0;j<fdc_segments[i].size();j++){
85  fdc_segments[i][j].hits.clear();
86  }
87  fdc_segments[i].clear();
88  }
89  fdc_tracks.clear();
90 
91 }
92 
94  fdc_hits.push_back(fdc_hit_t(hit));
95 }
96 
97 
99  int ring=hit->wire->ring;
100  if (ring<=4) axial_hits.push_back(cdc_hit_t(hit));
101  else if (ring<=12) stereo_hits.push_back(cdc_hit_t(hit));
102  else if (ring<=16) axial_hits.push_back(cdc_hit_t(hit));
103  else if (ring<=24) stereo_hits.push_back(cdc_hit_t(hit));
104  else axial_hits.push_back(cdc_hit_t(hit));
105 }
106 
107 // Find segments in cdc axial layers
109  if (axial_hits.size()==0) return false;
110  //jout << " Entering track finding with " << axial_hits.size() << " axial CDC hits" << endl;
111 
112  // Group adjacent axial_hits into pairs
113  vector<pair<unsigned int,unsigned int> > pairs;
114  for (unsigned int i=0;i<axial_hits.size()-1;i++){
115  for (unsigned int j=i+1;j<axial_hits.size();j++){
116  const DCDCWire *first_wire=axial_hits[i].hit->wire;
117  const DCDCWire *second_wire=axial_hits[j].hit->wire;
118  int r1=first_wire->ring;
119  int r2=second_wire->ring;
120  int s1=first_wire->straw;
121  int s2=second_wire->straw;
122  double d=(first_wire->origin-second_wire->origin).Perp();
123  if (DEBUG_HISTS) hCDCMatch_PairD->Fill(d);
124  if ((abs(r1-r2)<=2 && abs(r1-r2)>0 && d<CDC_MATCH_RADIUS)
125  || (r1 == r2 && abs(s1-s2)==1)){
126  pair <unsigned int,unsigned int> mypair(i,j);
127  if(VERBOSE) jout<< " Pair formed R" << r1 << " S" << s1 << " ,R" << r2 << " S" << s2 << endl;
128  pairs.push_back(mypair);
129  }
130  }
131  }
132  //jout << " Made " << pairs.size() << " pairs" << endl;
133  // Link pairs of axial_hits together into segments
134  for (unsigned int i=0;i<pairs.size();i++){
135  if (axial_hits[pairs[i].first].used==false
136  && axial_hits[pairs[i].second].used==false){
137  vector<const DCDCTrackHit *>neighbors;
138  set<unsigned int> used;
139  axial_hits[pairs[i].first].used=true;
140  axial_hits[pairs[i].second].used=true;
141  neighbors.push_back(axial_hits[pairs[i].first].hit);
142  neighbors.push_back(axial_hits[pairs[i].second].hit);
143  used.insert(pairs[i].first);
144  used.insert(pairs[i].second);
145  for (unsigned int j=i+1;j<pairs.size();j++){
146  // If any of the hits match in the pairs, add them together
147  unsigned int first=pairs[j].first;
148  unsigned int second=pairs[j].second;
149  set<unsigned int>::iterator it1, it2;
150  it1 = used.find(first);
151  it2 = used.find(second);
152 
153  if (it1 != used.end() && it2 == used.end()){
154  axial_hits[second].used=true;
155  neighbors.push_back(axial_hits[second].hit);
156  used.insert(second);
157  }
158  else if (it2 != used.end() && it1 == used.end()){
159  axial_hits[first].used=true;
160  neighbors.push_back(axial_hits[first].hit);
161  used.insert(first);
162  }
163 
164  }
165  if (COSMICS){
166  sort(neighbors.begin(),neighbors.end(),DTrackFinder_cdc_hit_cosmics_cmp);
167  } else{
168  sort(neighbors.begin(),neighbors.end(),DTrackFinder_cdc_hit_cmp);
169  }
170 
171  // Take Average direction from hits
172  DVector3 dir(0.,0.,0.);
173  DVector3 origin;
174  if(COSMICS){
175  unsigned int iHit = 1;
176  origin=neighbors[0]->wire->origin;
177  for (iHit = 1; iHit < neighbors.size(); iHit++){
178  dir+=neighbors[iHit]->wire->origin-origin;
179  }
180  if(dir.Mag() != 0.) dir.SetMag(1.);
181  }
182  else{
183  for (unsigned int iHit = 0; iHit < neighbors.size(); iHit++) dir += neighbors[iHit]->wire->origin;
184  if(dir.Mag() != 0.) dir.SetMag(1.);
185  }
186 
187  if (VERBOSE){
188  jout << " Axial Segment Formed: " << endl;
189  for(unsigned int jj = 0; jj<neighbors.size(); jj++){
190  jout << " R" << neighbors[jj]->wire->ring << " S" << neighbors[jj]->wire->straw << endl;
191  }
192  jout << "Dir" << endl;
193  dir.Print();
194  }
195  axial_segments.push_back(cdc_segment_t(neighbors,dir));
196  }
197  }
198 
199  //jout << " into " << axial_segments.size() << " axial segments" << endl;
200  return true;
201 }
202 
203 
204 
205 // Link axial segments together to form track candidates and match to stereo
206 // hits
208  unsigned int num_axial=axial_segments.size();
209  if (num_axial<1) return false;
210  for (unsigned int i=0;i<num_axial;i++){
211  if (axial_segments[i].matched==false){
212  DTrackFinder::cdc_track_t mytrack(axial_segments[i].hits);
213 
214  DVector3 pos0=axial_segments[i].hits[0]->wire->origin;
215  DVector3 vhat=axial_segments[i].dir;
216 
217  for (unsigned int j=i+1;j<num_axial;j++){
218  if (axial_segments[j].matched==false){
219  double dphi = axial_segments[j].dir.Phi() - axial_segments[i].dir.Phi();
220  while (dphi>M_PI) dphi-=2*M_PI;
221  while (dphi<-M_PI) dphi+=2*M_PI;
222  double matchphi = CDC_MATCH_PHI;
223  if (DEBUG_HISTS){
224  hCDCMatch_Axial->Fill(dphi);
225  }
226  if (COSMICS) matchphi = CDC_COSMIC_MATCH_PHI;
227  if ( fabs(dphi) < matchphi){
228  axial_segments[j].matched=true;
229  mytrack.axial_hits.insert(mytrack.axial_hits.end(),
230  axial_segments[j].hits.begin(),
231  axial_segments[j].hits.end());
232  if (COSMICS) sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),DTrackFinder_cdc_hit_cosmics_cmp);
233  else sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),DTrackFinder_cdc_hit_cmp);
234  }
235  }
236  }
237  // Position of the first axial wire in the track
238  pos0=mytrack.axial_hits[0]->wire->origin;
239  vhat.SetMag(1.);
240  if (VERBOSE){
241  jout << " Axial track Formed: pos vhat" << endl;
242  pos0.Print(); vhat.Print();
243  for(unsigned int jj = 0; jj<mytrack.axial_hits.size(); jj++){
244  jout << " R" << mytrack.axial_hits[jj]->wire->ring << " S" << mytrack.axial_hits[jj]->wire->straw << endl;
245  }
246  }
247 
248  // Grab axial hits not associated with segments
249  bool got_match=false;
250  for (unsigned int j=0;j<axial_hits.size();j++){
251  if (axial_hits[j].used==false){
252  if (MatchCDCHit(vhat,pos0,axial_hits[j].hit,CDC_MATCH_RADIUS)){
253  axial_hits[j].used=true;
254  mytrack.axial_hits.push_back(axial_hits[j].hit);
255  if (VERBOSE) jout << "Added to axial track R" << axial_hits[j].hit->wire->ring << " S" << axial_hits[j].hit->wire->straw << endl;
256  got_match=true;
257  }
258  }
259  }
260  // Resort if we added axial hits and recompute direction vector
261  if (got_match){
262  if (COSMICS){
263  sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),
265  }
266  else{
267  sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),
269  }
270 
271  vhat.SetXYZ(0., 0., 0.);
272  for (unsigned int iHit = 1; iHit < mytrack.axial_hits.size(); iHit++){
273  DVector3 temp =mytrack.axial_hits[iHit]->wire->origin
274  -mytrack.axial_hits[0]->wire->origin;
275  if(mytrack.axial_hits[iHit]->wire->ring != mytrack.axial_hits[0]->wire->ring) vhat += temp;
276  }
277  vhat.SetMag(1.);
278  pos0=mytrack.axial_hits[0]->wire->origin;
279  }
280 
281 
282  // Now try to associate stereo hits with this track
283  for (unsigned int j=0;j<stereo_hits.size();j++){
284  if (stereo_hits[j].used==false){
285  if (MatchCDCStereoHit(vhat,pos0,stereo_hits[j].hit)){
286  //stereo_hits[j].used=true;
287  mytrack.stereo_hits.push_back(stereo_hits[j].hit);
288  if (VERBOSE) jout << "Added stereo hit R" << stereo_hits[j].hit->wire->ring << " S" << stereo_hits[j].hit->wire->straw << endl;
289  }
290  }
291  }
292  size_t num_stereo=mytrack.stereo_hits.size();
293  size_t num_axial=mytrack.axial_hits.size();
294  if (VERBOSE) jout << " num_axial num_stereo " << num_axial << " " << num_stereo << endl;
295  if (num_stereo>0 && num_stereo+num_axial>4){
296  mytrack.dir=vhat;
297  if (mytrack.FindStateVector(COSMICS)==NOERROR){
298  cdc_tracks.push_back(mytrack);
299  }
300  }
301  }
302  }
303  return true;
304 }
305 
306 
307 // Match a CDC hit with a line starting at pos0 going in the vhat direction
308 bool DTrackFinder::MatchCDCHit(const DVector3 &vhat,const DVector3 &pos0,
309  const DCDCTrackHit *hit, double cut){
310  DVector3 pos1=hit->wire->origin;
311  DVector3 uhat=hit->wire->udir;
312  DVector3 diff=pos1-pos0;
313  double vhat_dot_uhat=vhat.Dot(uhat);
314  double scale=1./(1.-vhat_dot_uhat*vhat_dot_uhat);
315  double s=scale*(vhat_dot_uhat*diff.Dot(vhat)-diff.Dot(uhat));
316  double t=scale*(diff.Dot(vhat)-vhat_dot_uhat*diff.Dot(uhat));
317  if (t<0) return false;
318  double d=(diff+s*uhat-t*vhat).Mag();
319 
320  if (d<cut) return true;
321 
322  return false;
323 }
324 
325 // Match a CDC hit with a line starting at pos0 going in the vhat direction
327  const DCDCTrackHit *hit){
328  DVector3 w0=hit->wire->origin;
329  DVector3 wdir=hit->wire->udir;
330  DVector3 diff = t0-w0;
331  double diffCrosstdir=diff.X()*tdir.Y()-diff.Y()*tdir.X();
332  double diffCrosswdir=diff.X()*wdir.Y()-diff.Y()*wdir.X();
333  double wdirCrosstdir=wdir.X()*tdir.Y()-wdir.Y()*tdir.X();
334  double w=diffCrosstdir/wdirCrosstdir;
335  double t=diffCrosswdir/wdirCrosstdir;
336  if(t<0.) return false;
337  if(fabs(w)<hit->wire->L/2.) return true;
338 
339  return false;
340 }
341 
342 // Compute initial guess for state vector (x,y,tx,ty) for a track in the CDC
343 // by fitting a line to the intersections between the line in the xy plane and
344 // the stereo wires.
346  // Parameters for line in x-y plane
347  double vx=this->dir.x();
348  double vy=this->dir.y();
349  DVector3 pos0=this->axial_hits[0]->wire->origin;
350  double xa=pos0.x();
351  double ya=pos0.y();
352 
353  double sumv=0,sumx=0,sumy=0,sumz=0,sumxx=0,sumyy=0,sumxz=0,sumyz=0;
354  for (unsigned int i=0;i<this->stereo_hits.size();i++){
355  // Intersection of line in xy-plane with this stereo straw
356  DVector3 origin_s=this->stereo_hits[i]->wire->origin;
357  DVector3 dir_s=this->stereo_hits[i]->wire->udir;
358  double ux_s=dir_s.x();
359  double uy_s=dir_s.y();
360  double dx=xa-origin_s.x();
361  double dy=ya-origin_s.y();
362  double s=(dx*vy-dy*vx)/(ux_s*vy-uy_s*vx);
363  DVector3 pos1=origin_s+s*dir_s;
364  double x=pos1.x(),y=pos1.y(),z=pos1.z();
365 
366  if (z>17.0 && z<167.0)
367  { // Check for CDC dimensions
368  sumv+=1.;
369  sumx+=x;
370  sumxx+=x*x;
371  sumy+=y;
372  sumyy+=y*y;
373  sumz+=z;
374  sumxz+=x*z;
375  sumyz+=y*z;
376  }
377  }
378  /*
379  if (IsCosmics==false){ // Encourage track to come from target region
380  sumz+=TARGET_Z;
381  sumv+=1.;
382  }
383  */
384  const double EPS=1e-4;
385  double xdenom=sumv*sumxz-sumx*sumz;
386  if (fabs(xdenom)<EPS) return VALUE_OUT_OF_RANGE;
387 
388  double ydenom=sumv*sumyz-sumy*sumz;
389  if (fabs(ydenom)<EPS) return VALUE_OUT_OF_RANGE;
390 
391  double xtemp=sumv*sumxx-sumx*sumx;
392  double xslope=xtemp/xdenom;
393  double ytemp=sumv*sumyy-sumy*sumy;
394  double yslope=ytemp/ydenom;
395 
396  // double z0x=(sumxx*sumz-sumx*sumxz)/xtemp;
397  double z0y=(sumyy*sumz-sumy*sumyz)/ytemp;
398 
399  // Increment just beyond point largest in y
400  double delta_z=(yslope>0)?0.5:-0.5;
401 
402  //Starting z position
403  this->z=z0y+ya/yslope+delta_z;
404 
405  this->S(state_x)=xa+xslope*delta_z;
406  this->S(state_y)=ya+yslope*delta_z;
407  this->S(state_tx)=xslope;
408  this->S(state_ty)=yslope;
409 
410  return NOERROR;
411 
412 }
413 
414 // Given two straight tracks, find the doca between them
415 double DTrackFinder::FindDoca(const DVector3 &pos1,const DVector3 &mom1,
416  const DVector3 &pos2,const DVector3 &mom2,
417  DVector3 *poca) const{
418  DVector3 diff=pos1-pos2;
419  DVector3 uhat=mom1;
420  uhat.SetMag(1.);
421  DVector3 vhat=mom2;
422  vhat.SetMag(1.);
423 
424  double vhat_dot_diff=diff.Dot(vhat);
425  double uhat_dot_diff=diff.Dot(uhat);
426  double uhat_dot_vhat=uhat.Dot(vhat);
427  double D=1.-uhat_dot_vhat*uhat_dot_vhat;
428  double N=uhat_dot_vhat*vhat_dot_diff-uhat_dot_diff;
429  double N1=vhat_dot_diff-uhat_dot_vhat*uhat_dot_diff;
430  double scale=1./D;
431  double s=scale*N;
432  double t=scale*N1;
433 
434  if (poca!=NULL) *poca=pos1+s*uhat;
435 
436  diff+=s*uhat-t*vhat;
437  return diff.Mag();
438 }
439 
440 
441 // Given state vector S, find doca to wire given by origin and wdir
442 double DTrackFinder::FindDoca(double z,const DMatrix4x1 &S,const DVector3 &wdir,
443  const DVector3 &origin,DVector3 *poca) const{
444  DVector3 pos(S(state_x),S(state_y),z);
445  DVector3 diff=pos-origin;
446 
447  DVector3 uhat(S(state_tx),S(state_ty),1.);
448  uhat.SetMag(1.);
449  DVector3 vhat=wdir;
450  vhat.SetMag(1.);
451 
452  double vhat_dot_diff=diff.Dot(vhat);
453  double uhat_dot_diff=diff.Dot(uhat);
454  double uhat_dot_vhat=uhat.Dot(vhat);
455  double D=1.-uhat_dot_vhat*uhat_dot_vhat;
456  double N=uhat_dot_vhat*vhat_dot_diff-uhat_dot_diff;
457  double N1=vhat_dot_diff-uhat_dot_vhat*uhat_dot_diff;
458  double scale=1./D;
459  double s=scale*N;
460  double t=scale*N1;
461 
462  if (poca!=NULL) *poca=pos+s*uhat;
463 
464  diff+=s*uhat-t*vhat;
465  return diff.Mag();
466 }
467 
468 
469 // Find segments by associating adjacent hits within a package together.
471  if (fdc_hits.size()==0) return false;
472  unsigned int num_hits=fdc_hits.size();
473  const double MATCH_RADIUS=2.0;
474  const double ADJACENT_MATCH_RADIUS=1.0;
475 
476  // Order points by z
477  sort(fdc_hits.begin(),fdc_hits.end(),DTrackFinder_fdc_hit_cmp);
478 
479  // Put indices for the first point in each plane before the most downstream
480  // plane in the vector x_list.
481  int old_layer=fdc_hits[0].hit->wire->layer;
482  vector<unsigned int>x_list;
483  x_list.push_back(0);
484  for (unsigned int i=0;i<num_hits;i++){
485  if(DEBUG_HISTS){
486  hFDCLayerRaw->Fill(fdc_hits[i].hit->wire->layer);
487  }
488  if (fdc_hits[i].hit->wire->layer!=old_layer){
489  x_list.push_back(i);
490  }
491  old_layer=fdc_hits[i].hit->wire->layer;
492  }
493  x_list.push_back(num_hits);
494 
495  unsigned int start=0;
496  // loop over the start indices, starting with the first plane
497  while (start<x_list.size()-1){
498  // Now loop over the list of track segment start fdc_hits
499  for (unsigned int i=x_list[start];i<x_list[start+1];i++){
500  if (fdc_hits[i].used==false){
501  fdc_hits[i].used=true;
502  if(DEBUG_HISTS){
503  hFDCLayerFirst->Fill(fdc_hits[i].hit->wire->layer);
504  }
505 
506  // Point in the current plane in the package
507  DVector2 XY=fdc_hits[i].hit->xy;
508  double z=fdc_hits[i].hit->wire->origin.z();
509 
510  // Create list of nearest neighbors
511  vector<const DFDCPseudo*>neighbors;
512  neighbors.push_back(fdc_hits[i].hit);
513  unsigned int match=0;
514  double delta,delta_min=1000.;
515  for (unsigned int k=0;k<x_list.size()-1;k++){
516  delta_min=1000.;
517  match=0;
518  bool hasMatch=false;
519  for (unsigned int m=x_list[k];m<x_list[k+1];m++){
520  if(fdc_hits[m].used==false){
521  delta=(XY-fdc_hits[m].hit->xy).Mod();
522  double delta_z=fabs(z-fdc_hits[m].hit->wire->origin.z());
523  if (delta<delta_min){
524  delta_min=delta;
525  if (delta<MATCH_RADIUS && delta_z<11.0) {
526  match=m;
527  hasMatch = true;
528  }
529  }
530  }
531  }
532  if (hasMatch){
533  XY=fdc_hits[match].hit->xy;
534  fdc_hits[match].used=true;
535  neighbors.push_back(fdc_hits[match].hit);
536  }
537  }
538  unsigned int num_neighbors=neighbors.size();
539 
540  // Look for hits adjacent to the ones we have in our segment candidate
541  for (unsigned int k=0;k<num_hits;k++){
542  if (fdc_hits[k].used==false){
543  for (unsigned int j=0;j<num_neighbors;j++){
544  delta=(fdc_hits[k].hit->xy-neighbors[j]->xy).Mod();
545 
546  if (delta<ADJACENT_MATCH_RADIUS &&
547  abs(neighbors[j]->wire->wire-fdc_hits[k].hit->wire->wire)<=1
548  && neighbors[j]->wire->origin.z()==fdc_hits[k].hit->wire->origin.z()){
549  fdc_hits[k].used=true;
550  neighbors.push_back(fdc_hits[k].hit);
551  }
552  }
553  }
554  } // loop looking for hits adjacent to hits on segment
555 
556  if (neighbors.size()>3){
557  unsigned int packNum=(neighbors[0]->wire->layer-1)/6;
558  if (DEBUG_HISTS){
559  for (size_t iN = 0; iN < neighbors.size(); iN++){
560  hFDCLayer->Fill(neighbors[iN]->wire->layer);
561  }
562  }
563  fdc_segments[packNum].push_back(fdc_segment_t(neighbors));
564  }
565  }
566  }// loop over start points within a plane
567 
568  // Look for a new plane to start looking for a segment
569  while (start<x_list.size()-1){
570  if (fdc_hits[x_list[start]].used==false) break;
571  start++;
572  }
573 
574  }
575 
576  return true;
577 }
578 
579 // Link segments from package to package by doing straight-line projections
581  // Cuts for matching
582  const double MATCH_RADIUS=2.0;
583  const double LINK_MATCH_RADIUS=7.0;
584 
585  // Vector to store hits for the linked segments
586  vector<const DFDCPseudo *>myhits;
587 
588  // loop over packages
589  for (unsigned int i=0;i<4;i++){
590  for (unsigned int j=0;j<fdc_segments[i].size();j++){
591  if (fdc_segments[i][j].matched==false){
592  unsigned i_plus_1=i+1;
593  if (i_plus_1<4){
594  double tx=fdc_segments[i][j].S(state_tx);
595  double ty=fdc_segments[i][j].S(state_ty);
596  double x0=fdc_segments[i][j].S(state_x);
597  double y0=fdc_segments[i][j].S(state_y);
598 
599  for (unsigned int k=0;k<fdc_segments[i_plus_1].size();k++){
600  if (fdc_segments[i_plus_1][k].matched==false){
601  double z=fdc_segments[i_plus_1][k].hits[0]->wire->origin.z();
602  DVector2 proj(x0+tx*z,y0+ty*z);
603 
604  if ((proj-fdc_segments[i_plus_1][k].hits[0]->xy).Mod()<LINK_MATCH_RADIUS){
605  fdc_segments[i_plus_1][k].matched=true;
606  myhits.insert(myhits.end(),fdc_segments[i_plus_1][k].hits.begin(),
607  fdc_segments[i_plus_1][k].hits.end());
608 
609  unsigned int i_plus_2=i_plus_1+1;
610  if (i_plus_2<4){
611  tx=fdc_segments[i_plus_1][k].S(state_tx);
612  ty=fdc_segments[i_plus_1][k].S(state_ty);
613  x0=fdc_segments[i_plus_1][k].S(state_x);
614  y0=fdc_segments[i_plus_1][k].S(state_y);
615 
616  for (unsigned int m=0;m<fdc_segments[i_plus_2].size();m++){
617  if (fdc_segments[i_plus_2][m].matched==false){
618  z=fdc_segments[i_plus_2][m].hits[0]->wire->origin.z();
619  proj.Set(x0+tx*z,y0+ty*z);
620 
621  if ((proj-fdc_segments[i_plus_2][m].hits[0]->xy).Mod()<LINK_MATCH_RADIUS){
622  fdc_segments[i_plus_2][m].matched=true;
623  myhits.insert(myhits.end(),fdc_segments[i_plus_2][m].hits.begin(),
624  fdc_segments[i_plus_2][m].hits.end());
625 
626  unsigned int i_plus_3=i_plus_2+1;
627  if (i_plus_3<4){
628  tx=fdc_segments[i_plus_2][m].S(state_tx);
629  ty=fdc_segments[i_plus_2][m].S(state_ty);
630  x0=fdc_segments[i_plus_2][m].S(state_x);
631  y0=fdc_segments[i_plus_2][m].S(state_y);
632 
633  for (unsigned int n=0;n<fdc_segments[i_plus_3].size();n++){
634  if (fdc_segments[i_plus_3][n].matched==false){
635  z=fdc_segments[i_plus_3][n].hits[0]->wire->origin.z();
636  proj.Set(x0+tx*z,y0+ty*z);
637 
638  if ((proj-fdc_segments[i_plus_3][n].hits[0]->xy).Mod()<LINK_MATCH_RADIUS){
639  fdc_segments[i_plus_3][n].matched=true;
640  myhits.insert(myhits.end(),fdc_segments[i_plus_3][n].hits.begin(),
641  fdc_segments[i_plus_3][n].hits.end());
642 
643  break;
644  } // matched a segment
645  }
646  } // loop over last set of segments
647  } // if we have another package to loop over
648  break;
649  } // matched a segment
650  }
651  } // loop over second-to-last set of segments
652  }
653  break;
654  } // matched a segment
655  }
656  } // loop over third-to-last set of segments
657  }
658  if (myhits.size()>0){
659  myhits.insert(myhits.begin(),fdc_segments[i][j].hits.begin(),fdc_segments[i][j].hits.end());
660  fdc_tracks.push_back(fdc_segment_t(myhits));
661  }
662  myhits.clear();
663  } // check if we have already used this segment
664  } // loop over first set of segments
665  } // loop over packages
666 
667  // Try to link tracks together
668  if (fdc_tracks.size()>1){
669  for (unsigned int i=0;i<fdc_tracks.size()-1;i++){
670  DMatrix4x1 S=fdc_tracks[i].S;
671  size_t last_index_1=fdc_tracks[i].hits.size()-1;
672  int first_pack_1=(fdc_tracks[i].hits[0]->wire->layer-1)/6;
673  int last_pack_1=(fdc_tracks[i].hits[last_index_1]->wire->layer-1)/6;
674  for (unsigned int j=i+1;j<fdc_tracks.size();j++){
675  size_t last_index_2=fdc_tracks[j].hits.size()-1;
676  int first_pack_2=(fdc_tracks[j].hits[0]->wire->layer-1)/6;
677  int last_pack_2=(fdc_tracks[j].hits[last_index_2]->wire->layer-1)/6;
678 
679  if (last_pack_1<first_pack_2 || first_pack_1 > last_pack_2){
680  double z=fdc_tracks[j].hits[0]->wire->origin.z();
681  DVector2 proj(S(state_x)+z*S(state_tx),S(state_y)+z*S(state_ty));
682  double diff=(fdc_tracks[j].hits[0]->xy-proj).Mod();
683 
684  if (diff<MATCH_RADIUS){
685  // Combine the hits from the two tracks and recompute the state
686  // vector S
687  if (last_pack_1<first_pack_2){
688  fdc_tracks[i].hits.insert(fdc_tracks[i].hits.end(),
689  fdc_tracks[j].hits.begin(),
690  fdc_tracks[j].hits.end());
691  }
692  else{
693  fdc_tracks[i].hits.insert(fdc_tracks[i].hits.begin(),
694  fdc_tracks[j].hits.begin(),
695  fdc_tracks[j].hits.end());
696  }
697  fdc_tracks[i].FindStateVector();
698 
699  // Drop the second track from the list
700  fdc_tracks.erase(fdc_tracks.begin()+j);
701  break;
702  }
703  }
704  }
705  } // loop over tracks
706  } // check if we have more than one track
707 
708  // Try to attach unmatched segments to tracks
709  for (unsigned int i=0;i<fdc_tracks.size();i++){
710  DMatrix4x1 S=fdc_tracks[i].S;
711  size_t last_index_1=fdc_tracks[i].hits.size()-1;
712  int first_pack_1=(fdc_tracks[i].hits[0]->wire->layer-1)/6;
713  int last_pack_1=(fdc_tracks[i].hits[last_index_1]->wire->layer-1)/6;
714  for (unsigned int j=0;j<4;j++){
715  for (unsigned int k=0;k<fdc_segments[j].size();k++){
716  if (fdc_segments[j][k].matched==false){
717  int pack_2=(fdc_segments[j][k].hits[0]->wire->layer-1)/6;
718  if (pack_2<first_pack_1 || pack_2>last_pack_1){
719  double z=fdc_segments[j][k].hits[0]->wire->origin.z();
720  DVector2 proj(S(state_x)+z*S(state_tx),S(state_y)+z*S(state_ty));
721  double diff=(fdc_segments[j][k].hits[0]->xy-proj).Mod();
722 
723  if (diff<MATCH_RADIUS){
724  fdc_segments[j][k].matched=true;
725 
726  // Add hits and recompute S
727  if (pack_2<first_pack_1){
728  fdc_tracks[i].hits.insert(fdc_tracks[i].hits.begin(),
729  fdc_segments[j][k].hits.begin(),
730  fdc_segments[j][k].hits.end());
731  }
732  else {
733  fdc_tracks[i].hits.insert(fdc_tracks[i].hits.end(),
734  fdc_segments[j][k].hits.begin(),
735  fdc_segments[j][k].hits.end());
736 
737  }
738  fdc_tracks[i].FindStateVector();
739  }
740  }
741  } // check if already matched to other segments
742  } // loop over segments in package
743  } // loop over packages
744  } //loop over existing tracks
745 
746 
747  return true;
748 }
749 
750 
751 
752 // Use linear regression on the hits to obtain a first guess for the state
753 // vector. Method taken from Numerical Recipes in C.
754 DMatrix4x1
756  double S1=0.;
757  double S1z=0.;
758  double S1y=0.;
759  double S1zz=0.;
760  double S1zy=0.;
761  double S2=0.;
762  double S2z=0.;
763  double S2x=0.;
764  double S2zz=0.;
765  double S2zx=0.;
766 
767  double sig2v=0.25; // rough guess;
768 
769  for (unsigned int i=0;i<hits.size();i++){
770  double cosa=hits[i]->wire->udir.y();
771  double sina=hits[i]->wire->udir.x();
772  double x=hits[i]->xy.X();
773  double y=hits[i]->xy.Y();
774  double z=hits[i]->wire->origin.z();
775  double sig2x=cosa*cosa/12+sina*sina*sig2v;
776  double sig2y=sina*sina/12+cosa*cosa*sig2v;
777  double one_over_var1=1/sig2y;
778  double one_over_var2=1/sig2x;
779 
780  S1+=one_over_var1;
781  S1z+=z*one_over_var1;
782  S1y+=y*one_over_var1;
783  S1zz+=z*z*one_over_var1;
784  S1zy+=z*y*one_over_var1;
785 
786  S2+=one_over_var2;
787  S2z+=z*one_over_var2;
788  S2x+=x*one_over_var2;
789  S2zz+=z*z*one_over_var2;
790  S2zx+=z*x*one_over_var2;
791  }
792  double D1=S1*S1zz-S1z*S1z;
793  double y_intercept=(S1zz*S1y-S1z*S1zy)/D1;
794  double y_slope=(S1*S1zy-S1z*S1y)/D1;
795  double D2=S2*S2zz-S2z*S2z;
796  double x_intercept=(S2zz*S2x-S2z*S2zx)/D2;
797  double x_slope=(S2*S2zx-S2z*S2x)/D2;
798 
799  return DMatrix4x1(x_intercept,y_intercept,x_slope,y_slope);
800 }
801 
802 // Find intersection between a straight line and a plane
804  const DVector3 &norm,
805  const DVector3 &pos,
806  const DVector3 &dir,
807  DVector3 &outpos) const{
808  DVector3 mydir(dir);
809  mydir.SetMag(1.);
810  double dot=mydir.Dot(norm);
811  if (fabs(dot)<1e-16) return false; // parallel lines
812  double s=(origin-pos).Dot(norm)/dot;
813  outpos=pos+s*mydir;
814 
815  return true;
816 }
817 
818 
819 // Find the intersections between a straight line and a cylinder of radius R
821  const DVector3 &dir,
822  const DVector3 &pos,
823  DVector3 &out1,
824  DVector3 &out2) const{
825  double denom=dir.Mag();
826  double ux=dir.x()/denom;
827  double uy=dir.y()/denom;
828  double uz=dir.z()/denom;
829  double ux2=ux*ux;
830  double uy2=uy*uy;
831  double ux2_plus_uy2=ux2+uy2;
832  double x0=pos.x();
833  double y0=pos.y();
834  double z0=pos.z();
835  double A=ux2_plus_uy2*R*R-uy2*x0*x0-ux2*y0*y0+2.*ux*uy*x0*y0;
836  if (A<0) return false;
837 
838  double t0=-(x0*ux+y0*uy)/ux2_plus_uy2;
839  double dt=sqrt(A)/ux2_plus_uy2;
840  double tplus=t0+dt;
841  out1.SetXYZ(x0+ux*tplus,y0+uy*tplus,z0+uz*tplus);
842  double tminus=t0-dt;
843  out2.SetXYZ(x0+ux*tminus,y0+uy*tminus,z0+uz*tminus);
844 
845  return true;
846 }
847 
TH1F * hCDCMatch_Axial
Definition: DTrackFinder.h:141
virtual ~DTrackFinder()
Definition: DTrackFinder.cc:61
#define ADJACENT_MATCH_RADIUS
void AddHit(const DCDCTrackHit *hit)
Definition: DTrackFinder.cc:98
bool FindIntersectionWithPlane(const DVector3 &origin, const DVector3 &norm, const DVector3 &pos, const DVector3 &dir, DVector3 &outpos) const
TH1I * hFDCLayerRaw
Definition: DTrackFinder.h:142
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
TVector2 DVector2
Definition: DVector2.h:9
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define EPS
#define y
vector< cdc_track_t > cdc_tracks
Definition: DTrackFinder.h:146
bool FindFDCSegments(void)
vector< const DCDCTrackHit * > axial_hits
Definition: DTrackFinder.h:102
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
bool MatchCDCStereoHit(const DVector3 &tdir, const DVector3 &t0, const DCDCTrackHit *hit)
const DFDCPseudo * hit
Definition: DTrackFinder.h:40
vector< cdc_hit_t > axial_hits
Definition: DTrackFinder.h:143
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
bool DTrackFinder_fdc_hit_cmp(const DTrackFinder::fdc_hit_t &a, const DTrackFinder::fdc_hit_t &b)
Definition: DTrackFinder.cc:18
vector< cdc_hit_t > stereo_hits
Definition: DTrackFinder.h:144
bool LinkFDCSegments(void)
TH1I * hFDCLayer
Definition: DTrackFinder.h:142
TEllipse * e
TLatex tx
int straw
Definition: DCDCWire.h:81
TH1F * hCDCMatch_PairD
Definition: DTrackFinder.h:141
#define MATCH_RADIUS
vector< fdc_segment_t > fdc_tracks
Definition: DTrackFinder.h:150
vector< fdc_segment_t > fdc_segments[4]
Definition: DTrackFinder.h:149
vector< fdc_hit_t > fdc_hits
Definition: DTrackFinder.h:148
bool DTrackFinder_cdc_hit_cosmics_cmp(const DCDCTrackHit *a, const DCDCTrackHit *b)
Definition: DTrackFinder.cc:10
bool LinkCDCSegments(void)
double sqrt(double)
bool MatchCDCHit(const DVector3 &vhat, const DVector3 &pos0, const DCDCTrackHit *hit, double cut)
#define S(str)
Definition: hddm-c.cpp:84
DMatrix4x1 FindStateVector(void) const
jerror_t FindStateVector(bool IsCosmics=false)
void Reset(void)
Definition: DTrackFinder.cc:66
int ring
Definition: DCDCWire.h:80
double CDC_MATCH_RADIUS
Definition: DTrackFinder.h:153
double CDC_MATCH_PHI
Definition: DTrackFinder.h:153
bool FindAxialSegments(void)
double CDC_COSMIC_MATCH_PHI
Definition: DTrackFinder.h:153
bool FindIntersectionsWithCylinder(double R, const DVector3 &dir, const DVector3 &pos, DVector3 &out1, DVector3 &out2) const
vector< cdc_segment_t > axial_segments
Definition: DTrackFinder.h:145
TDirectory * dir
Definition: bcal_hist_eff.C:31
double FindDoca(double z, const DMatrix4x1 &S, const DVector3 &wdir, const DVector3 &origin, DVector3 *poca=NULL) const
TH2F * temp
vector< const DCDCTrackHit * > stereo_hits
Definition: DTrackFinder.h:103
TH1I * hFDCLayerFirst
Definition: DTrackFinder.h:142
bool DTrackFinder_cdc_hit_cmp(const DCDCTrackHit *a, const DCDCTrackHit *b)
Definition: DTrackFinder.cc:14