Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DTrackHitSelectorALT1.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DTrackHitSelectorALT1.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 "DTrackHitSelectorALT1.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 
28 bool static DTrackHitSelector_cdchit_cmp(pair<double,const DCDCTrackHit *>a,
29  pair<double,const DCDCTrackHit *>b){
30  if (a.second->wire->ring!=b.second->wire->ring)
31  return (a.second->wire->ring>b.second->wire->ring);
32  return (a.first>b.first);
33 }
34 bool static DTrackHitSelector_fdchit_cmp(pair<double,const DFDCPseudo *>a,
35  pair<double,const DFDCPseudo *>b){
36  if (a.second->wire->layer!=b.second->wire->layer)
37  return (a.second->wire->layer>b.second->wire->layer);
38  return (a.first>b.first);
39 }
40 
41 
42 //---------------------------------
43 // DTrackHitSelectorALT1 (Constructor)
44 //---------------------------------
46 {
47  HS_DEBUG_LEVEL = 0;
48  MAKE_DEBUG_TREES = false;
49 
50  gPARMS->SetDefaultParameter("TRKFIT:HS_DEBUG_LEVEL", HS_DEBUG_LEVEL, "Debug verbosity level for hit selector used in track fitting (0=no debug messages)");
51  gPARMS->SetDefaultParameter("TRKFIT:MAKE_DEBUG_TREES", MAKE_DEBUG_TREES, "Create a TTree with debugging info on hit selection for the FDC and CDC");
52 
53  cdchitsel = NULL;
54  fdchitsel = NULL;
55  if(MAKE_DEBUG_TREES){
56  loop->GetJApplication()->Lock();
57 
58  cdchitsel= (TTree*)gROOT->FindObject("cdchitsel");
59  if(!cdchitsel){
60  cdchitsel = new TTree("cdchitsel", "CDC Hit Selector");
61  cdchitsel->Branch("H", &cdchitdbg, "fit_type/I:p/F:theta:mass:sigma:mom_factor:x:y:z:s:s_factor:itheta02:itheta02s:itheta02s2:dist:doca:resi:sigma_total:chisq:prob");
62  }else{
63  _DBG__;
64  jerr<<" !!! WARNING !!!"<<endl;
65  jerr<<"It appears that the cdchitsel TTree is already defined."<<endl;
66  jerr<<"This is probably means you are running with multiple threads."<<endl;
67  jerr<<"To avoid complication, filling of the hit selector debug"<<endl;
68  jerr<<"trees will be disabled for this thread."<<endl;
69  _DBG__;
70  cdchitsel = NULL;
71  }
72 
73  fdchitsel= (TTree*)gROOT->FindObject("fdchitsel");
74  if(!fdchitsel){
75  fdchitsel = new TTree("fdchitsel", "FDC Hit Selector");
76  fdchitsel->Branch("H", &fdchitdbg, "fit_type/I:p/F:theta:mass:sigma_anode:sigma_cathode:mom_factor_anode:mom_factor_cathode:x:y:z:s:s_factor_anode:s_factor_cathode:itheta02:itheta02s:itheta02s2:dist:doca:resi:u:u_cathodes:resic:sigma_anode_total:sigma_cathode_total:chisq:prob:prob_anode:prob_cathode:pull_anode:pull_cathode");
77  }else{
78  _DBG__;
79  jerr<<" !!! WARNING !!!"<<endl;
80  jerr<<"It appears that the fdchitsel TTree is already defined."<<endl;
81  jerr<<"This is probably means you are running with multiple threads."<<endl;
82  jerr<<"To avoid complication, filling of the hit selector debug"<<endl;
83  jerr<<"trees will be disabled for this thread."<<endl;
84  _DBG__;
85  fdchitsel = NULL;
86  }
87 
88  loop->GetJApplication()->Unlock();
89  }
90 }
91 
92 //---------------------------------
93 // ~DTrackHitSelectorALT1 (Destructor)
94 //---------------------------------
96 {
97 
98 }
99 
100 //---------------------------------
101 // GetCDCHits
102 //---------------------------------
103 void DTrackHitSelectorALT1::GetCDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector<const DCDCTrackHit*> &cdchits_in, vector<const DCDCTrackHit*> &cdchits_out,int N) const
104 {
105  // Vector of pairs storing the hit with the probability it is on the track
106  vector<pair<double,const DCDCTrackHit*> >cdchits_tmp;
107 
108  /// Determine the probability that for each CDC hit that it came from the
109  /// track with the given trajectory.
110  ///
111  /// This will calculate a probability for each CDC hit that
112  /// it came from the track represented by the given
113  /// DReference trajectory. The probability is based on
114  /// the residual between the distance of closest approach
115  /// of the trajectory to the wire and the drift time for
116  /// time-based tracks and the distance to the wire for
117  /// wire-based tracks.
118 
119  // Calculate beta of particle.
120  double p = rt->swim_steps[0].mom.Mag();
121  double my_mass=rt->GetMass();
122  double one_over_beta =sqrt(1.0+my_mass*my_mass/(p*p));
123 
124  // The error on the residual. This will be different based on the
125  // quality of the track and whether MULS is on or not etc.
126  // In principle, this could also depend on the momentum parameters
127  // of the track.
128  double sigma;
129  switch(fit_type){
130  case kTimeBased:
131  sigma = 0.8*ONE_OVER_SQRT12;
132  break;
133  case kWireBased:
134  sigma = 1.6*ONE_OVER_SQRT12;
135  break;
136  case kHelical:
137  default:
138  sigma = 8.0*ONE_OVER_SQRT12;
139  }
140 
141  // Low-momentum tracks are more poorly defined than high-momentum tracks.
142  // We account for that here by increasing the error as a function of momentum
143  double g = 0.350/sqrt(log(2.0)); // total guess
144  double p_over_g=p/g;
145  //sigma *= 1.0 + exp(-pow(rt->swim_steps[0].mom.Mag()/g,2.0));
146  double mom_factor = 1.0+exp(-p_over_g*p_over_g);
147  sigma *= mom_factor;
148 
149  int old_straw=1000,old_ring=1000;
150 
151  // Minimum probability of hit belonging to wire and still be accepted
152  double MIN_HIT_PROB = 0.05;
153  vector<const DCDCTrackHit*>::const_iterator iter;
154  for(iter=cdchits_in.begin(); iter!=cdchits_in.end(); iter++){
155  const DCDCTrackHit *hit = *iter;
156 
157  // Skip hit if it is on the same wire as the previous hit
158  if (fit_type!=kTimeBased){
159  if (hit->wire->ring == old_ring && hit->wire->straw==old_straw) continue;
160  old_ring=hit->wire->ring;
161  old_straw=hit->wire->straw;
162  }
163  // Find the DOCA to this wire
164  double s;
165  double doca = rt->DistToRT(hit->wire, &s);
166  if(!isfinite(doca))
167  continue;
168 
169  // Get "measured" distance to wire. For time-based tracks
170  // this is calculated from the drift time. For all other
171  // tracks, this is assumed to be half a cell size
172  double dist;
173  if(fit_type == kTimeBased){
174  // Distance using drift time
175  // NOTE: Right now we assume pions for the TOF
176  // and a constant drift velocity of 55um/ns
177  double tof = s*one_over_beta/29.98;
178  dist = (hit->tdrift - tof)*55E-4;
179  }else{
180  dist = 0.4; // =0.8/2.0; half cell-size
181  }
182 
183  // For time-based and wire-based tracks, the fit was
184  // weighted for multiple scattering by material times
185  // angle giving preference to the begining of the
186  // track. Take this into account here by enhancing the
187  // error for hits further from the vertex
188  double sigma_total = sigma;
189  double s_factor = 1.0;
190  if(fit_type == kTimeBased || fit_type == kWireBased){
191  s_factor = 1.0 + s/50.0; // double error at 50cm out (guess for now)
192  sigma_total *= s_factor;
193  }
194 
195  // Residual
196  double resi = dist - doca;
197  //double chisq = pow(resi/sigma_total, 2.0);
198  double chisq=resi*resi/(sigma_total*sigma_total);
199 
200  // Use chi-sq probability function with Ndof=1 to calculate probability
201  double probability = TMath::Prob(chisq, 1);
202  if(probability>=MIN_HIT_PROB){
203  pair<double,const DCDCTrackHit*>myhit;
204  myhit.first=probability;
205  myhit.second=hit;
206  cdchits_tmp.push_back(myhit);
207  }
208 
209  // Optionally fill debug tree
210  if(cdchitsel){
211  DVector3 pos = rt->GetLastDOCAPoint();
212  const DReferenceTrajectory::swim_step_t *last_step = rt->GetLastSwimStep();
213 
214  cdchitdbg.fit_type = fit_type;
215  cdchitdbg.p = p;
216  cdchitdbg.theta = rt->swim_steps[0].mom.Theta();
217  cdchitdbg.mass = my_mass;
219  cdchitdbg.mom_factor = mom_factor;
220  cdchitdbg.x = pos.X();
221  cdchitdbg.y = pos.Y();
222  cdchitdbg.z = pos.Z();
223  cdchitdbg.s = s;
224  cdchitdbg.s_factor = s_factor;
225  cdchitdbg.itheta02 = last_step->itheta02;
226  cdchitdbg.itheta02s = last_step->itheta02s;
227  cdchitdbg.itheta02s2 = last_step->itheta02s2;
228  cdchitdbg.dist = dist;
229  cdchitdbg.doca = doca;
230  cdchitdbg.resi = resi;
231  cdchitdbg.sigma_total = sigma_total;
232  cdchitdbg.chisq = chisq;
233  cdchitdbg.prob = probability;
234 
235  cdchitsel->Fill();
236 
237  static bool printed_first = false;
238  if(!printed_first){
239  _DBG_<<"=== Printing first entry for CDC hit selector debug tree ==="<<endl;
240  _DBG_<<" fit_type = "<<cdchitdbg.fit_type<<endl;
241  _DBG_<<" p = "<<cdchitdbg.p<<endl;
242  _DBG_<<" theta = "<<cdchitdbg.theta<<endl;
243  _DBG_<<" mass = "<<cdchitdbg.mass<<endl;
244  _DBG_<<" sigma = "<<cdchitdbg.sigma<<endl;
245  _DBG_<<" mom_factor = "<<cdchitdbg.mom_factor<<endl;
246  _DBG_<<" x = "<<cdchitdbg.x<<endl;
247  _DBG_<<" y = "<<cdchitdbg.y<<endl;
248  _DBG_<<" z = "<<cdchitdbg.z<<endl;
249  _DBG_<<" s = "<<cdchitdbg.s<<endl;
250  _DBG_<<" s_factor = "<<cdchitdbg.s_factor<<endl;
251  _DBG_<<" itheta02 = "<<cdchitdbg.itheta02<<endl;
252  _DBG_<<" itheta02s = "<<cdchitdbg.itheta02s<<endl;
253  _DBG_<<" itheta02s2 = "<<cdchitdbg.itheta02s2<<endl;
254  _DBG_<<" dist = "<<cdchitdbg.dist<<endl;
255  _DBG_<<" doca = "<<cdchitdbg.doca<<endl;
256  _DBG_<<" resi = "<<cdchitdbg.resi<<endl;
257  _DBG_<<"sigma_total = "<<cdchitdbg.sigma_total<<endl;
258  _DBG_<<" chisq = "<<cdchitdbg.chisq<<endl;
259  _DBG_<<" prob = "<<cdchitdbg.prob<<endl;
260 
261  printed_first = true;
262  }
263  }
264 
265  if(HS_DEBUG_LEVEL>10){
266  _DBG_;
267  if(probability>=MIN_HIT_PROB)jerr<<ansi_bold<<ansi_green;
268  jerr<<"s="<<s<<" doca="<<doca<<" dist="<<dist<<" resi="<<resi<<" sigma="<<sigma_total<<" prob="<<probability<<endl;
269  jerr<<ansi_normal;
270  }
271  }
272 
273  // Order according to ring number and probability, then put the hits in the
274  // output list with the following algorithm: hits with the highest
275  // probability in a given ring are automatically put in the output list,
276  // but if there is more than one hit in a given ring, only those hits
277  // that are within +/-1 of the straw # of the most probable hit are added
278  // to the list.
279  sort(cdchits_tmp.begin(),cdchits_tmp.end(),DTrackHitSelector_cdchit_cmp);
280  old_straw=1000,old_ring=1000;
281  for (unsigned int i=0;i<cdchits_tmp.size();i++){
282  if (cdchits_tmp[i].second->wire->ring!=old_ring ||
283  abs(cdchits_tmp[i].second->wire->straw-old_straw)==1){
284  cdchits_out.push_back(cdchits_tmp[i].second);
285  }
286  old_straw=cdchits_tmp[i].second->wire->straw;
287  old_ring=cdchits_tmp[i].second->wire->ring;
288  }
289 }
290 
291 //---------------------------------
292 // GetFDCHits
293 //---------------------------------
294 void DTrackHitSelectorALT1::GetFDCHits(fit_type_t fit_type, const DReferenceTrajectory *rt, const vector<const DFDCPseudo*> &fdchits_in, vector<const DFDCPseudo*> &fdchits_out,int N) const
295 {
296  // Vector of pairs storing the hit with the probability it is on the track
297  vector<pair<double,const DFDCPseudo*> >fdchits_tmp;
298 
299  /// Determine the probability that for each FDC hit that it came from the
300  /// track with the given trajectory.
301  ///
302  /// This will calculate a probability for each FDC hit that
303  /// it came from the track represented by the given
304  /// DReference trajectory. The probability is based on
305  /// the residual between the distance of closest approach
306  /// of the trajectory to the wire and the drift time
307  /// and the distance along the wire.
308 
309  // Calculate beta of particle assuming its a pion for now. If the
310  // particles is really a proton or an electron, the residual
311  // calculated below will only be off by a little.
312  double my_mass=rt->GetMass();
313  double p = rt->swim_steps[0].mom.Mag();
314  //double one_over_beta =sqrt(1.0+my_mass*my_mass/(p*p));
315 
316  // Scale the errors up by 1/p for p<1GeV/c. This accounts for the poorer knowledge
317  // of the track parameters contained in the candidate for low momentum tracks
318  double mom_factor = 1.0;
319  if(p<1.0)mom_factor = 1.0/p;
320 
321  // Higher mass particles (protons) lose energy quicker and therefore have even
322  // less helical shapes for candidates and larger errors due to eloss straggling.
323  // These next 2 lines are here mainly to improve the situation for protons so
324  // we take a stab at scaling up the errors by the number of pion masses since
325  // this worked reasonably well for pions before.
326  double mass_factor=my_mass/0.13957;
327  if (my_mass<0.13957) mass_factor=1.;
328 
329  // Minimum probability of hit belonging to wire and still be accepted
330  double MIN_HIT_PROB = 0.01;
331 
332  vector<const DFDCPseudo*>::const_iterator iter;
333  for(iter=fdchits_in.begin(); iter!=fdchits_in.end(); iter++){
334  const DFDCPseudo *hit = *iter;
335 
336  // Find the DOCA to this wire
337  double s;
338  DVector3 fdc_pos(hit->xy.X(),hit->xy.Y(),hit->wire->origin.z());
339  double doca=rt->DistToRT(fdc_pos,&s);
340  if(!isfinite(doca))
341  continue;
342  double fdc_var=mom_factor*mom_factor*mass_factor*mass_factor*(1.0*1.0+0.3*0.3)/12.;
343 
344  if (fit_type==kHelical) fdc_var*=25.;
345  double chisq=doca*doca/fdc_var;
346  double MAX_HIT_DOCA = 30;
347  double probability = (doca<MAX_HIT_DOCA)?TMath::Prob(chisq, 1):0.;
348  if(probability>=MIN_HIT_PROB){
349  pair<double,const DFDCPseudo*>myhit;
350  myhit.first=probability;
351  myhit.second=hit;
352  fdchits_tmp.push_back(myhit);
353  }
354 
355  // Optionally fill debug tree
356  /*
357  if(fdchitsel){
358  DVector3 pos = rt->GetLastDOCAPoint();
359  const DReferenceTrajectory::swim_step_t *last_step = rt->GetLastSwimStep();
360 
361 
362  fdchitdbg.fit_type = fit_type;
363  fdchitdbg.p = p;
364  fdchitdbg.theta = rt->swim_steps[0].mom.Theta();
365  fdchitdbg.mass = my_mass;
366  fdchitdbg.sigma_anode = sigma_anode;
367  fdchitdbg.sigma_cathode = sigma_cathode;
368  fdchitdbg.mom_factor_anode = mom_factor;
369  fdchitdbg.mom_factor_cathode = mom_factor;
370  fdchitdbg.x = pos.X();
371  fdchitdbg.y = pos.Y();
372  fdchitdbg.z = pos.Z();
373  fdchitdbg.s = s;
374  fdchitdbg.s_factor_anode = 1.0;
375  fdchitdbg.s_factor_cathode = 1.0;
376  fdchitdbg.itheta02 = last_step->itheta02;
377  fdchitdbg.itheta02s = last_step->itheta02s;
378  fdchitdbg.itheta02s2 = last_step->itheta02s2;
379  fdchitdbg.dist = dist;
380  fdchitdbg.doca = doca;
381  fdchitdbg.resi = resi;
382  fdchitdbg.u = u;
383  fdchitdbg.u_cathodes = u_cathodes;
384  fdchitdbg.resic = resic;
385  fdchitdbg.sigma_anode_total = sigma_anode_total;
386  fdchitdbg.sigma_cathode_total = sigma_cathode_total;
387  fdchitdbg.chisq = chisq;
388  fdchitdbg.prob = probability;
389  fdchitdbg.prob_anode = TMath::Prob(pull_anode*pull_anode, 1);
390  fdchitdbg.prob_cathode = TMath::Prob(pull_cathode*pull_cathode, 1);
391  fdchitdbg.pull_anode = pull_anode;
392  fdchitdbg.pull_cathode = pull_cathode;
393 //_DBG_<<"fdchitdbg.pull_anode="<<fdchitdbg.pull_anode<<" pull_anode="<<pull_anode<<" resi/sigma_anode_total="<<resi/sigma_anode_total<<endl;
394 
395  fdchitsel->Fill();
396  }
397  */
398 
399  if(HS_DEBUG_LEVEL>10){
400  _DBG_;
401  if(probability>=MIN_HIT_PROB)jerr<<ansi_bold<<ansi_blue;
402  jerr<<"s="<<s<<" doca="<<doca<<" chisq="<<chisq<<" prob="<<probability<<endl;
403  jerr<<ansi_normal;
404  }
405  }
406  // Order according to layer number and probability,then put the hits in the
407  // output list with the following algorithm: hits with the highest
408  // probability in a given layer are automatically put in the output list,
409  // but if there is more than one hit in a given layer, only those hits
410  // that are within +/-1 of the wire # of the most probable hit are added
411  // to the list.
412  sort(fdchits_tmp.begin(),fdchits_tmp.end(),DTrackHitSelector_fdchit_cmp);
413  int old_layer=1000,old_wire=1000;
414  for (unsigned int i=0;i<fdchits_tmp.size();i++){
415  if (fdchits_tmp[i].second->wire->layer!=old_layer ||
416  abs(fdchits_tmp[i].second->wire->wire-old_wire)==1){
417  fdchits_out.push_back(fdchits_tmp[i].second);
418  }
419  old_wire=fdchits_tmp[i].second->wire->wire;
420  old_layer=fdchits_tmp[i].second->wire->layer;
421  }
422 }
DVector2 xy
rough x,y coordinates in lab coordinate system
Definition: DFDCPseudo.h:100
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
const swim_step_t * GetLastSwimStep(void) const
TVector3 DVector3
Definition: DVector3.h:14
DVector3 GetLastDOCAPoint(void) const
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
DTrackHitSelectorALT1(jana::JEventLoop *loop)
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
The DTrackHitSelector class is a base class for algorithms that will select hits from the drift chamb...
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
static bool DTrackHitSelector_fdchit_cmp(pair< double, const DFDCPseudo * >a, pair< double, const DFDCPseudo * >b)
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
double DistToRT(double x, double y, double z) const
int straw
Definition: DCDCWire.h:81
#define _DBG_
Definition: HDEVIO.h:12
#define ONE_OVER_SQRT12
Double_t sigma[NCHANNELS]
Definition: st_tw_resols.C:37
double GetMass(void) const
static bool DTrackHitSelector_cdchit_cmp(pair< double, const DCDCTrackHit * >a, pair< double, const DCDCTrackHit * >b)
#define ansi_blue
#define _DBG__
Definition: HDEVIO.h:13
double sqrt(double)
#define ansi_normal
int ring
Definition: DCDCWire.h:80
#define ansi_bold
#define ansi_green