Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackHitSelectorALT2.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTrackHitSelectorALT2.cc
4 // Created: Fri Feb 6 08:22:58 EST 2009
5 // Creator: davidl (on Darwin harriet.jlab.org 9.6.0 i386)
6 //
7 
8 #include <cmath>
9 using namespace std;
10 
11 #include <TROOT.h>
12 
14 
15 #include "DTrackHitSelectorALT2.h"
16 
17 #ifndef ansi_escape
18 #define ansi_escape ((char)0x1b)
19 #define ansi_bold ansi_escape<<"[1m"
20 #define ansi_normal ansi_escape<<"[0m"
21 #define ansi_red ansi_escape<<"[31m"
22 #define ansi_green ansi_escape<<"[32m"
23 #define ansi_blue ansi_escape<<"[34m"
24 #endif // ansi_escape
25 
26 #define ONE_OVER_SQRT12 0.288675
27 #define ONE_OVER_12 0.08333333333333
28 #define EPS 1e-6
29 
30 bool static DTrackHitSelector_cdchit_cmp(pair<double,const DCDCTrackHit *>a,
31  pair<double,const DCDCTrackHit *>b){
32  if (a.second->wire->ring!=b.second->wire->ring)
33  return (a.second->wire->ring>b.second->wire->ring);
34  return (a.first>b.first);
35 }
36 bool static DTrackHitSelector_fdchit_cmp(pair<double,const DFDCPseudo *>a,
37  pair<double,const DFDCPseudo *>b){
38  if (a.second->wire->layer!=b.second->wire->layer)
39  return (a.second->wire->layer>b.second->wire->layer);
40  return (a.first>b.first);
41 }
42 
44  if (a->wire->ring != b->wire->ring) return (a->wire->ring < b->wire->ring);
45  return (a->wire->straw < b->wire->straw);
46 }
47 
48 bool static DTrackHitSelector_fdchit_in_cmp(const DFDCPseudo *a, const DFDCPseudo *b){
49  if (a->wire->layer != b->wire->layer) return (a->wire->layer < b->wire->layer);
50  return (a->wire->wire < b->wire->wire);
51 }
52 
53 
54 //---------------------------------
55 // DTrackHitSelectorALT2 (Constructor)
56 //---------------------------------
57 DTrackHitSelectorALT2::DTrackHitSelectorALT2(jana::JEventLoop *loop, int32_t runnumber):DTrackHitSelector(loop)
58 {
59  HS_DEBUG_LEVEL = 0;
60  MAKE_DEBUG_TREES = false;
61  MIN_HIT_PROB_CDC = 0.01;
62  MIN_HIT_PROB_FDC = 0.01;
67  MAX_DOCA=2.5;
68 
69  gPARMS->SetDefaultParameter("TRKFIT:MAX_DOCA",MAX_DOCA,"Maximum doca for associating hit with track");
70 
71  gPARMS->SetDefaultParameter("TRKFIT:HS_DEBUG_LEVEL", HS_DEBUG_LEVEL, "Debug verbosity level for hit selector used in track fitting (0=no debug messages)");
72  gPARMS->SetDefaultParameter("TRKFIT:MAKE_DEBUG_TREES", MAKE_DEBUG_TREES, "Create a TTree with debugging info on hit selection for the FDC and CDC");
73  gPARMS->SetDefaultParameter("TRKFIT:MIN_HIT_PROB_CDC", MIN_HIT_PROB_CDC, "Minimum probability a CDC hit may have to be associated with a track to be included in list passed to fitter");
74  gPARMS->SetDefaultParameter("TRKFIT:MIN_HIT_PROB_FDC", MIN_HIT_PROB_FDC, "Minimum probability a FDC hit may have to be associated with a track to be included in list passed to fitter");
75  gPARMS->SetDefaultParameter("TRKFIT:MIN_FDC_SIGMA_ANODE_CANDIDATE", MIN_FDC_SIGMA_ANODE_CANDIDATE, "Minimum sigma used for FDC anode hits on track candidates");
76  gPARMS->SetDefaultParameter("TRKFIT:MIN_FDC_SIGMA_CATHODE_CANDIDATE", MIN_FDC_SIGMA_CATHODE_CANDIDATE, "Minimum sigma used for FDC cathode hits on track candidates");
77  gPARMS->SetDefaultParameter("TRKFIT:MIN_FDC_SIGMA_ANODE_WIREBASED", MIN_FDC_SIGMA_ANODE_WIREBASED, "Minimum sigma used for FDC anode hits on wire-based tracks");
78  gPARMS->SetDefaultParameter("TRKFIT:MIN_FDC_SIGMA_CATHODE_WIREBASED", MIN_FDC_SIGMA_CATHODE_WIREBASED, "Minimum sigma used for FDC cathode hits on wire-based tracks");
79 
80  cdchitsel = NULL;
81  fdchitsel = NULL;
82  if(MAKE_DEBUG_TREES){
83  loop->GetJApplication()->Lock();
84 
85  cdchitsel= (TTree*)gROOT->FindObject("cdchitsel");
86  if(!cdchitsel){
87  cdchitsel = new TTree("cdchitsel", "CDC Hit Selector");
88  cdchitsel->Branch("H", &cdchitdbg, "fit_type/I:p/F:theta:mass:sigma:x:y:z:s:itheta02:itheta02s:itheta02s2:dist:doca:resi:chisq:prob:sig_phi:sig_lambda:sig_pt");
89  }else{
90  _DBG__;
91  jerr<<" !!! WARNING !!!"<<endl;
92  jerr<<"It appears that the cdchitsel TTree is already defined."<<endl;
93  jerr<<"This is probably means you are running with multiple threads."<<endl;
94  jerr<<"To avoid complication, filling of the hit selector debug"<<endl;
95  jerr<<"trees will be disabled for this thread."<<endl;
96  _DBG__;
97  cdchitsel = NULL;
98  }
99 
100  fdchitsel= (TTree*)gROOT->FindObject("fdchitsel");
101  if(!fdchitsel){
102  fdchitsel = new TTree("fdchitsel", "FDC Hit Selector");
103  fdchitsel->Branch("H", &fdchitdbg, "fit_type/I:p/F:theta:mass:sigma_anode:sigma_cathode:x:y:z:s:itheta02:itheta02s:itheta02s2:dist:doca:resi:u:u_cathodes:resic:chisq:prob:sig_phi:sig_lambda:sig_pt");
104  }else{
105  _DBG__;
106  jerr<<" !!! WARNING !!!"<<endl;
107  jerr<<"It appears that the fdchitsel TTree is already defined."<<endl;
108  jerr<<"This is probably means you are running with multiple threads."<<endl;
109  jerr<<"To avoid complication, filling of the hit selector debug"<<endl;
110  jerr<<"trees will be disabled for this thread."<<endl;
111  _DBG__;
112  fdchitsel = NULL;
113  }
114 
115  loop->GetJApplication()->Unlock();
116  }
117 
118  DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
119  bfield = dapp->GetBfield(runnumber); // this should be run number based!
120 
121 }
122 
123 //---------------------------------
124 // ~DTrackHitSelectorALT2 (Destructor)
125 //---------------------------------
127 {
128 
129 }
130 
131 //---------------------------------
132 // GetCDCHits
133 //---------------------------------
134 void DTrackHitSelectorALT2::GetCDCHits(double Bz,double q,
135  const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DCDCTrackHit*> &cdchits_in, vector<const DCDCTrackHit*> &cdchits_out, int N) const
136 {
137  // Vector of pairs storing the hit with the probability it is on the track
138  vector<pair<double,const DCDCTrackHit*> >cdchits_tmp;
139 
140  // Sort so innermost ring is first and outermost is last
141  vector<const DCDCTrackHit*> cdchits_in_sorted = cdchits_in;
142  sort(cdchits_in_sorted.begin(),cdchits_in_sorted.end(),DTrackHitSelector_cdchit_in_cmp);
143 
144  // The variance on the residual due to measurement error.
145  double var=0.25*2.4336*ONE_OVER_12;
146 
147  // To estimate the impact of errors in the track momentum on the variance
148  // of the residual, use a helical approximation.
149  double a=-0.003*Bz*q;
150  DVector3 mom=extrapolations[extrapolations.size()/2].momentum;
151  double p=mom.Mag();
152  double p_over_a=p/a;
153  double a_over_p=1./p_over_a;
154  double lambda=M_PI_2-mom.Theta();
155  double tanl=tan(lambda);
156  double tanl2=tanl*tanl;
157  double sinl=sin(lambda);
158  double cosl=cos(lambda);
159  double cosl2=cosl*cosl;
160  double sinl2=sinl*sinl;
161  double pt_over_a=cosl*p_over_a;
162 
163  // variances
164  double var_lambda_res=0.;
165  double var_phi_radial=0.;
166  double var_x0=0.0,var_y0=0.0;
167  double var_k=0.;
168 
169  // Loop over all the CDC hits looking for matches with the track
170  bool outermost_hit=true;
171  vector<const DCDCTrackHit*>::const_reverse_iterator iter;
172  for(iter=cdchits_in_sorted.rbegin(); iter!=cdchits_in_sorted.rend(); iter++){
173  const DCDCTrackHit *hit = *iter;
174  DVector3 origin=hit->wire->origin;
175  DVector3 dir=hit->wire->udir;
176  double ux=dir.x();
177  double uy=dir.y();
178  double uz=dir.z();
179  double z0=origin.z();
180  double d2=0.,d2_old=1.e6;
181  double s=0.;
182  DVector3 old_trackpos;
183  for (unsigned int i=0;i<extrapolations.size();i++){
184  DVector3 trackpos=extrapolations[i].position;
185  double dz=trackpos.z()-z0;
186  DVector3 wirepos=origin+dz/uz*dir;
187  d2=(trackpos-wirepos).Perp2();
188  if (d2>d2_old){
189  if (d2<4){ // has to be reasonably close to the wire in question
190  double phi=extrapolations[i].momentum.Phi();
191  double sinphi=sin(phi);
192  double cosphi=cos(phi);
193  // Variables relating wire direction and track direction
194  double my_ux=ux*sinl-cosl*cosphi;
195  double my_uy=uy*sinl-cosl*sinphi;
196  double denom=my_ux*my_ux+my_uy*my_uy;
197  // For simplicity make a linear approximation for the path increment
198  double ds=((old_trackpos.x()-origin.x()-ux*dz)*my_ux
199  +(old_trackpos.y()-origin.y()-uy*dz)*my_uy)/denom;
200  wirepos+=ds*dir;
201  double dx=old_trackpos.x()+mom.X()/mom.Mag()*ds-wirepos.x();
202  double dy=old_trackpos.y()+mom.Y()/mom.Mag()*ds-wirepos.y();
203  d2_old=d2;
204  d2=dx*dx+dy*dy;
205  if (d2>d2_old){
206  // linear approximation did not work...
207  d2=d2_old;
208  }
209  // Variance in dip angle due to multiple scattering
210  double var_lambda = extrapolations[i].theta2ms_sum/3.;
211  // variance in phi due to multiple scattering
212  double var_phi=var_lambda*(1.+tanl2);
213 
214  if (outermost_hit){
215  // variance in the curvature k due to resolution and multiple scattering
216  double s_sq=s*s;
217  double s_4=s_sq*s_sq;
218  double sum_s_theta_ms=extrapolations[i].s_theta_ms_sum;
219  double var_k_ms=(4./3.)*sum_s_theta_ms*sum_s_theta_ms/s_4;
220  double var_k_res=var*0.0720/double(N+4)/s_4/(cosl2*cosl2);
221  var_k=var_k_ms+var_k_res;
222 
223  // Variance in dip angle due to measurement error
224  var_lambda_res=12.0*var*double(N-1)/double(N*(N+1))
225  *sinl2*sinl2/s_sq;
226 
227  // Variance in phi, crude approximation
228  double tan_s_2R=tan(s*cosl/(2.*pt_over_a));
229  var_phi_radial=tan_s_2R*tan_s_2R*pt_over_a*pt_over_a*var_k;
230 
231  outermost_hit=false;
232  }
233  // Include error in lambda due to measurements
234  var_lambda+=var_lambda_res;
235 
236  // Include uncertainty in phi due to uncertainty in the center of
237  // the circle
238  var_phi+=var_phi_radial;
239 
240  // Variance in position due to multiple scattering
241  double var_pos_ms=extrapolations[i].s_theta_ms_sum/3.;
242 
243  // Hit doca and residual
244  double doca=sqrt(d2);
245  double dist=0.39;
246  double resi=dist-doca;
247 
248  // Variances in x and y due to uncertainty in track parameters
249  double as_over_p=s*a_over_p;
250  double sin_as_over_p=sin(as_over_p);
251  double cos_as_over_p=cos(as_over_p);
252  double one_minus_cos_as_over_p=1-cos_as_over_p;
253  double diff1=sin_as_over_p-as_over_p*cos_as_over_p;
254  double diff2=one_minus_cos_as_over_p-as_over_p*sin_as_over_p;
255  double dx_dk=2.*pt_over_a*pt_over_a*(sinphi*diff2-cosphi*diff1);
256  double dx_dcosl=p_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
257  double dx_dphi=-pt_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
258  double var_x=var_x0+dx_dk*dx_dk*var_k+var_pos_ms
259  +dx_dcosl*dx_dcosl*sinl*sinl*var_lambda+dx_dphi*dx_dphi*var_phi;
260 
261  double dy_dk=-2.*pt_over_a*pt_over_a*(sinphi*diff1+cosphi*diff2);
262  double dy_dcosl=p_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
263  double dy_dphi=pt_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
264  double var_y=var_y0+dy_dk*dy_dk*var_k+var_pos_ms
265  +dy_dcosl*dy_dcosl*sinl*sinl*var_lambda+dy_dphi*dy_dphi*var_phi;
266 
267  double dd_dx=dx/doca;
268  double dd_dy=dy/doca;
269  double var_d=dd_dx*dd_dx*var_x+dd_dy*dd_dy*var_y;
270  double chisq=resi*resi/(var+var_d);
271 
272  // Use chi-sq probability function with Ndof=1 to calculate probability
273  double probability = TMath::Prob(chisq, 1);
274  if(probability>=MIN_HIT_PROB_CDC){
275  pair<double,const DCDCTrackHit*>myhit;
276  myhit.first=probability;
277  myhit.second=hit;
278  cdchits_tmp.push_back(myhit);
279  }
280 
281  // Optionally fill debug tree
282  if(cdchitsel){
284  cdchitdbg.p = p;
285  cdchitdbg.theta = extrapolations[i].momentum.Theta();
286  //cdchitdbg.mass = mass;
287  cdchitdbg.sigma = sqrt(var+var_d);
288  cdchitdbg.x = old_trackpos.X();
289  cdchitdbg.y = old_trackpos.Y();
290  cdchitdbg.z = old_trackpos.Z();
291  cdchitdbg.s = s;
292  cdchitdbg.itheta02 = extrapolations[i].theta2ms_sum;
293  //cdchitdbg.itheta02s = last_step->itheta02s;
294  //cdchitdbg.itheta02s2 = last_step->itheta02s2;
295  cdchitdbg.dist = dist;
296  cdchitdbg.doca = doca;
297  cdchitdbg.resi = resi;
298  cdchitdbg.chisq = chisq;
299  cdchitdbg.prob = probability;
300  cdchitdbg.sig_phi=sqrt(var_phi);
301  cdchitdbg.sig_lambda=sqrt(var_lambda);
302  cdchitdbg.sig_pt=fabs(2.*pt_over_a)*sqrt(var_k);
303 
304  cdchitsel->Fill();
305  }
306 
307  if(HS_DEBUG_LEVEL>10){
308  _DBG_;
309  if (probability>=MIN_HIT_PROB_CDC) jerr<<"---> ";
310  jerr<<"s="<<s<<" t=" <<hit->tdrift << " doca="<<doca<<" dist="<<dist<<" resi="<<resi<<" sigma="/*<<sigma_total*/<<" prob="<<probability<<endl;
311  }
312  }
313  break;
314  }
315  d2_old=d2;
316  old_trackpos=trackpos;
317  s=extrapolations[i].s;
318  }
319 
320  }
321 
322  // Order according to ring number and probability, then put the hits in the
323  // output list with the following algorithm: hits with the highest
324  // probability in a given ring are automatically put in the output list,
325  // but if there is more than one hit in a given ring, only those hits
326  // that are within +/-1 of the straw # of the most probable hit are added
327  // to the list.
328  sort(cdchits_tmp.begin(),cdchits_tmp.end(),DTrackHitSelector_cdchit_cmp);
329  int old_straw=1000,old_ring=1000;
330  for (unsigned int i=0;i<cdchits_tmp.size();i++){
331  if (cdchits_tmp[i].second->wire->ring!=old_ring ||
332  abs(cdchits_tmp[i].second->wire->straw-old_straw)==1){
333  cdchits_out.push_back(cdchits_tmp[i].second);
334  }
335  old_straw=cdchits_tmp[i].second->wire->straw;
336  old_ring=cdchits_tmp[i].second->wire->ring;
337  }
338 }
339 
340 //---------------------------------
341 // GetCDCHits
342 //---------------------------------
343 void DTrackHitSelectorALT2::GetCDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector<const DCDCTrackHit*> &cdchits_in, vector<const DCDCTrackHit*> &cdchits_out, int N) const
344 {
345  // Vector of pairs storing the hit with the probability it is on the track
346  vector<pair<double,const DCDCTrackHit*> >cdchits_tmp;
347 
348  /// Determine the probability that for each CDC hit that it came from the
349  /// track with the given trajectory.
350  ///
351  /// This will calculate a probability for each CDC hit that
352  /// it came from the track represented by the given
353  /// DReference trajectory. The probability is based on
354  /// the residual between the distance of closest approach
355  /// of the trajectory to the wire and the drift time for
356  /// time-based tracks and the distance to the wire for
357  /// wire-based tracks.
358 
359  // Sort so innermost ring is first and outermost is last
360  vector<const DCDCTrackHit*> cdchits_in_sorted = cdchits_in;
361  sort(cdchits_in_sorted.begin(),cdchits_in_sorted.end(),DTrackHitSelector_cdchit_in_cmp);
362 
363  // Calculate beta of particle.
364  //double my_mass=rt->GetMass();
365  // double one_over_beta =sqrt(1.0+my_mass*my_mass/rt->swim_steps[0].mom.Mag2());
366 
367  // The variance on the residual due to measurement error.
368  double var=0.25*2.4336*ONE_OVER_12;
369 
370  // To estimate the impact of errors in the track momentum on the variance of the residual,
371  // use a helical approximation.
372  const DReferenceTrajectory::swim_step_t *my_step=&rt->swim_steps[0];
373  double Bz0=my_step->B.z();
374  double a=-0.003*Bz0*rt->q;
375  double p=my_step->mom.Mag();
376  double p_over_a=p/a;
377  double a_over_p=1./p_over_a;
378  double lambda=M_PI_2-my_step->mom.Theta();
379  double cosl=cos(lambda);
380  double sinl=sin(lambda);
381  double sinl2=sinl*sinl;
382  double cosl2=cosl*cosl;
383  double tanl=tan(lambda);
384  double tanl2=tanl*tanl;
385  double pt_over_a=cosl*p_over_a;
386  double phi=my_step->mom.Phi();
387  double cosphi=cos(phi);
388  double sinphi=sin(phi);
389 
390  double var_lambda_res=0.;
391  double var_phi_radial=0.;
392  double var_x0=0.0,var_y0=0.0;
393  double mass=rt->GetMass();
394  double one_over_beta=sqrt(1.+mass*mass/(p*p));
395  double var_pt_factor=0.016*one_over_beta/(cosl*a);
396  double var_pt_over_pt_sq=0.;
397 
398  // Keep track of straws and rings
399  int old_straw=1000,old_ring=1000;
400 
401  // Loop over hits
402  bool outermost_hit=true;
403  vector<const DCDCTrackHit*>::const_reverse_iterator iter;
404  for(iter=cdchits_in_sorted.rbegin(); iter!=cdchits_in_sorted.rend(); iter++){
405  const DCDCTrackHit *hit = *iter;
406 
407  // Skip hit if it is on the same wire as the previous hit
408  if (hit->wire->ring == old_ring && hit->wire->straw==old_straw){
409  //_DBG_ << "ring " << hit->wire->ring << " straw " << hit->wire->straw << endl;
410  continue;
411  }
412  old_ring=hit->wire->ring;
413  old_straw=hit->wire->straw;
414 
415  // Find the DOCA to this wire
416  double s=0.;
417  double doca = rt->DistToRT(hit->wire, &s);
418 
419  if(!isfinite(doca)) continue;
420  if(!isfinite(s))continue;
421  if (s<1.) continue;
422  if (doca>MAX_DOCA) continue;
423 
424  const DReferenceTrajectory::swim_step_t *last_step = rt->GetLastSwimStep();
425 
426  // Position along trajectory
427  DVector3 pos=rt->GetLastDOCAPoint();
428 
429  // Compensate for the fact that the field at the "origin" of the
430  // track does not correspond to the average Bz used to compute pt
431  double Bratio=last_step->B.z()/Bz0;
432  double invBratio=1./Bratio;
433  pt_over_a*=invBratio;
434  p_over_a*=invBratio;
435  a_over_p*=Bratio;
436 
437  // Variances in angles due to multiple scattering
438  double var_lambda = last_step->itheta02/3.;
439  double var_phi=var_lambda*(1.+tanl2);
440 
441  if (outermost_hit){
442  // Fractional variance in the curvature k due to resolution and multiple scattering
443  double s_sq=s*s;
444  double var_k_over_k_sq_res=var*p_over_a*p_over_a*0.0720/double(N+4)/(s_sq*s_sq*sinl2)/cosl2;
445  double var_k_over_k_sq_ms=var_pt_factor*var_pt_factor*last_step->invX0/s;
446  // Fractional variance in pt
447  var_pt_over_pt_sq=var_k_over_k_sq_ms+var_k_over_k_sq_res;
448 
449  // Variance in dip angle due to measurement error
450  var_lambda_res=12.0*var*double(N-1)/double(N*(N+1))*cosl2*cosl2/s_sq;
451 
452  // Variance in phi, crude approximation
453  double tan_s_2R=tan(s*cosl/(2.*pt_over_a));
454  var_phi_radial=tan_s_2R*tan_s_2R*var_pt_over_pt_sq;
455 
456  outermost_hit=false;
457  }
458  // Include error in lambda due to measurements
459  var_lambda+=var_lambda_res;
460 
461  // Include uncertainty in phi due to uncertainty in the radius of
462  // the circle
463  var_phi+=var_phi_radial;
464 
465  // Get "measured" distance to wire.
466  double dist=0.39;
467 
468  // Residual
469  double resi = dist - doca;
470 
471  // Variance in position due to multiple scattering
472  double var_pos_ms=last_step->itheta02s2/3.;
473 
474  // Variances in x and y due to uncertainty in track parameters
475  double as_over_p=s*a_over_p;
476  double sin_as_over_p=sin(as_over_p);
477  double cos_as_over_p=cos(as_over_p);
478  double one_minus_cos_as_over_p=1-cos_as_over_p;
479  double diff1=sin_as_over_p-as_over_p*cos_as_over_p;
480  double diff2=one_minus_cos_as_over_p-as_over_p*sin_as_over_p;
481  double pdx_dp=pt_over_a*(cosphi*diff1-sinphi*diff2);
482  double dx_dcosl=p_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
483  double dx_dphi=-pt_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
484  double var_x=var_x0+pdx_dp*pdx_dp*var_pt_over_pt_sq+var_pos_ms
485  +dx_dcosl*dx_dcosl*sinl*sinl*var_lambda+dx_dphi*dx_dphi*var_phi;
486 
487  double pdy_dp=pt_over_a*(sinphi*diff1+cosphi*diff2);
488  double dy_dcosl=p_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
489  double dy_dphi=pt_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
490  double var_y=var_y0+pdy_dp*pdy_dp*var_pt_over_pt_sq+var_pos_ms
491  +dy_dcosl*dy_dcosl*sinl*sinl*var_lambda+dy_dphi*dy_dphi*var_phi;
492 
493 
494  DVector3 origin=hit->wire->origin;
495  DVector3 dir=hit->wire->udir;
496  double uz=dir.z();
497  double z0=origin.z();
498  DVector3 wirepos=origin+(pos.z()-z0)/uz*dir;
499  double dd_dx=(pos.x()-wirepos.x())/doca;
500  double dd_dy=(pos.y()-wirepos.y())/doca;
501  double var_d=dd_dx*dd_dx*var_x+dd_dy*dd_dy*var_y;
502 
503  double chisq=resi*resi/(var+var_d);
504 
505  // Use chi-sq probability function with Ndof=1 to calculate probability
506  double probability = TMath::Prob(chisq, 1);
507  if(probability>=MIN_HIT_PROB_CDC){
508  pair<double,const DCDCTrackHit*>myhit;
509  myhit.first=probability;
510  myhit.second=hit;
511  cdchits_tmp.push_back(myhit);
512  }
513 
514  // Optionally fill debug tree
515  if(cdchitsel){
516  cdchitdbg.fit_type = fit_type;
517  cdchitdbg.p = p;
518  cdchitdbg.theta = rt->swim_steps[0].mom.Theta();
519  cdchitdbg.mass = mass;
520  cdchitdbg.sigma = sqrt(var+var_d);
521  cdchitdbg.x = pos.X();
522  cdchitdbg.y = pos.Y();
523  cdchitdbg.z = pos.Z();
524  cdchitdbg.s = s;
525  cdchitdbg.itheta02 = last_step->itheta02;
526  cdchitdbg.itheta02s = last_step->itheta02s;
527  cdchitdbg.itheta02s2 = last_step->itheta02s2;
528  cdchitdbg.dist = dist;
529  cdchitdbg.doca = doca;
530  cdchitdbg.resi = resi;
531  cdchitdbg.chisq = chisq;
532  cdchitdbg.prob = probability;
533  cdchitdbg.sig_phi=sqrt(var_phi);
534  cdchitdbg.sig_lambda=sqrt(var_lambda);
535  cdchitdbg.sig_pt=sqrt(var_pt_over_pt_sq);
536 
537  cdchitsel->Fill();
538  }
539 
540  if(HS_DEBUG_LEVEL>10){
541  _DBG_;
542  if (probability>=MIN_HIT_PROB_CDC) jerr<<"---> ";
543  jerr<<"s="<<s<<" t=" <<hit->tdrift << " doca="<<doca<<" dist="<<dist<<" resi="<<resi<<" sigma="/*<<sigma_total*/<<" prob="<<probability<<endl;
544  }
545  }
546 
547  // Order according to ring number and probability, then put the hits in the
548  // output list with the following algorithm: hits with the highest
549  // probability in a given ring are automatically put in the output list,
550  // but if there is more than one hit in a given ring, only those hits
551  // that are within +/-1 of the straw # of the most probable hit are added
552  // to the list.
553  sort(cdchits_tmp.begin(),cdchits_tmp.end(),DTrackHitSelector_cdchit_cmp);
554  old_straw=1000,old_ring=1000;
555  for (unsigned int i=0;i<cdchits_tmp.size();i++){
556  if (cdchits_tmp[i].second->wire->ring!=old_ring ||
557  abs(cdchits_tmp[i].second->wire->straw-old_straw)==1){
558  cdchits_out.push_back(cdchits_tmp[i].second);
559  }
560  old_straw=cdchits_tmp[i].second->wire->straw;
561  old_ring=cdchits_tmp[i].second->wire->ring;
562  }
563 }
564 
565 //---------------------------------
566 // GetFDCHits
567 //---------------------------------
568 void DTrackHitSelectorALT2::GetFDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector<const DFDCPseudo*> &fdchits_in, vector<const DFDCPseudo*> &fdchits_out,int N) const
569 {
570  // Vector of pairs storing the hit with the probability it is on the track
571  vector<pair<double,const DFDCPseudo*> >fdchits_tmp;
572 
573  /// Determine the probability that for each FDC hit that it came from the
574  /// track with the given trajectory.
575  ///
576  /// This will calculate a probability for each FDC hit that
577  /// it came from the track represented by the given
578  /// DReference trajectory. The probability is based on
579  /// the residual between the distance of closest approach
580  /// of the trajectory to the wire and the drift distance
581  /// and the distance along the wire.
582 
583  // Sort so innermost ring is first and outermost is last
584  vector<const DFDCPseudo*> fdchits_in_sorted = fdchits_in;
585  sort(fdchits_in_sorted.begin(),fdchits_in_sorted.end(),DTrackHitSelector_fdchit_in_cmp);
586 
587  // The variance on the residual due to measurement error.
588  double var_anode = 0.25*ONE_OVER_12;
589  const double VAR_CATHODE_STRIPS=0.000225;
590  double var_cathode = VAR_CATHODE_STRIPS;
591 
592  // To estimate the impact of errors in the track momentum on the variance of the residual,
593  // use a helical approximation.
594  const DReferenceTrajectory::swim_step_t *my_step=&rt->swim_steps[0];
595  double Bz0=my_step->B.z();
596  double z0=my_step->origin.z();
597  double a=-0.003*Bz0*rt->q;
598  double p=my_step->mom.Mag();
599  double p_sq=p*p;
600  double p_over_a=p/a;
601  double a_over_p=1./p_over_a;
602  double lambda=M_PI_2-my_step->mom.Theta();
603  double cosl=cos(lambda);
604  double cosl2=cosl*cosl;
605  double sinl=sin(lambda);
606  double sinl2=sinl*sinl;
607  double tanl=tan(lambda);
608  double tanl2=tanl*tanl;
609  double pt_over_a=cosl*p_over_a;
610  double phi=my_step->mom.Phi();
611  double cosphi=cos(phi);
612  double sinphi=sin(phi);
613  double var_lambda=0.,var_phi=0.,var_lambda_res=0.;
614  double var_phi_radial=0.;
615  double mass=rt->GetMass();
616 
617  double var_x0=0.0,var_y0=0.0;
618  double var_pt_over_pt_sq=0.;
619 
620  // Loop over hits
621  bool most_downstream_hit=true;
622  vector<const DFDCPseudo*>::const_reverse_iterator iter;
623  for(iter=fdchits_in_sorted.rbegin(); iter!=fdchits_in_sorted.rend(); iter++){
624  const DFDCPseudo *hit = *iter;
625 
626  // Find the DOCA to this wire
627  double s=0.;
628  double doca = rt->DistToRT(hit->wire, &s);
629 
630  if(!isfinite(doca)) continue;
631  if(!isfinite(s))continue;
632  if (s<1.) continue;
633  if (doca>MAX_DOCA)continue;
634 
635  const DReferenceTrajectory::swim_step_t *last_step = rt->GetLastSwimStep();
636 
637  // Position along trajectory
638  DVector3 pos=rt->GetLastDOCAPoint();
639  double dz=pos.z()-z0;
640 
641  // Direction variables for wire
642  double cosa=hit->wire->udir.y();
643  double sina=hit->wire->udir.x();
644 
645  // Cathode Residual
646  double u=rt->GetLastDistAlongWire();
647  double u_cathodes = hit->s;
648  double resic = u - u_cathodes;
649 
650  // Get "measured" distance to wire.
651  double dist=0.25;
652 
653  // Take into account non-normal incidence to FDC plane
654  double pz=last_step->mom.z();
655  double tx=last_step->mom.x()/pz;
656  double ty=last_step->mom.y()/pz;
657  double tu=tx*cosa-ty*sina;
658  double alpha=atan(tu);
659  double cosalpha=cos(alpha);
660 
661  // Compensate for the fact that the field at the "origin" of the
662  // track does not correspond to the average Bz used to compute pt
663  double Bz=last_step->B.z();
664  double Bratio=Bz/Bz0;
665  double invBratio=1./Bratio;
666  pt_over_a*=invBratio;
667  p_over_a*=invBratio;
668  a_over_p*=Bratio;
669 
670  // Anode Residual
671  double resi = dist - doca/cosalpha;
672 
673  // Initialize some probability-related variables needed later
674  double probability=0.,chisq=0.;
675 
676  if (fit_type!=kHelical){
677  // Correct for deflection of avalanche position due to Lorentz force
678  double sign=(pos.x()*cosa-pos.y()*sina-hit->w)<0?1:-1.;
679  double ucor=0.1458*Bz*(1.-0.048*last_step->B.Perp())*sign*doca;
680  resic-=ucor;
681  }
682  else{
683  // Cathode variance due to Lorentz deflection
684  double max_deflection=0.1458*Bz*(1.-0.048*last_step->B.Perp())*0.5;
685  var_cathode=VAR_CATHODE_STRIPS+max_deflection*max_deflection/12.;
686  }
687  double var_tot=var_anode+var_cathode;
688 
689  // Variance in angles due to multiple scattering
690  var_lambda = last_step->itheta02/3.;
691  var_phi=var_lambda*(1.+tanl2);
692 
693  if (most_downstream_hit){
694  // Fractional variance in the curvature k due to resolution and multiple scattering
695  double s_sq=s*s;
696  double var_k_over_k_sq_res=var_tot*p_over_a*p_over_a
697  *0.0720/double(N+4)/(s_sq*s_sq)/cosl2;
698 
699 
700  double one_over_beta=sqrt(1.+mass*mass/p_sq);
701  double var_pt_factor=0.016*one_over_beta/(cosl*0.003*last_step->B.z());
702  double var_k_over_k_sq_ms=var_pt_factor*var_pt_factor*last_step->invX0/s;
703  // Fractional variance in pt
704  var_pt_over_pt_sq=var_k_over_k_sq_ms+var_k_over_k_sq_res;
705 
706  // Variance in dip angle due to measurement error
707  var_lambda_res=12.0*var_tot*double(N-1)/double(N*(N+1))
708  *sinl2*sinl2/s_sq;
709 
710  // Variance in phi, crude approximation
711  double tan_s_2R=tan(s*cosl/(2.*pt_over_a));
712  var_phi_radial=tan_s_2R*tan_s_2R*var_pt_over_pt_sq;
713 
714  most_downstream_hit=false;
715  }
716 
717  // Include error in lambda due to measurements
718  var_lambda+=var_lambda_res;
719 
720  // Include uncertainty in phi due to uncertainty in the center of
721  // the circle
722  var_phi+=var_phi_radial;
723 
724  var_phi=0.;
725  var_lambda=0.;
726 
727  // Variance in position due to multiple scattering
728  double var_pos_ms=last_step->itheta02s2/3.;
729 
730  // Variances in x and y due to uncertainty in track parameters
731  double as_over_p=s*a_over_p;
732  double sin_as_over_p=sin(as_over_p);
733  double cos_as_over_p=cos(as_over_p);
734  double one_minus_cos_as_over_p=1-cos_as_over_p;
735  double diff1=sin_as_over_p-as_over_p*cos_as_over_p;
736  double diff2=one_minus_cos_as_over_p-as_over_p*sin_as_over_p;
737  double pdx_dp=pt_over_a*(cosphi*diff1-sinphi*diff2);
738  double dx_ds=cosl*(cosphi*cos_as_over_p-sinphi*sin_as_over_p);
739  double ds_dcosl=dz*cosl/(sinl*sinl2);
740  double dx_dcosl
741  =p_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p)
742  +dx_ds*ds_dcosl;
743  double dx_dphi=-pt_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
744  double var_z0=2.*tanl2*(var_tot)*double(2*N-1)/double(N*(N+1));
745 
746  double var_x=var_x0+pdx_dp*pdx_dp*var_pt_over_pt_sq+var_pos_ms
747  +dx_dcosl*dx_dcosl*sinl2*var_lambda+dx_dphi*dx_dphi*var_phi
748  +dx_ds*dx_ds*var_z0/sinl2;
749 
750  double pdy_dp=pt_over_a*(sinphi*diff1+cosphi*diff2);
751  double dy_ds=cosl*(sinphi*cos_as_over_p+cosphi*sin_as_over_p);
752  double dy_dcosl
753  =p_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p)
754  +dy_ds*ds_dcosl;
755  double dy_dphi=pt_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
756  double var_y=var_y0+pdy_dp*pdy_dp*var_pt_over_pt_sq+var_pos_ms
757  +dy_dcosl*dy_dcosl*sinl2*var_lambda+dy_dphi*dy_dphi*var_phi
758  +dy_ds*dy_ds*var_z0/sinl2;
759 
760  // Rotate from global coordinate system into FDC local system
761  double cos2a=cosa*cosa;
762  double sin2a=sina*sina;
763  double var_d=(cos2a*var_x+sin2a*var_y)/(cosalpha*cosalpha);
764  double var_u=cos2a*var_y+sin2a*var_x;
765 
766  if (fit_type!=kHelical){
767  // Factors take into account improved resolution after wire-based fit
768  var_d*=0.1;
769  var_u*=0.1;
770  }
771 
772  // Calculate chisq
773  chisq = resi*resi/(var_d+var_anode)+resic*resic/(var_u+var_cathode);
774 
775  // Probability of this hit being on the track
776  probability = TMath::Prob(chisq,2);
777 
778  if(probability>=MIN_HIT_PROB_FDC){
779  pair<double,const DFDCPseudo*>myhit;
780  myhit.first=probability;
781  myhit.second=hit;
782  fdchits_tmp.push_back(myhit);
783  }
784 
785  // Optionally fill debug tree
786  if(fdchitsel){
787  fdchitdbg.fit_type = fit_type;
788  fdchitdbg.p = p;
789  fdchitdbg.theta = rt->swim_steps[0].mom.Theta();
790  fdchitdbg.mass = mass;
791  fdchitdbg.sigma_anode = sqrt(var_d+var_anode);
792  fdchitdbg.sigma_cathode = sqrt(var_u+var_cathode);
793  fdchitdbg.x = pos.X();
794  fdchitdbg.y = pos.Y();
795  fdchitdbg.z = pos.Z();
796  fdchitdbg.s = s;
797  fdchitdbg.itheta02 = last_step->itheta02;
798  fdchitdbg.itheta02s = last_step->itheta02s;
799  fdchitdbg.itheta02s2 = last_step->itheta02s2;
800  fdchitdbg.dist = dist;
801  fdchitdbg.doca = doca;
802  fdchitdbg.resi = resi;
803  fdchitdbg.u = u;
804  fdchitdbg.u_cathodes = u_cathodes;
805  fdchitdbg.resic = resic;
806  fdchitdbg.chisq = chisq;
807  fdchitdbg.prob = probability;
808  fdchitdbg.sig_phi=sqrt(var_phi);
809  fdchitdbg.sig_lambda=sqrt(var_lambda);
810  fdchitdbg.sig_pt=sqrt(var_pt_over_pt_sq);
811 
812  fdchitsel->Fill();
813  }
814 
815  if(HS_DEBUG_LEVEL>10){
816  _DBG_;
817  if(probability>=MIN_HIT_PROB_FDC)jerr<<"----> ";
818  jerr<<"s="<<s<<" doca="<<doca<<" dist="<<dist<<" resi="<<resi<<" resic="<<resic<<" chisq="<<chisq<<" prob="<<probability<<endl;
819  }
820  }
821  // Order according to layer number and probability,then put the hits in the
822  // output list with the following algorithm: hits with the highest
823  // probability in a given layer are automatically put in the output list,
824  // but if there is more than one hit in a given layer, only those hits
825  // that are within +/-1 of the wire # of the most probable hit are added
826  // to the list.
827  sort(fdchits_tmp.begin(),fdchits_tmp.end(),DTrackHitSelector_fdchit_cmp);
828  int old_layer=1000,old_wire=1000;
829  for (unsigned int i=0;i<fdchits_tmp.size();i++){
830  if (fdchits_tmp[i].second->wire->layer!=old_layer ||
831  abs(fdchits_tmp[i].second->wire->wire-old_wire)==1){
832  fdchits_out.push_back(fdchits_tmp[i].second);
833  }
834  old_wire=fdchits_tmp[i].second->wire->wire;
835  old_layer=fdchits_tmp[i].second->wire->layer;
836  }
837 }
838 void DTrackHitSelectorALT2::GetFDCHits(double Bz,double q,
839  const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DFDCPseudo*> &fdchits_in, vector<const DFDCPseudo*> &fdchits_out,int N) const
840 {
841  // Vector of pairs storing the hit with the probability it is on the track
842  vector<pair<double,const DFDCPseudo*> >fdchits_tmp;
843 
844  /// Determine the probability that for each FDC hit that it came from the
845  /// track with the given trajectory. The probability is based on
846  /// the residual between the distance of closest approach
847  /// of the trajectory to the wire and the drift distance
848  /// and the distance along the wire.
849 
850  // Sort so innermost ring is first and outermost is last
851  vector<const DFDCPseudo*> fdchits_in_sorted = fdchits_in;
852  sort(fdchits_in_sorted.begin(),fdchits_in_sorted.end(),DTrackHitSelector_fdchit_in_cmp);
853 
854  // The variance on the residual due to measurement error.
855  // The variance on the residual due to measurement error.
856  double var_anode = 0.25*ONE_OVER_12;
857  const double VAR_CATHODE_STRIPS=0.000225;
858  double var_cathode = VAR_CATHODE_STRIPS+0.15*0.15*ONE_OVER_12;
859  double var_tot=var_anode+var_cathode;
860 
861  // To estimate the impact of errors in the track momentum on the variance of the residual,
862  // use a helical approximation.
863  double a=-0.003*Bz*q;
864  DVector3 mom=extrapolations[extrapolations.size()/2].momentum;
865  double p=mom.Mag();
866  double p_over_a=p/a;
867  double a_over_p=1./p_over_a;
868  double lambda=M_PI_2-mom.Theta();
869  double tanl=tan(lambda);
870  double tanl2=tanl*tanl;
871  double sinl=sin(lambda);
872  double cosl=cos(lambda);
873  double cosl2=cosl*cosl;
874  double sinl2=sinl*sinl;
875  double pt_over_a=cosl*p_over_a;
876  double z0=extrapolations[0].position.z();
877  // variances
878  double var_lambda=0.,var_phi=0.,var_lambda_res=0.,var_k=0.;
879  double var_phi_radial=0.;
880  double var_x0=0.0,var_y0=0.0;
881  double var_z0=2.*tanl2*(var_tot)*double(2*N-1)/double(N*(N+1));
882 
883  // Loop over hits
884  bool most_downstream_hit=true;
885  int last_extrapolation_index=extrapolations.size()-1;
886  vector<const DFDCPseudo*>::const_reverse_iterator iter;
887  for(iter=fdchits_in_sorted.rbegin(); iter!=fdchits_in_sorted.rend(); iter++){
888  const DFDCPseudo *hit = *iter;
889  for (int k=last_extrapolation_index;k>=0;k--){
890  // Position along trajectory
891  DVector3 pos=extrapolations[k].position;
892  double dz=pos.z()-z0;
893  double s=extrapolations[k].s;
894  if (fabs(pos.z()-hit->wire->origin.z())<0.5){
895  // Variance in dip angle due to multiple scattering
896  var_lambda = extrapolations[k].theta2ms_sum/3.;
897  // the above expression seems to lead to overestimation of the uncertainty in the dip angle after the wire-based pass..
898  var_lambda*=0.01;
899  // Variance in phi due to multiple scattering
900  var_phi=var_lambda*(1.+tanl2);
901 
902  // azimuthal angle
903  double phi=extrapolations[k].momentum.Phi();
904  double sinphi=sin(phi);
905  double cosphi=cos(phi);
906 
907  if (most_downstream_hit){
908  // variance in the curvature k due to resolution and multiple scattering
909  double s_sq=s*s;
910  double s_4=s_sq*s_sq;
911  double sum_s_theta_ms=extrapolations[k].s_theta_ms_sum;
912  double var_k_ms=(4./3.)*sum_s_theta_ms*sum_s_theta_ms/s_4;
913  double var_k_res=var_tot*0.0720/double(N+4)/s_4/(cosl2*cosl2);
914  var_k=var_k_ms+var_k_res;
915 
916  // Variance in dip angle due to measurement error
917  var_lambda_res=12.0*var_tot*double(N-1)/double(N*(N+1))
918  *sinl2*sinl2/s_sq;
919 
920  // Variance in phi, crude approximation
921  double tan_s_2R=tan(s*cosl/(2.*pt_over_a));
922  var_phi_radial=tan_s_2R*tan_s_2R*pt_over_a*pt_over_a*var_k;
923 
924  most_downstream_hit=false;
925  }
926  // Include error in lambda due to measurements
927  var_lambda+=var_lambda_res;
928 
929  // Include uncertainty in phi due to uncertainty in the center of
930  // the circle
931  var_phi+=var_phi_radial;
932 
933  // Variance in position due to multiple scattering
934  double var_pos_ms=extrapolations[k].s_theta_ms_sum/3.;
935 
936  // doca to wire
937  double x=pos.x();
938  double y=pos.y();
939  double dx=hit->xy.X()-x;
940  double dy=hit->xy.Y()-y;
941  double doca=sqrt(dx*dx+dy*dy);
942 
943  // Direction variables for wire
944  double cosa=hit->wire->udir.y();
945  double sina=hit->wire->udir.x();
946 
947  // Cathode Residual
948  double u=x*sina+y*cosa;
949  double u_cathodes = hit->s;
950  double resic = u - u_cathodes;
951 
952  // Get "measured" distance to wire.
953  double dist=0.25;
954 
955  // Take into account non-normal incidence to FDC plane
956  double pz=extrapolations[k].momentum.z();
957  double tx=extrapolations[k].momentum.x()/pz;
958  double ty=extrapolations[k].momentum.y()/pz;
959  double tu=tx*cosa-ty*sina;
960  double alpha=atan(tu);
961  double cosalpha=cos(alpha);
962 
963  // Anode Residual
964  double resi = dist - doca/cosalpha;
965 
966  // Initialize some probability-related variables needed later
967  double probability=0.,chisq=0.;
968 
969  // Variances in x and y due to uncertainty in track parameters
970  double as_over_p=s*a_over_p;
971  double sin_as_over_p=sin(as_over_p);
972  double cos_as_over_p=cos(as_over_p);
973  double one_minus_cos_as_over_p=1-cos_as_over_p;
974  double diff1=sin_as_over_p-as_over_p*cos_as_over_p;
975  double diff2=one_minus_cos_as_over_p-as_over_p*sin_as_over_p;
976  double dx_ds=cosl*(cosphi*cos_as_over_p-sinphi*sin_as_over_p);
977  double ds_dcosl=dz*cosl/(sinl*sinl2);
978  double dx_dcosl
979  =p_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p)
980  +dx_ds*ds_dcosl;
981  double dx_dphi=-pt_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p);
982  double dx_dk=2.*pt_over_a*pt_over_a*(sinphi*diff2-cosphi*diff1);
983 
984  double var_x=var_x0+dx_dk*dx_dk*var_k+var_pos_ms
985  +dx_dcosl*dx_dcosl*sinl2*var_lambda+dx_dphi*dx_dphi*var_phi
986  +dx_ds*dx_ds*var_z0/sinl2;
987 
988  double dy_dk=-2.*pt_over_a*pt_over_a*(sinphi*diff1+cosphi*diff2);
989  double dy_ds=cosl*(sinphi*cos_as_over_p+cosphi*sin_as_over_p);
990  double dy_dcosl
991  =p_over_a*(sinphi*sin_as_over_p+cosphi*one_minus_cos_as_over_p)
992  +dy_ds*ds_dcosl;
993  double dy_dphi=pt_over_a*(cosphi*sin_as_over_p-sinphi*one_minus_cos_as_over_p);
994  double var_y=var_y0+dy_dk*dy_dk*var_k+var_pos_ms
995  +dy_dcosl*dy_dcosl*sinl2*var_lambda+dy_dphi*dy_dphi*var_phi
996  +dy_ds*dy_ds*var_z0/sinl2;
997 
998  // Rotate from global coordinate system into FDC local system
999  double cos2a=cosa*cosa;
1000  double sin2a=sina*sina;
1001  double var_d=(cos2a*var_x+sin2a*var_y)/(cosalpha*cosalpha);
1002  double var_u=cos2a*var_y+sin2a*var_x;
1003 
1004  // Factors take into account improved resolution after wire-based fit
1005  //var_d*=0.1;
1006  //var_u*=0.1;
1007 
1008  // Calculate chisq
1009  chisq = resi*resi/(var_d+var_anode)+resic*resic/(var_u+var_cathode);
1010 
1011  // Probability of this hit being on the track
1012  probability = TMath::Prob(chisq,2);
1013 
1014  if(probability>=MIN_HIT_PROB_FDC){
1015  pair<double,const DFDCPseudo*>myhit;
1016  myhit.first=probability;
1017  myhit.second=hit;
1018  fdchits_tmp.push_back(myhit);
1019  }
1020  // Optionally fill debug tree
1021  if(fdchitsel){
1023  fdchitdbg.p = p;
1024  fdchitdbg.theta = extrapolations[k].momentum.Theta();
1025  //fdchitdbg.mass = mass;
1026  fdchitdbg.sigma_anode = sqrt(var_d+var_anode);
1027  fdchitdbg.sigma_cathode = sqrt(var_u+var_cathode);
1028  fdchitdbg.x = pos.X();
1029  fdchitdbg.y = pos.Y();
1030  fdchitdbg.z = pos.Z();
1031  fdchitdbg.s = s;
1032  fdchitdbg.itheta02 = extrapolations[k].theta2ms_sum;
1033  //fdchitdbg.itheta02s = last_step->itheta02s;
1034  //fdchitdbg.itheta02s2 = last_step->itheta02s2;
1035  fdchitdbg.dist = dist;
1036  fdchitdbg.doca = doca;
1037  fdchitdbg.resi = resi;
1038  fdchitdbg.u = u;
1039  fdchitdbg.u_cathodes = u_cathodes;
1040  fdchitdbg.resic = resic;
1041  fdchitdbg.chisq = chisq;
1042  fdchitdbg.prob = probability;
1043  fdchitdbg.sig_phi=sqrt(var_phi);
1044  fdchitdbg.sig_lambda=sqrt(var_lambda);
1045  fdchitdbg.sig_pt=fabs(2.*pt_over_a)*sqrt(var_k);
1046 
1047  fdchitsel->Fill();
1048  }
1049 
1050  if(HS_DEBUG_LEVEL>10){
1051  _DBG_;
1052  if(probability>=MIN_HIT_PROB_FDC)jerr<<"----> ";
1053  jerr<<"s="<<s<<" doca="<<doca<<" dist="<<dist<<" resi="<<resi<<" resic="<<resic<<" chisq="<<chisq<<" prob="<<probability<<endl;
1054  }
1055 
1056  }
1057  }
1058 
1059  }
1060  // Order according to layer number and probability,then put the hits in the
1061  // output list with the following algorithm: hits with the highest
1062  // probability in a given layer are automatically put in the output list,
1063  // but if there is more than one hit in a given layer, only those hits
1064  // that are within +/-1 of the wire # of the most probable hit are added
1065  // to the list.
1066  sort(fdchits_tmp.begin(),fdchits_tmp.end(),DTrackHitSelector_fdchit_cmp);
1067  int old_layer=1000,old_wire=1000;
1068  for (unsigned int i=0;i<fdchits_tmp.size();i++){
1069  if (fdchits_tmp[i].second->wire->layer!=old_layer ||
1070  abs(fdchits_tmp[i].second->wire->wire-old_wire)==1){
1071  fdchits_out.push_back(fdchits_tmp[i].second);
1072  }
1073  old_wire=fdchits_tmp[i].second->wire->wire;
1074  old_layer=fdchits_tmp[i].second->wire->layer;
1075  }
1076 }
DVector2 xy
rough x,y coordinates in lab coordinate system
Definition: DFDCPseudo.h:100
DTrackHitSelectorALT2(jana::JEventLoop *loop, int32_t runnumber)
DApplication * dapp
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
const swim_step_t * GetLastSwimStep(void) const
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define y
DMagneticFieldMap * GetBfield(unsigned int run_number=1)
DVector3 GetLastDOCAPoint(void) const
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
void GetCDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector< const DCDCTrackHit * > &cdchits_in, vector< const DCDCTrackHit * > &cdchits_out, int N=20) const
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
double GetLastDistAlongWire(void) const
The DTrackHitSelector class is a base class for algorithms that will select hits from the drift chamb...
static bool DTrackHitSelector_fdchit_cmp(pair< double, const DFDCPseudo * >a, pair< double, const DFDCPseudo * >b)
int layer
1-24
Definition: DFDCWire.h:16
void GetFDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector< const DFDCPseudo * > &fdchits_in, vector< const DFDCPseudo * > &fdchits_out, int N=20) const
const DMagneticFieldMap * bfield
double DistToRT(double x, double y, double z) const
const double alpha
TLatex tx
int straw
Definition: DCDCWire.h:81
#define _DBG_
Definition: HDEVIO.h:12
double s
&lt; wire position computed from cathode data, assuming the avalanche occurs at the wire ...
Definition: DFDCPseudo.h:91
double GetMass(void) const
static bool DTrackHitSelector_cdchit_cmp(pair< double, const DCDCTrackHit * >a, pair< double, const DCDCTrackHit * >b)
#define _DBG__
Definition: HDEVIO.h:13
double w
Definition: DFDCPseudo.h:89
double sqrt(double)
double sin(double)
static bool DTrackHitSelector_cdchit_in_cmp(const DCDCTrackHit *a, const DCDCTrackHit *b)
int wire
1-N
Definition: DFDCWire.h:17
int ring
Definition: DCDCWire.h:80
#define ONE_OVER_12
static bool DTrackHitSelector_fdchit_in_cmp(const DFDCPseudo *a, const DFDCPseudo *b)
TDirectory * dir
Definition: bcal_hist_eff.C:31
union @6::@8 u