Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DParticleID.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DParticleID.cc
4 // Created: Mon Feb 28 14:48:56 EST 2011
5 // Creator: staylor (on Linux ifarml1 2.6.18-128.el5 x86_64)
6 //
7 
8 #include "DParticleID.h"
10 
11 #ifndef M_TWO_PI
12 #define M_TWO_PI 6.28318530717958647692
13 #endif
14 
15 // Routines for sorting dEdx data
17  return a.dEdx < b.dEdx;
18 }
20  return a.dEdx_amp < b.dEdx_amp;
21 }
22 
23 // Routine for sorting hypotheses accorpding to FOM
25  const DTrackTimeBased *b){
26  return (a->FOM>b->FOM);
27 }
28 
29 
30 //---------------------------------
31 // DParticleID (Constructor)
32 //---------------------------------
33 DParticleID::DParticleID(JEventLoop *loop)
34 {
35  dSCdphi=12.0*M_PI/180.; // 12 degrees
36 
37  C_EFFECTIVE = 15.0;
38  ATTEN_LENGTH = 150.0;
39  OUT_OF_TIME_CUT = 35.0; // Changed 200 -> 35 ns, March 2016
40  gPARMS->SetDefaultParameter("PID:OUT_OF_TIME_CUT",OUT_OF_TIME_CUT);
41  CDC_TIME_CUT_FOR_DEDX = 1000.0;
42  gPARMS->SetDefaultParameter("PID:CDC_TIME_CUT_FOR_DEDX",CDC_TIME_CUT_FOR_DEDX);
43 
44 
45  DApplication* dapp = dynamic_cast<DApplication*>(loop->GetJApplication());
46  if(!dapp){
47  _DBG_<<"Cannot get DApplication from JEventLoop! (are you using a JApplication based program?)"<<endl;
48  return;
49  }
50 
51  const DRootGeom *RootGeom = dapp->GetRootGeom(loop->GetJEvent().GetRunNumber());
52  // Get material properties for chamber gas
53  double rho_Z_over_A_LnI=0,radlen=0;
54  RootGeom->FindMat("CDchamberGas", dRhoZoverA_CDC, rho_Z_over_A_LnI, radlen);
55  dLnI_CDC = rho_Z_over_A_LnI/dRhoZoverA_CDC;
56  dKRhoZoverA_CDC = 0.1535E-3*dRhoZoverA_CDC;
57 
58  RootGeom->FindMat("FDchamberGas", dRhoZoverA_FDC, rho_Z_over_A_LnI, radlen);
59  dLnI_FDC = rho_Z_over_A_LnI/dRhoZoverA_FDC;
60  dKRhoZoverA_FDC = 0.1535E-3*dRhoZoverA_FDC;
61 
62  RootGeom->FindMat("Scintillator", dRhoZoverA_Scint, rho_Z_over_A_LnI, radlen);
63  dLnI_Scint = rho_Z_over_A_LnI/dRhoZoverA_Scint;
65 
66  // Get the geometry
67  DGeometry* locGeometry = dapp->GetDGeometry(loop->GetJEvent().GetRunNumber());
68 
69  // Get z position of face of FCAL
70  locGeometry->GetFCALZ(dFCALz);
71 
72  // Get start counter geometry;
73  uint MAX_SC_SECTORS = 0; // keep track of the number of sectors
74  if (locGeometry->GetStartCounterGeom(sc_pos, sc_norm))
75  {
76  dSCphi0=sc_pos[0][0].Phi();
77  //sc_leg_tcor = -sc_pos[0][0].z()/C_EFFECTIVE;
78  double theta = sc_norm[0][sc_norm[0].size() - 2].Theta();
79  sc_angle_cor = 1./cos(M_PI_2 - theta);
80 
81  // Create vector of direction vectors in scintillator planes
82  for (int i=0;i<30;i++)
83  {
84  vector<DVector3> temp;
85  for (unsigned int j = 0; j < sc_pos[i].size() - 1; ++j)
86  {
87  double dx = sc_pos[i][j + 1].x() - sc_pos[i][j].x();
88  double dy = sc_pos[i][j + 1].y() - sc_pos[i][j].y();
89  double dz = sc_pos[i][j + 1].z() - sc_pos[i][j].z();
90  temp.push_back(DVector3(dx/dz,dy/dz,1.));
91  }
92  sc_dir.push_back(temp);
93  }
94  START_EXIST = true; // Found Start Counter
95  MAX_SC_SECTORS = sc_pos.size();
96  }
97  else {
98  START_EXIST = false; // no Start Counter found
99  }
100 
101 
102  //IF YOU CHANGE THESE, PLEASE (!!) UPDATE THE CUT LINES DRAWN FOR THE MONITORING IN:
103  // src/plugins/Analysis/monitoring_hists/HistMacro_Matching_*.C
104 
105  FCAL_CUT_PAR1=2.75;
106  gPARMS->SetDefaultParameter("FCAL:CUT_PAR1",FCAL_CUT_PAR1);
107 
108  FCAL_CUT_PAR2=0.5;
109  gPARMS->SetDefaultParameter("FCAL:CUT_PAR2",FCAL_CUT_PAR2);
110 
111  FCAL_CUT_PAR3=0.002;
112  gPARMS->SetDefaultParameter("FCAL:CUT_PAR3",FCAL_CUT_PAR3);
113 
114  TOF_CUT_PAR1 = 1.1;
115  gPARMS->SetDefaultParameter("TOF:CUT_PAR1",TOF_CUT_PAR1);
116 
117  TOF_CUT_PAR2 = 1.5;
118  gPARMS->SetDefaultParameter("TOF:CUT_PAR2",TOF_CUT_PAR2);
119 
120  TOF_CUT_PAR3 = 6.15;
121  gPARMS->SetDefaultParameter("TOF:CUT_PAR3",TOF_CUT_PAR3);
122 
123  TOF_CUT_PAR4 = 0.005;
124  gPARMS->SetDefaultParameter("TOF:CUT_PAR4",TOF_CUT_PAR4);
125 
126  BCAL_Z_CUT = 30.0;
127  gPARMS->SetDefaultParameter("BCAL:Z_CUT",BCAL_Z_CUT);
128 
129  BCAL_PHI_CUT_PAR1 = 3.0;
130  gPARMS->SetDefaultParameter("BCAL:PHI_CUT_PAR1",BCAL_PHI_CUT_PAR1);
131 
132  BCAL_PHI_CUT_PAR2 = 24.0;
133  gPARMS->SetDefaultParameter("BCAL:PHI_CUT_PAR2",BCAL_PHI_CUT_PAR2);
134 
135  BCAL_PHI_CUT_PAR3 = 0.8;
136  gPARMS->SetDefaultParameter("BCAL:PHI_CUT_PAR3",BCAL_PHI_CUT_PAR3);
137 
138  double locSCCutPar = 8.0;
139  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR1",locSCCutPar);
140  dSCCutPars_TimeBased.push_back(locSCCutPar);
141 
142  locSCCutPar = 0.5;
143  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR2",locSCCutPar);
144  dSCCutPars_TimeBased.push_back(locSCCutPar);
145 
146  locSCCutPar = 0.1;
147  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR3",locSCCutPar);
148  dSCCutPars_TimeBased.push_back(locSCCutPar);
149 
150  locSCCutPar = 60.0;
151  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR4",locSCCutPar);
152  dSCCutPars_TimeBased.push_back(locSCCutPar);
153 
154  locSCCutPar = 10.0;
155  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR1_WB",locSCCutPar);
156  dSCCutPars_WireBased.push_back(locSCCutPar);
157 
158  locSCCutPar = 0.5;
159  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR2_WB",locSCCutPar);
160  dSCCutPars_WireBased.push_back(locSCCutPar);
161 
162  locSCCutPar = 0.1;
163  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR3_WB",locSCCutPar);
164  dSCCutPars_WireBased.push_back(locSCCutPar);
165 
166  locSCCutPar = 60.0;
167  gPARMS->SetDefaultParameter("SC:SC_CUT_PAR4_WB",locSCCutPar);
168  dSCCutPars_WireBased.push_back(locSCCutPar);
169 
170  dTargetZCenter = 0.0;
171  locGeometry->GetTargetZ(dTargetZCenter);
172 
173 
174  // Track finder helper class
175  vector<const DTrackFinder *> finders;
176  loop->Get(finders);
177 
178  if(finders.size()<1){
179  _DBG_<<"Unable to get a DTrackFinder object!"<<endl;
180  return;
181  }
182 
183  finder = finders[0];
184 
185  // Track fitterer helper class
186  vector<const DTrackFitter *> fitters;
187  loop->Get(fitters);
188 
189  if(fitters.size()<1){
190  _DBG_<<"Unable to get a DTrackFinder object!"<<endl;
191  return;
192  }
193 
194  fitter = fitters[0];
195 
196  // CDC correction for gain drop from progressive gas deterioration in spring 2018
197  if(loop->GetCalib("CDC/gain_doca_correction", CDC_GAIN_DOCA_PARS))
198  jout << "Error loading CDC/gain_doca_correction !" << endl;
199 
200 
201  // FCAL geometry
202  loop->GetSingle(dFCALGeometry);
203 
204  //TOF calibration constants & geometry
205  if(loop->GetCalib("TOF/propagation_speed", propagation_speed))
206  jout << "Error loading /TOF/propagation_speed !" << endl;
207 
208  map<string, double> tofparms;
209  loop->GetCalib("TOF/tof_parms", tofparms);
210  TOF_ATTEN_LENGTH = tofparms["TOF_ATTEN_LENGTH"];
211  TOF_E_THRESHOLD = tofparms["TOF_E_THRESHOLD"];
212  //TOF_HALFPADDLE = tofparms["TOF_HALFPADDLE"]; // REPLACE? NOT USED?
213 
214  loop->GetSingle(dTOFGeometry);
216  double locBeamHoleWidth = dTOFGeometry->Get_LongBarLength() - 2.0*dTOFGeometry->Get_ShortBarLength(); // calc this in geometry?
217  ONESIDED_PADDLE_MIDPOINT_MAG = dHalfPaddle_OneSided + locBeamHoleWidth/2.0;
218 
219  // Start counter calibration constants
220  // vector<map<string,double> > tvals;
221  vector< vector<double> > pt_vals;
222  vector<map<string,double> > attn_vals;
223 
224  // if(loop->GetCalib("/START_COUNTER/propagation_speed",tvals))
225  // jout << "Error loading /START_COUNTER/propagation_speed !" << endl;
226  // else{
227  // for(unsigned int i=0; i<tvals.size(); i++){
228  // map<string, double> &row = tvals[i];
229  // sc_veff[SC_STRAIGHT].push_back(row["SC_STRAIGHT_PROPAGATION_B"]);
230  // sc_veff[SC_BEND].push_back(row["SC_BEND_PROPAGATION_B"]);
231  // sc_veff[SC_NOSE].push_back(row["SC_NOSE_PROPAGATION_B"]);
232  // }
233  // }
234 
235  // Individual propagation speed calibrations (beam data)
236  if(loop->GetCalib("/START_COUNTER/propagation_time_corr", pt_vals))
237  jout << "Error loading /START_COUNTER/propagation_time_corr !" << endl;
238  else
239  {
240  for(unsigned int i = 0; i < pt_vals.size(); i++)
241  {
242  // Functional form is: A + B*x
243  //map<string, double> &row = pt_vals[i];
244  sc_pt_yint[SC_STRAIGHT].push_back(pt_vals[i][0]);
245  sc_pt_yint[SC_BEND].push_back(pt_vals[i][2]);
246  sc_pt_yint[SC_NOSE].push_back(pt_vals[i][4]);
247 
248  sc_pt_slope[SC_STRAIGHT].push_back(pt_vals[i][1]);
249  sc_pt_slope[SC_BEND].push_back(pt_vals[i][3]);
250  sc_pt_slope[SC_NOSE].push_back(pt_vals[i][5]);
251  }
252  }
253 
254  // Individual attenuation calibrations (FIU bench mark data)
255  if(loop->GetCalib("START_COUNTER/attenuation_factor", attn_vals))
256  jout << "Error in loading START_COUNTER/attenuation_factor !" << endl;
257  else
258  {
259  for(unsigned int i = 0; i < attn_vals.size(); i++)
260  {
261  // Functional form is: A*exp(B*x) + C
262  map<string, double> &row = attn_vals[i];
263  sc_attn_A[SC_STRAIGHT_ATTN].push_back(row["SC_STRAIGHT_ATTENUATION_A"]);
264  sc_attn_A[SC_BENDNOSE_ATTN].push_back(row["SC_BENDNOSE_ATTENUATION_A"]);
265 
266  sc_attn_B[SC_STRAIGHT_ATTN].push_back(row["SC_STRAIGHT_ATTENUATION_B"]);
267  sc_attn_B[SC_BENDNOSE_ATTN].push_back(row["SC_BENDNOSE_ATTENUATION_B"]);
268 
269  sc_attn_C[SC_STRAIGHT_ATTN].push_back(row["SC_STRAIGHT_ATTENUATION_C"]);
270  sc_attn_C[SC_BENDNOSE_ATTN].push_back(row["SC_BENDNOSE_ATTENUATION_C"]);
271  }
272  }
273 
274  // Start counter individual paddle resolutions
275  vector< vector<double> > sc_paddle_resolution_params;
276  if(loop->GetCalib("START_COUNTER/TRvsPL", sc_paddle_resolution_params))
277  jout << "Error in loading START_COUNTER/TRvsPL !" << endl;
278  else {
279  if(sc_paddle_resolution_params.size() != MAX_SC_SECTORS)
280  jerr << "Start counter paddle resolutions table has wrong number of entries:" << endl
281  << " loaded = " << sc_paddle_resolution_params.size()
282  << " expected = " << MAX_SC_SECTORS << endl;
283 
284  for(int i=0; i<(int)MAX_SC_SECTORS; i++) {
285  SC_SECTION1_P0.push_back( sc_paddle_resolution_params[i][0] );
286  SC_SECTION1_P1.push_back( sc_paddle_resolution_params[i][1] );
287  SC_BOUNDARY1.push_back( sc_paddle_resolution_params[i][2] );
288  SC_SECTION2_P0.push_back( sc_paddle_resolution_params[i][3] );
289  SC_SECTION2_P1.push_back( sc_paddle_resolution_params[i][4] );
290  SC_BOUNDARY2.push_back( sc_paddle_resolution_params[i][5] );
291  SC_SECTION3_P0.push_back( sc_paddle_resolution_params[i][6] );
292  SC_SECTION3_P1.push_back( sc_paddle_resolution_params[i][7] );
293  SC_BOUNDARY3.push_back( sc_paddle_resolution_params[i][8] );
294  SC_SECTION4_P0.push_back( sc_paddle_resolution_params[i][9] );
295  SC_SECTION4_P1.push_back( sc_paddle_resolution_params[i][10] );
296  }
297  }
298 
299  //be sure that DRFTime_factory::init() and brun() are called
300  vector<const DTOFPoint*> locTOFPoints;
301  loop->Get(locTOFPoints);
302 
303  dTOFPointFactory = static_cast<DTOFPoint_factory*>(loop->GetFactory("DTOFPoint"));
304 
305  // Initialize DIRC LUT
306  loop->GetSingle(dDIRCLut);
307 }
308 
309 // Group fitted tracks according to candidate id
310 jerror_t DParticleID::GroupTracks(vector<const DTrackTimeBased *> &tracks,
311  vector<vector<const DTrackTimeBased*> >&grouped_tracks) const{
312  if (tracks.size()==0) return RESOURCE_UNAVAILABLE;
313 
314  JObject::oid_t old_id=tracks[0]->candidateid;
315  vector<const DTrackTimeBased *>hypotheses;
316  for (unsigned int i=0;i<tracks.size();i++){
317  const DTrackTimeBased *track=tracks[i];
318 
319  if (old_id != track->candidateid){
320  // Sort according to FOM
321  sort(hypotheses.begin(),hypotheses.end(),DParticleID_hypothesis_cmp);
322 
323  // Add to the grouped_tracks vector
324  grouped_tracks.push_back(hypotheses);
325 
326  // Clear the hypothesis list for the next track
327  hypotheses.clear();
328  }
329  hypotheses.push_back(track);
330  old_id=track->candidateid;
331  }
332  // Final set
333  sort(hypotheses.begin(),hypotheses.end(),DParticleID_hypothesis_cmp);
334  grouped_tracks.push_back(hypotheses);
335 
336 
337  return NOERROR;
338 }
339 
340 // Compute the energy losses and the path lengths in the chambers for each hit
341 // on the track. Returns a list of dE and dx pairs with the momentum at the
342 // hit.
343 jerror_t DParticleID::GetDCdEdxHits(const DTrackTimeBased *track, vector<dedx_t>& dEdxHits_CDC,vector<dedx_t>& dEdxHits_FDC) const{
344 
345 
346  // Position and momentum
347  DVector3 pos,mom;
348  // flight time and t0 for the event
349  //double tflight=0.;
350  //double t0=track->t0();
351 
352  //dE and dx pairs
353  dedx_t de_and_dx(0.,0.,0.,0.);
354 
355  //Get the list of cdc hits used in the fit
356  vector<const DCDCTrackHit*>cdchits;
357  track->GetT(cdchits);
358 
359  // Loop over cdc hits
360  vector<DTrackFitter::Extrapolation_t>cdc_extrapolations=track->extrapolations.at(SYS_CDC);
361  if (cdc_extrapolations.size()>0){
362  for (unsigned int i=0;i<cdchits.size();i++){
363  if (cdchits[i]->dE <= 0.0) continue; // pedestal > signal
364 
365  double doca2_old=1e6;
366  for (unsigned int j=0;j<cdc_extrapolations.size();j++){
367  double z=cdc_extrapolations[j].position.z();
368  DVector3 wirepos=cdchits[i]->wire->origin
369  +((z-cdchits[i]->wire->origin.z())/cdchits[i]->wire->udir.z())
370  *cdchits[i]->wire->udir;
371  double doca2=(wirepos-cdc_extrapolations[j].position).Mag2();
372  if (doca2>doca2_old){
373  unsigned int index=j-1;
374  mom=cdc_extrapolations[index].momentum;
375  pos=cdc_extrapolations[index].position;
376  //tflight=cdc_extrapolations[index].t;
377  break;
378  }
379  doca2_old=doca2;
380  }
381 
382  // Cut late drift time hits where the energy deposition is degraded
383  double dt=cdchits[i]->tdrift; //-tflight-t0;
384  if (dt>CDC_TIME_CUT_FOR_DEDX) continue;
385 
386  // Create the dE,dx pair from the position and momentum using a helical approximation for the path
387  // in the straw and keep track of the momentum in the active region of the detector
388  if (CalcdEdxHit(mom,pos,cdchits[i],de_and_dx)==NOERROR){
389  dEdxHits_CDC.push_back(de_and_dx);
390  }
391  }
392  }
393 
394  //Get the list of fdc hits used in the fit
395  vector<const DFDCPseudo*>fdchits;
396  track->GetT(fdchits);
397 
398  // loop over fdc hits
399  vector<DTrackFitter::Extrapolation_t>fdc_extrapolations=track->extrapolations.at(SYS_FDC);
400  if (fdc_extrapolations.size()>0){
401  for (unsigned int i=0;i<fdchits.size();i++){
402  if (fdchits[i]->dE <= 0.0) continue; // pedestal > signal
403 
404  for (unsigned int j=0;j<fdc_extrapolations.size();j++){
405  double z=fdc_extrapolations[j].position.z();
406  if (fabs(z-fdchits[i]->wire->origin.z())<0.5){
407  mom=fdc_extrapolations[j].momentum;
408  double gas_thickness = 1.0; // cm
409  dEdxHits_FDC.push_back(dedx_t(fdchits[i]->dE,fdchits[i]->dE_amp,
410  gas_thickness/cos(mom.Theta()),
411  mom.Mag()));
412  break;
413  }
414  }
415  }
416  }
417 
418  // Sort the dEdx entries from smallest to largest
419  sort(dEdxHits_FDC.begin(),dEdxHits_FDC.end(),DParticleID_dedx_cmp);
420  sort(dEdxHits_CDC.begin(),dEdxHits_CDC.end(),DParticleID_dedx_cmp);
421 
422  return NOERROR;
423 }
424 
425 jerror_t DParticleID::CalcDCdEdx(const DTrackTimeBased *locTrackTimeBased, double& locdEdx_FDC, double& locdx_FDC, double& locdEdx_CDC, double& locdEdx_CDC_amp,double& locdx_CDC, double& locdx_CDC_amp,unsigned int& locNumHitsUsedFordEdx_FDC, unsigned int& locNumHitsUsedFordEdx_CDC) const
426 {
427  vector<dedx_t> locdEdxHits_CDC, locdEdxHits_CDC_amp,locdEdxHits_FDC;
428  jerror_t locReturnStatus = GetDCdEdxHits(locTrackTimeBased, locdEdxHits_CDC, locdEdxHits_FDC);
429  if(locReturnStatus != NOERROR)
430  {
431  locdEdx_FDC = numeric_limits<double>::quiet_NaN();
432  locdx_FDC = numeric_limits<double>::quiet_NaN();
433  locNumHitsUsedFordEdx_FDC = 0;
434  locdEdx_CDC = numeric_limits<double>::quiet_NaN();
435  locdEdx_CDC_amp = numeric_limits<double>::quiet_NaN();
436  locdx_CDC = numeric_limits<double>::quiet_NaN();
437  locdx_CDC_amp = numeric_limits<double>::quiet_NaN();
438  locNumHitsUsedFordEdx_CDC = 0;
439  return locReturnStatus;
440  }
441  return CalcDCdEdx(locTrackTimeBased, locdEdxHits_CDC,locdEdxHits_FDC,
442  locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp,
443  locdx_CDC, locdx_CDC_amp,locNumHitsUsedFordEdx_FDC,
444  locNumHitsUsedFordEdx_CDC);
445 }
446 
447 jerror_t DParticleID::CalcDCdEdx(const DTrackTimeBased *locTrackTimeBased, const vector<dedx_t>& locdEdxHits_CDC, const vector<dedx_t>& locdEdxHits_FDC, double& locdEdx_FDC, double& locdx_FDC, double& locdEdx_CDC, double &locdEdx_CDC_amp,double& locdx_CDC, double& locdx_CDC_amp,unsigned int& locNumHitsUsedFordEdx_FDC, unsigned int& locNumHitsUsedFordEdx_CDC) const
448 {
449  locdx_CDC = 0.0;
450  locdx_CDC_amp = 0.0;
451  locdEdx_CDC = 0.0;
452  locdEdx_CDC_amp = 0.0;
453  locNumHitsUsedFordEdx_CDC = locdEdxHits_CDC.size()*4/5;
454  if(locNumHitsUsedFordEdx_CDC > 0)
455  {
456  for(unsigned int loc_i = 0; loc_i < locNumHitsUsedFordEdx_CDC; ++loc_i)
457  {
458  locdEdx_CDC += locdEdxHits_CDC[loc_i].dE; //weight is ~ #e- (scattering sites): dx!
459  locdx_CDC += locdEdxHits_CDC[loc_i].dx;
460  }
461  locdEdx_CDC /= locdx_CDC;
462 
463  // Sort according to amplitude (the order of hits might be different
464  // compared to sorting by the integral).
465  vector<dedx_t>locdEdxHitsTemp(locdEdxHits_CDC);
466  sort(locdEdxHitsTemp.begin(),locdEdxHitsTemp.end(),
468  for(unsigned int loc_i = 0; loc_i < locNumHitsUsedFordEdx_CDC; ++loc_i)
469  {
470  locdEdx_CDC_amp+=locdEdxHitsTemp[loc_i].dE_amp;
471  locdx_CDC_amp += locdEdxHitsTemp[loc_i].dx;
472  }
473  locdEdx_CDC_amp/=locdx_CDC_amp;
474  }
475 
476  locdx_FDC = 0.0;
477  locdEdx_FDC = 0.0;
478  locNumHitsUsedFordEdx_FDC = locdEdxHits_FDC.size()*4/5;
479  if(locNumHitsUsedFordEdx_FDC > 0)
480  {
481  for(unsigned int loc_i = 0; loc_i < locNumHitsUsedFordEdx_FDC; ++loc_i)
482  {
483  locdEdx_FDC += locdEdxHits_FDC[loc_i].dE; //weight is ~ #e- (scattering sites): dx!
484  locdx_FDC += locdEdxHits_FDC[loc_i].dx;
485  }
486  locdEdx_FDC /= locdx_FDC; //weight is dx/dx_total
487  }
488 
489  return NOERROR;
490 }
491 
492 // Calculate the path length for a single hit in a straw and return ds and the
493 // energy deposition in the straw. It returns dE as the first element in the
494 // dedx pair and ds as the second element in the dedx pair.
495 jerror_t DParticleID::CalcdEdxHit(const DVector3 &mom,
496  const DVector3 &pos,
497  const DCDCTrackHit *hit,
498  dedx_t &dedx) const{
499  if (hit==NULL || hit->wire==NULL) return RESOURCE_UNAVAILABLE;
500 
501  double dx=CalcdXHit(mom,pos,hit->wire);
502 
503  if ((dx>0.) && (hit->dist >0.)){ // cannot cope w -ve doca
504 
505  // arc length and energy deposition
506 
507  // CDC/gain_doca_correction contains CDC_GAIN_DOCA_PARS
508  // dmax dcorr goodp0 goodp1 thisp0 thisp1
509  // 0: dmax ignore hits outside this doca
510  // 1: dcorr do not correct hits within this doca
511  // 2: goodp0 par0 for good reference run
512  // 3: goodp1 par1 for good reference run
513  // 4: thisp0 par0 for this run
514  // 5: thisp1 par1 for this run
515 
516 
517  if (hit->dist < CDC_GAIN_DOCA_PARS[0]) {
518 
519  dedx.dx=dx;
520  dedx.dE=hit->dE; //GeV
521  dedx.dE_amp=hit->dE_amp;
522  dedx.p=mom.Mag();
523 
524  if (hit->dist > CDC_GAIN_DOCA_PARS[1]) {
525  double reference = CDC_GAIN_DOCA_PARS[2] + hit->dist*CDC_GAIN_DOCA_PARS[3];
526  double this_run = CDC_GAIN_DOCA_PARS[4] + hit->dist*CDC_GAIN_DOCA_PARS[5];
527  dedx.dE_amp = dedx.dE_amp * reference/this_run;
528  }
529 
530 
531  // integral correction
532 
533  double dmax = CDC_GAIN_DOCA_PARS[0];
534  double dmin = CDC_GAIN_DOCA_PARS[1];
535 
536  double reference;
537  double this_run;
538 
539  if (hit->dist < dmin) {
540 
541  reference = (CDC_GAIN_DOCA_PARS[2] + CDC_GAIN_DOCA_PARS[3]*dmin) * (dmin - hit->dist);
542  reference += (CDC_GAIN_DOCA_PARS[2] + 0.5*CDC_GAIN_DOCA_PARS[3]*(dmin+dmax)) * (dmax - dmin);
543 
544  this_run = (CDC_GAIN_DOCA_PARS[4] + CDC_GAIN_DOCA_PARS[5]*dmin) * (dmin - hit->dist);
545  this_run += (CDC_GAIN_DOCA_PARS[4] + 0.5*CDC_GAIN_DOCA_PARS[5]*(dmin+dmax)) * (dmax - dmin);
546 
547  } else {
548 
549  reference = (CDC_GAIN_DOCA_PARS[2] + 0.5*CDC_GAIN_DOCA_PARS[3]*(hit->dist+dmax)) * (dmax - hit->dist);
550  this_run = (CDC_GAIN_DOCA_PARS[4] + 0.5*CDC_GAIN_DOCA_PARS[5]*(hit->dist+dmax)) * (dmax - hit->dist);
551 
552  }
553 
554  dedx.dE = dedx.dE * reference/this_run;
555 
556  dedx.dEdx=dedx.dE/dx;
557  dedx.dEdx_amp=dedx.dE_amp/dx;
558 
559  return NOERROR;
560  }
561  }
562 
563  return VALUE_OUT_OF_RANGE;
564 }
565 
566 
567 // Calculate the path length for a single hit in a straw.
569  const DVector3 &pos,
570  const DCoordinateSystem *wire) const{
571  if (wire==NULL) return -1.; // should not get here
572 
573  // Track direction parameters
574  double phi=mom.Phi();
575  double lambda=M_PI_2-mom.Theta();
576  double cosphi=cos(phi);
577  double sinphi=sin(phi);
578  double tanl=tan(lambda);
579 
580  //Position relative to wire origin
581  double dz=pos.z()-wire->origin.z();
582  double dx=pos.x()-wire->origin.x();
583  double dy=pos.y()-wire->origin.y();
584 
585  // square of straw radius
586  double rs2=0.776*0.776;
587 
588  // Useful temporary variables related to the direction of the wire
589  double ux=wire->udir.x();
590  double uy=wire->udir.y();
591  double uz=wire->udir.z();
592  double A=1.-ux*ux;
593  double B=-2.*ux*uy;
594  double C=-2.*ux*uz;
595  double D=-2.*uy*uz;
596  double E=1.-uy*uy;
597  double F=1.-uz*uz;
598 
599  // The path length in the straw is given by s=sqrt(b*b-4*a*c)/a/cosl.
600  // a, b, and c follow.
601  double a=A*cosphi*cosphi+B*cosphi*sinphi+C*cosphi*tanl+D*sinphi*tanl
602  +E*sinphi*sinphi+F*tanl*tanl;
603  double b=2.*A*dx*cosphi+B*dx*sinphi+B*dy*cosphi+C*dx*tanl+C*cosphi*dz
604  +D*dy*tanl+D*sinphi*dz+2.*E*dy*sinphi+2.*F*dz*tanl;
605  double c=A*dx*dx+B*dx*dy+C*dx*dz+D*dy*dz+E*dy*dy+F*dz*dz-rs2;
606 
607  // Check for valid arc length and compute dEdx
608  double temp=b*b-4.*a*c;
609  if (temp>0){
610  double cosl=fabs(cos(lambda));
611  // double gas_density=0.0018;
612 
613  // arc length and energy deposition
614  //dedx.second=gas_density*sqrt(temp)/a/cosl; // g/cm^2
615  return sqrt(temp)/a/cosl;
616  }
617 
618  return -1.; // should not get here
619 }
620 
621 
622 void DParticleID::GetScintMPdEandSigma(double p,double M,double x,
623  double &most_probable_dE,
624  double &sigma_dE) const{
625  double one_over_beta_sq=1.+M*M/(p*p);
626  double betagamma=p/M;
627  double Xi=dKRhoZoverA_Scint*one_over_beta_sq*x;
628  double Me=0.000511;
629 
630  // Density effect
631  double X=log10(betagamma);
632  double X0,X1;
633  double Cbar=2.*(dLnI_Scint-log(28.816e-9*sqrt(dRhoZoverA_Scint)))+1.;
634  if (dLnI_Scint<-1.6118){ // I<100
635  if (Cbar<=3.681) X0=0.2;
636  else X0=0.326*Cbar-1.;
637  X1=2.;
638  }
639  else{
640  if (Cbar<=5.215) X0=0.2;
641  else X0=0.326*Cbar-1.5;
642  X1=3.;
643  }
644  double delta=0;
645  if (X>=X0 && X<X1)
646  delta=4.606*X-Cbar+(Cbar-4.606*X0)*pow((X1-X)/(X1-X0),3.);
647  else if (X>=X1)
648  delta= 4.606*X-Cbar;
649 
650  most_probable_dE=Xi*(log(Xi)-2.*dLnI_Scint-1./one_over_beta_sq
651  -log((one_over_beta_sq-1)/(2.*Me))+0.2-delta);
652  sigma_dE=4.*Xi/2.354;
653 }
654 
655 // Calculate the most probable energy loss per unit length in units of
656 // GeV/cm in the FDC or CDC gas for a particle of momentum p and mass "mass"
657 double DParticleID::GetMostProbabledEdx_DC(double p,double mass,double dx, bool locIsCDCFlag) const{
658  double betagamma=p/mass;
659  double beta2=1./(1.+1./betagamma/betagamma);
660  if (beta2<1e-6) beta2=1e-6;
661 
662  // Electron mass
663  double Me=0.000511; //GeV
664 
665  double locKRhoZoverAGas = locIsCDCFlag ? dKRhoZoverA_CDC : dKRhoZoverA_FDC;
666  double locLnIGas = locIsCDCFlag ? dLnI_CDC : dLnI_FDC;
667 
668  // First (non-logarithmic) term in Bethe-Bloch formula
669  double mean_dedx=locKRhoZoverAGas/beta2;
670 
671  // Most probable energy loss from Landau theory (see Leo, pp. 51-52)
672  return mean_dedx*(log(mean_dedx*dx)
673  -log((1.-beta2)/2./Me/beta2)-2.*locLnIGas-beta2+0.200);
674 }
675 
676 // Empirical form for sigma/mean for gaseous detectors with num_dedx
677 // samples and sampling thickness path_length. Assumes that the number of
678 // hits has already been converted from an (unsigned) int to a double.
679 double DParticleID::GetdEdxSigma_DC(double num_hits,double p,double mass,
680  double mean_path_length, bool locIsCDCFlag) const{
681  // kinematic quantities
682  double betagamma=p/mass;
683  double betagamma2=betagamma*betagamma;
684  double beta2=1./(1.+1./betagamma2);
685  if (beta2<1e-6) beta2=1e-6;
686 
687  double Me=0.000511; //GeV
688  double m_ratio=Me/mass;
689  double two_Me_betagamma_sq=2.*Me*betagamma2;
690  double Tmax
691  =two_Me_betagamma_sq/(1.+2.*sqrt(1.+betagamma2)*m_ratio+m_ratio*m_ratio);
692  // Energy truncation for knock-on electrons
693  double T0=(Tmax>100.e-6)?100.e-6:Tmax; //100.e-6: energy cut for bethe-bloch
694 
695  // Bethe-Bloch
696  double locKRhoZoverAGas = locIsCDCFlag ? dKRhoZoverA_CDC : dKRhoZoverA_FDC;
697  double locLnIGas = locIsCDCFlag ? dLnI_CDC : dLnI_FDC;
698  double mean_dedx=locKRhoZoverAGas/beta2
699  *(log(two_Me_betagamma_sq*T0)-2.*locLnIGas-beta2*(1.+T0/Tmax));
700 
701  return 0.41*mean_dedx*pow(num_hits,-0.43)*pow(mean_path_length,-0.32);
702  //return 0.41*mean_dedx*pow(double(num_hits),-0.5)*pow(mean_path_length,-0.32);
703 }
704 
705 /****************************************************** DISTANCE TO TRACK ******************************************************/
706 // routine to find the distance to a cluster within an FCAL shower that is
707 // closest to a projected track position
708 double DParticleID::Distance_ToTrack(const DFCALShower *locFCALShower,
709  const DVector3 &locProjPos) const{
710  const DVector3 fcal_pos=locFCALShower->getPosition();
711  // Find minimum distance between track projection and each of the hits
712  // associated with the shower.
713  double d2min=(fcal_pos - locProjPos).Mag();
714  double xproj=locProjPos.x();
715  double yproj=locProjPos.y();
716  vector<const DFCALCluster*>clusters;
717  locFCALShower->Get(clusters);
718 
719  for (unsigned int k=0;k<clusters.size();k++)
720  {
721  vector<DFCALCluster::DFCALClusterHit_t>hits=clusters[k]->GetHits();
722  for (unsigned int m=0;m<hits.size();m++)
723  {
724  double dx=hits[m].x-xproj;
725  double dy=hits[m].y-yproj;
726  double d2=dx*dx+dy*dy;
727  if (d2<d2min)
728  d2min=d2;
729  }
730  }
731  return sqrt(d2min);
732 }
733 
734 
735 // NOTE: For these functions, an initial guess for start time is expected as input so that out-of-time tracks can be skipped
736 
737 bool DParticleID::Distance_ToTrack(const DReferenceTrajectory* rt, const DFCALShower* locFCALShower, double locInputStartTime, shared_ptr<DFCALShowerMatchParams>& locShowerMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
738 {
739  if(rt == nullptr)
740  return false;
741 
742  // Find the distance of closest approach between the track trajectory
743  // and the cluster position, looking for the minimum
744  DVector3 fcal_pos = locFCALShower->getPosition();
745  DVector3 norm(0.0, 0.0, 1.0); //normal vector for the FCAL plane
746  double locPathLength = 9.9E9, locFlightTime = 9.9E9;
747  double locFlightTimeVariance=9.9E9;
748  DVector3 locProjPos, locProjMom;
749  if(rt->GetIntersectionWithPlane(fcal_pos, norm, locProjPos, locProjMom, &locPathLength, &locFlightTime, &locFlightTimeVariance,SYS_FCAL) != NOERROR)
750  return false;
751 
752  // Check that the hit is not out of time with respect to the track
753  double locDeltaT = locFCALShower->getTime() - locFlightTime - locInputStartTime;
754  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
755  return false;
756 
757  // Find minimum distance between track projection and each of the hits
758  // associated with the shower.
759  double d2min=(fcal_pos - locProjPos).Mag();
760  double xproj=locProjPos.x();
761  double yproj=locProjPos.y();
762  vector<const DFCALCluster*>clusters;
763  locFCALShower->Get(clusters);
764 
765  for (unsigned int k=0;k<clusters.size();k++)
766  {
767  vector<DFCALCluster::DFCALClusterHit_t>hits=clusters[k]->GetHits();
768  for (unsigned int m=0;m<hits.size();m++)
769  {
770  double dx=hits[m].x-xproj;
771  double dy=hits[m].y-yproj;
772  double d2=dx*dx+dy*dy;
773  if (d2<d2min)
774  d2min=d2;
775  }
776  }
777 
778  if(locOutputProjMom != nullptr)
779  {
780  *locOutputProjPos = locProjPos;
781  *locOutputProjMom = locProjMom;
782  }
783 
784  double d = sqrt(d2min);
785  double p=locProjMom.Mag();
786 
787  //SET MATCHING INFORMATION
788  if(locShowerMatchParams == nullptr)
789  locShowerMatchParams = std::make_shared<DFCALShowerMatchParams>();
790  locShowerMatchParams->dFCALShower = locFCALShower;
791  locShowerMatchParams->dx = 45.0*p/(locProjMom.Dot(norm));
792  locShowerMatchParams->dFlightTime = locFlightTime;
793  locShowerMatchParams->dFlightTimeVariance = locFlightTimeVariance;
794  locShowerMatchParams->dPathLength = locPathLength;
795  locShowerMatchParams->dDOCAToShower = d;
796 
797  return true;
798 }
799 
800 bool DParticleID::Distance_ToTrack(const DReferenceTrajectory* rt, const DBCALShower* locBCALShower, double locInputStartTime, shared_ptr<DBCALShowerMatchParams>& locShowerMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
801 {
802  if(rt == nullptr)
803  return false;
804 
805  // Get the BCAL cluster position and normal
806  DVector3 bcal_pos(locBCALShower->x, locBCALShower->y, locBCALShower->z);
807 
808  double locFlightTime = 9.9E9, locPathLength = 9.9E9, locFlightTimeVariance = 9.9E9;
809  double locDistance = rt->DistToRTwithTime(bcal_pos, &locPathLength, &locFlightTime,&locFlightTimeVariance,SYS_BCAL);
810  if(!isfinite(locDistance))
811  return false;
812 
813  // Check that the hit is not out of time with respect to the track
814  double locDeltaT = locBCALShower->t - locFlightTime - locInputStartTime;
815  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
816  return false;
817 
818  DVector3 locProjPos = rt->GetLastDOCAPoint();
819  DVector3 locProjMom = rt->swim_steps[0].mom;
820  if(locOutputProjMom != nullptr)
821  {
822  *locOutputProjPos = locProjPos;
823  *locOutputProjMom = locProjMom;
824  }
825 
826  double locDeltaZ = bcal_pos.z() - locProjPos.z();
827  double locDeltaPhiMin = bcal_pos.Phi() - locProjPos.Phi();
828  while(locDeltaPhiMin > M_PI)
829  locDeltaPhiMin -= M_TWO_PI;
830  while(locDeltaPhiMin < -M_PI)
831  locDeltaPhiMin += M_TWO_PI;
832 
833  // Find intersection of track with inner radius of BCAL to get dx
834  DVector3 proj_pos_surface;
835  double locDx = 0.0;
836  if (rt->GetIntersectionWithRadius(65.0, proj_pos_surface) == NOERROR) //HARD-CODED RADIUS!!!
837  locDx = (locProjPos - proj_pos_surface).Mag();
838 
839  // The next part of the code tries to take into account curvature
840  // of shower cluster distribution
841 
842  // Get clusters associated with this shower
843  vector<const DBCALCluster*>clusters;
844  locBCALShower->Get(clusters);
845 
846  // make list of points associated with the shower
847  vector<const DBCALPoint*> points;
848  if(!clusters.empty())
849  {
850  // classic BCAL shower objects are built from the output of the clusterizer
851  // so the points need to be accessed as shower -> cluster -> points
852  for (unsigned int k=0;k<clusters.size();k++)
853  {
854  vector<const DBCALPoint*> cluster_points=clusters[k]->points();
855  points.insert(points.end(), cluster_points.begin(), cluster_points.end());
856  }
857  }
858  else
859  {
860  // other BCAL shower objects directly keep a list of the points associated with the shower
861  // (e.g. "CURVATURE" showers)
862  locBCALShower->Get(points);
863  }
864 
865  // loop over points associated with this shower, finding
866  // the closest match between a point and the track
867  for (unsigned int m=0;m<points.size();m++)
868  {
869  double rpoint=points[m]->r();
870  double s, t;
871  DVector3 locPointProjPos, locPointProjMom;
872  if (rt->GetIntersectionWithRadius(rpoint, locPointProjPos, &s, &t, &locPointProjMom) != NOERROR)
873  continue;
874 
875  double mydphi=points[m]->phi()-locPointProjPos.Phi();
876  while(mydphi > M_PI)
877  mydphi -= M_TWO_PI;
878  while(mydphi < -M_PI)
879  mydphi += M_TWO_PI;
880  if(fabs(mydphi) >= fabs(locDeltaPhiMin))
881  continue;
882 
883  locDeltaPhiMin=mydphi;
884  if(locOutputProjMom != nullptr)
885  {
886  *locOutputProjPos = locPointProjPos;
887  *locOutputProjMom = locPointProjMom;
888  }
889  }
890 
891  //SET MATCHING INFORMATION
892  if(locShowerMatchParams == nullptr)
893  locShowerMatchParams = std::make_shared<DBCALShowerMatchParams>();
894  locShowerMatchParams->dBCALShower = locBCALShower;
895  locShowerMatchParams->dx = locDx;
896  locShowerMatchParams->dFlightTime = locFlightTime;
897  locShowerMatchParams->dFlightTimeVariance = locFlightTimeVariance;
898  locShowerMatchParams->dPathLength = locPathLength;
899  locShowerMatchParams->dDeltaPhiToShower = locDeltaPhiMin;
900  locShowerMatchParams->dDeltaZToShower = locDeltaZ;
901 
902  return true;
903 }
904 
905 bool DParticleID::Distance_ToTrack(const DReferenceTrajectory* rt, const DTOFPoint* locTOFPoint, double locInputStartTime, shared_ptr<DTOFHitMatchParams>& locTOFHitMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
906 {
907  if(rt == nullptr)
908  return false;
909 
910  // Find the distance of closest approach between the track trajectory
911  // and the tof cluster position, looking for the minimum
912  DVector3 tof_pos = locTOFPoint->pos;
913  DVector3 norm(0.0, 0.0, 1.0); //normal vector to TOF plane
914  DVector3 locProjPos, locProjMom;
915  double locPathLength = 9.9E9, locFlightTime = 9.9E9;
916  double locFlightTimeVariance=9.9E9;
917  if(rt->GetIntersectionWithPlane(tof_pos, norm, locProjPos, locProjMom, &locPathLength, &locFlightTime,&locFlightTimeVariance,SYS_TOF) != NOERROR)
918  return false;
919 
920  //If position was not well-defined, correct deposited energy due to attenuation, and time due to propagation along paddle
921  //These values were reported at the midpoint of the paddle
922  float locHitEnergy = locTOFPoint->dE;
923  double locHitTime = locTOFPoint->t;
924  double locHitTimeVariance = locTOFPoint->tErr*locTOFPoint->tErr;
925  if(!locTOFPoint->Is_XPositionWellDefined())
926  {
927  //Is unmatched horizontal paddle with only one hit above threshold
928  bool locNorthIsGoodHit = (locTOFPoint->dHorizontalBarStatus == 1); //+x
929  int locBar = locTOFPoint->dHorizontalBar;
930  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
931 
932  //Paddle midpoint
933  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
934  if(!locIsDoubleEndedBar)
935  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
936 
937  //delta_x = delta_x_actual - delta_x_mid
938  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
939  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
940  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.X() : locProjPos.X() - locPaddleMidPoint;
941 
942  //Energy
943  locHitEnergy *= exp(locDistanceToMidPoint/TOF_ATTEN_LENGTH);
944 
945  //Time
946  int id = 44 + locBar - 1;
947  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
948  //locHitTimeVariance = //UPDATE ME!!!
949  }
950  else if(!locTOFPoint->Is_YPositionWellDefined())
951  {
952  //Is unmatched vertical paddle with only one hit above threshold
953  bool locNorthIsGoodHit = (locTOFPoint->dVerticalBarStatus == 1); //+y
954  int locBar = locTOFPoint->dVerticalBar;
955  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
956 
957  //Paddle midpoint
958  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
959  if(!locIsDoubleEndedBar)
960  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
961 
962  //delta_x = delta_x_actual - delta_x_mid
963  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
964  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
965  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.Y() : locProjPos.Y() - locPaddleMidPoint;
966 
967  //Energy
968  locHitEnergy *= exp(locDistanceToMidPoint/TOF_ATTEN_LENGTH);
969 
970  //Time
971  int id = locBar - 1;
972  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
973  //locHitTimeVariance = //UPDATE ME!!!
974  }
975 
976  // Check that the hit is not out of time with respect to the track
977  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
978  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
979  return false;
980 
981  if(locOutputProjMom != nullptr)
982  {
983  *locOutputProjPos = locProjPos;
984  *locOutputProjMom = locProjMom;
985  }
986 
987  double locDeltaX = locTOFPoint->Is_XPositionWellDefined() ? tof_pos.X() - locProjPos.X() : 999.0;
988  double locDeltaY = locTOFPoint->Is_YPositionWellDefined() ? tof_pos.Y() - locProjPos.Y() : 999.0;
989 
990  //SET MATCHING INFORMATION
991  if(locTOFHitMatchParams == nullptr)
992  locTOFHitMatchParams = std::make_shared<DTOFHitMatchParams>();
993  double dx = 2.54*locProjMom.Mag()/locProjMom.Dot(norm);
994  locTOFHitMatchParams->dTOFPoint = locTOFPoint;
995 
996  locTOFHitMatchParams->dHitTime = locHitTime;
997  locTOFHitMatchParams->dHitTimeVariance = locHitTimeVariance;
998  locTOFHitMatchParams->dHitEnergy = locHitEnergy;
999 
1000  locTOFHitMatchParams->dEdx = locHitEnergy/dx;
1001  locTOFHitMatchParams->dFlightTime = locFlightTime;
1002  locTOFHitMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1003  locTOFHitMatchParams->dPathLength = locPathLength;
1004  locTOFHitMatchParams->dDeltaXToHit = locDeltaX;
1005  locTOFHitMatchParams->dDeltaYToHit = locDeltaY;
1006 
1007  return true;
1008 }
1009 
1010 bool DParticleID::Distance_ToTrack(const DReferenceTrajectory* rt, const DSCHit* locSCHit, double locInputStartTime, shared_ptr<DSCHitMatchParams>& locSCHitMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
1011 {
1012  if(rt == nullptr)
1013  return false;
1014  if (! START_EXIST)
1015  return false; // if no Start Counter in geometry
1016 
1017 
1018  //The track may be projected to hit a different paddle than the one it actually hit!!!!
1019  //First, we need to find where the track is projected to intersect the start counter geometry
1020  DVector3 locProjPos, locProjMom, locPaddleNorm;
1021  double locDeltaPhi, locPathLength, locFlightTime, locFlightTimeVariance;
1022  int locSCPlane;
1023  unsigned int locBestSCSector = PredictSCSector(rt, locDeltaPhi, locProjPos, locProjMom, locPaddleNorm, locPathLength, locFlightTime, locFlightTimeVariance, locSCPlane);
1024  if(locBestSCSector == 0)
1025  return false;
1026 
1027  //Now, the input SC hit may have been on a separate SC paddle than the projection
1028  //So, we have to assume that the locProjPos.Z() for the projected paddle is accurate enough for the hit paddle (no other way to get it).
1029  //In fact, we assume that everything from the above is accurate except for locDeltaPhi (we'll recalculate it at the end)
1030 
1031  // Check that the hit is not out of time with respect to the track
1032  if(fabs(locSCHit->t - locFlightTime - locInputStartTime) > OUT_OF_TIME_CUT)
1033  return false;
1034 
1035  // Start Counter geometry in hall coordinates, obtained from xml file
1036  unsigned int sc_index = locSCHit->sector - 1;
1037  double sc_pos_soss = sc_pos[sc_index][0].z(); // Start of straight section
1038  double sc_pos_eoss = sc_pos[sc_index][1].z(); // End of straight section
1039  double sc_pos_eobs = sc_pos[sc_index][sc_pos[sc_index].size() - 2].z(); // End of bend section
1040 
1041  // Grab the time-walk corrected start counter hit time, and the pulse integral
1042  double locCorrectedHitTime = locSCHit->t;
1043  double locCorrectedHitEnergy = locSCHit->dE;
1044 
1045  // Check to see if hit occured in the straight section
1046  double L = 0.;
1047  if (locProjPos.Z() <= sc_pos_eoss)
1048  {
1049  // Calculate hit distance along scintillator relative to upstream end
1050  L = locProjPos.Z() - sc_pos_soss;
1051  // Apply propagation time correction
1052  locCorrectedHitTime -= L*sc_pt_slope[SC_STRAIGHT][sc_index] + sc_pt_yint[SC_STRAIGHT][sc_index];
1053  // Apply attenuation correction
1054  locCorrectedHitEnergy *= 1.0/(exp(sc_attn_B[SC_STRAIGHT_ATTN][sc_index]*L));
1055  }
1056  else if(locProjPos.Z() > sc_pos_eoss && locProjPos.Z() <= sc_pos_eobs) //check if in bend section: if so, apply corrections
1057  {
1058  // Calculate the hit position relative to the upstream end
1059  L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
1060  // Apply propagation time correction
1061  locCorrectedHitTime -= L*sc_pt_slope[SC_BEND][sc_index] + sc_pt_yint[SC_BEND][sc_index];
1062  // Apply attenuation correction
1063  locCorrectedHitEnergy *= (sc_attn_A[SC_STRAIGHT_ATTN][sc_index] / ((sc_attn_A[SC_BENDNOSE_ATTN][sc_index]*
1064  exp(sc_attn_B[SC_BENDNOSE_ATTN][sc_index]*L)) + sc_attn_C[SC_BENDNOSE_ATTN][sc_index]));
1065  }
1066  else // nose section: apply corrections
1067  {
1068  // Calculate the hit position relative to the upstream end
1069  L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
1070  // Apply propagation time correction
1071  locCorrectedHitTime -= L*sc_pt_slope[SC_NOSE][sc_index] + sc_pt_yint[SC_NOSE][sc_index];
1072  // Apply attenuation correction
1073  locCorrectedHitEnergy *= (sc_attn_A[SC_STRAIGHT_ATTN][sc_index] / ((sc_attn_A[SC_BENDNOSE_ATTN][sc_index]*
1074  exp(sc_attn_B[SC_BENDNOSE_ATTN][sc_index]*L)) + sc_attn_C[SC_BENDNOSE_ATTN][sc_index]));
1075  }
1076 
1077  if(locOutputProjMom != nullptr)
1078  {
1079  *locOutputProjPos = locProjPos;
1080  *locOutputProjMom = locProjMom;
1081  }
1082 
1083  // Correct the locDeltaPhi in case the projected and input SC hit paddles are different
1084  DVector3 sc_pos_at_projz = sc_pos[sc_index][locSCPlane] + (locProjPos.Z() - sc_pos[sc_index][locSCPlane].z())*sc_dir[sc_index][locSCPlane];
1085  locDeltaPhi = sc_pos_at_projz.Phi() - locProjPos.Phi();
1086  while(locDeltaPhi > TMath::Pi())
1087  locDeltaPhi -= M_TWO_PI;
1088  while(locDeltaPhi < -1.0*TMath::Pi())
1089  locDeltaPhi += M_TWO_PI;
1090 
1091  // For the dEdx measurement we now need to take into account that L does not
1092  // compensate for the position in z at which the start counter paddle starts
1093  double ds = 0.3*locProjMom.Mag()/fabs(locProjMom.Dot(locPaddleNorm));
1094 
1095  // ============================
1096  // Figure out timing resolution
1097  // This is parameterized by
1098  double time_resolution = 0.;
1099  //double sc_local_z = locProjPos.Z() - sc_pos_soss; // resolutions are stored as a function of the z distance from the upstream end of the SC
1100 
1101  if(L < SC_BOUNDARY1[sc_index]) {
1102  time_resolution = SC_SECTION1_P0[sc_index] + SC_SECTION1_P1[sc_index]*L;
1103  } else if(L < SC_BOUNDARY2[sc_index]) {
1104  time_resolution = SC_SECTION2_P0[sc_index] + SC_SECTION2_P1[sc_index]*L;
1105  } else if(L < SC_BOUNDARY3[sc_index]) {
1106  time_resolution = SC_SECTION3_P0[sc_index] + SC_SECTION3_P1[sc_index]*L;
1107  } else {
1108  time_resolution = SC_SECTION4_P0[sc_index] + SC_SECTION4_P1[sc_index]*L;
1109  }
1110 
1111 
1112  //SET MATCHING INFORMATION
1113  if(locSCHitMatchParams == nullptr)
1114  locSCHitMatchParams = std::make_shared<DSCHitMatchParams>();
1115  locSCHitMatchParams->dSCHit = locSCHit;
1116  locSCHitMatchParams->dHitEnergy = locCorrectedHitEnergy;
1117  locSCHitMatchParams->dEdx = locSCHitMatchParams->dHitEnergy/ds;
1118  locSCHitMatchParams->dHitTime = locCorrectedHitTime;
1119  locSCHitMatchParams->dHitTimeVariance = time_resolution*time_resolution;
1120  locSCHitMatchParams->dFlightTime = locFlightTime;
1121  locSCHitMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1122  locSCHitMatchParams->dPathLength = locPathLength;
1123  locSCHitMatchParams->dDeltaPhiToHit = locDeltaPhi;
1124 
1125  return true;
1126 }
1127 
1128 bool DParticleID::ProjectTo_SC(const DReferenceTrajectory* rt, unsigned int locSCSector, double& locDeltaPhi, DVector3& locProjPos, DVector3& locProjMom, DVector3& locPaddleNorm, double& locPathLength, double& locFlightTime, double& locFlightTimeVariance, int& locSCPlane) const
1129 {
1130  if(rt == nullptr)
1131  return false;
1132  if (! START_EXIST)
1133  return false; // if no Start Counter in geometry
1134 
1135 
1136  // Find intersection with a "barrel" approximation for the start counter
1137  unsigned int sc_index = locSCSector - 1;
1138  locSCPlane = -1;
1139  if(rt->GetIntersectionWithPlane(sc_pos[sc_index][0], sc_norm[sc_index][0], locProjPos, locProjMom, &locPathLength, &locFlightTime, &locFlightTimeVariance) != NOERROR)
1140  return false;
1141 
1142  // Start Counter geometry in hall coordinates, obtained from xml file
1143  double sc_pos_soss = sc_pos[sc_index][0].z(); // Start of straight section
1144  double sc_pos_eoss = sc_pos[sc_index][1].z(); // End of straight section
1145  double sc_pos_eons = sc_pos[sc_index][sc_pos[sc_index].size() - 1].z(); // End of nose section
1146 
1147  // Check that the intersection isn't upstream of the paddle
1148  double locProjectionZTolerance = 5.0;
1149  if (locProjPos.Z() < sc_pos_soss + locProjectionZTolerance)
1150  return false;
1151  if (locProjPos.Z() < sc_pos_soss) //unphysical, adjust: due to track projection uncertainty (or it really did miss)
1152  locProjPos.SetZ(sc_pos_soss);
1153 
1154  // Check to see if hit occured in the straight section
1155  if (locProjPos.Z() <= sc_pos_eoss)
1156  locSCPlane = 0;
1157  else //bend or nose
1158  {
1159  //loop through SC planes
1160  //consider: 12 planes, labeled 1 -> 12
1161  //but, the vectors are size 13
1162  //sc_norm[sc_index][loc_i] are the normal vectors for plane loc_i //loc_i = 0 should be ignored
1163  //sc_pos[sc_index][loc_i] are the end points for plane loc_i //for loc_i = 0, is begin point
1164  for (unsigned int loc_i = 1; loc_i < sc_norm[sc_index].size(); ++loc_i)
1165  {
1166  if(rt->GetIntersectionWithPlane(sc_pos[sc_index][loc_i], sc_norm[sc_index][loc_i], locProjPos, locProjMom, &locPathLength, &locFlightTime, &locFlightTimeVariance) != NOERROR)
1167  continue;
1168 
1169  // If on final plane, check for intersection point well beyond nose
1170  if(loc_i == (sc_norm[sc_index].size() - 1))
1171  {
1172  if (locProjPos.Z() > (sc_pos_eons + locProjectionZTolerance))
1173  return false;
1174  }
1175  else if(locProjPos.Z() > sc_pos[sc_index][loc_i + 1].z())
1176  continue; //past the end of this plane, go to next plane
1177 
1178  locSCPlane = loc_i;
1179  break;
1180  }
1181 
1182  // Check to see if the projections changed their mind, and put the hit in the straight section after all
1183  if(locProjPos.Z() < sc_pos_eoss) // Assume hit just past the end of straight section
1184  {
1185  locProjPos.SetZ(sc_pos_eoss - 0.0001); //some tolerance
1186  locSCPlane = 0;
1187  }
1188  }
1189  if(locSCPlane == -1)
1190  return false; //should be impossible ...
1191 
1192  //normal to the plane
1193  locPaddleNorm = sc_norm[sc_index][locSCPlane];
1194 
1195  //Calculate delta-phi
1196  DVector3 sc_pos_at_projz = sc_pos[sc_index][locSCPlane] + (locProjPos.Z() - sc_pos[sc_index][locSCPlane].z())*sc_dir[sc_index][locSCPlane];
1197  locDeltaPhi = sc_pos_at_projz.Phi() - locProjPos.Phi();
1198  while(locDeltaPhi > TMath::Pi())
1199  locDeltaPhi -= M_TWO_PI;
1200  while(locDeltaPhi < -1.0*TMath::Pi())
1201  locDeltaPhi += M_TWO_PI;
1202 
1203  return true;
1204 }
1205 
1206 // The routines below use the extrapolations vector from the track
1207 
1208 bool DParticleID::Distance_ToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DFCALShower* locFCALShower, double locInputStartTime, shared_ptr<DFCALShowerMatchParams>& locShowerMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
1209 {
1210  if(extrapolations.size()==0)
1211  return false;
1212 
1213  // Check that the hit is not out of time with respect to the track
1214  double locFlightTime=extrapolations[0].t;
1215  double locPathLength=extrapolations[0].s;
1216  double locFlightTimeVariance=0.; // fill this in!
1217  double locDeltaT = locFCALShower->getTime() - locFlightTime - locInputStartTime;
1218  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
1219  return false;
1220 
1221  // Find the track projection to the FCAL
1222  DVector3 locProjPos=extrapolations[0].position;
1223  DVector3 locProjMom=extrapolations[0].momentum;
1224  double dz=locFCALShower->getPosition().z()-locProjPos.z();
1225  locProjPos+=dz*DVector3(locProjMom.x()/locProjMom.z(),
1226  locProjMom.y()/locProjMom.z(),1.);
1227  // Correct the flight path and flight time to this point
1228  double v=(extrapolations[1].s-extrapolations[0].s)/(extrapolations[1].t-extrapolations[0].t);
1229  double ds=dz/cos(locProjMom.Theta());
1230  double dt=ds/v;
1231  locFlightTime+=dt;
1232  locPathLength+=ds;
1233 
1234  if(locOutputProjMom != nullptr)
1235  {
1236  *locOutputProjPos = locProjPos;
1237  *locOutputProjMom = locProjMom;
1238  }
1239 
1240  double d = Distance_ToTrack(locFCALShower,locProjPos);
1241  double p=locProjMom.Mag();
1242  //SET MATCHING INFORMATION
1243  if(locShowerMatchParams == nullptr)
1244  locShowerMatchParams = std::make_shared<DFCALShowerMatchParams>();
1245  locShowerMatchParams->dFCALShower = locFCALShower;
1246  locShowerMatchParams->dx = 45.0*p/(locProjMom.Dot(DVector3(0.,0.,1.)));
1247  locShowerMatchParams->dFlightTime = locFlightTime;
1248  locShowerMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1249  locShowerMatchParams->dPathLength = locPathLength;
1250  locShowerMatchParams->dDOCAToShower = d;
1251 
1252  return true;
1253 }
1254 bool DParticleID::Distance_ToTrack(const vector<DTrackFitter::Extrapolation_t>&extrapolations, const DTOFPoint* locTOFPoint, double locInputStartTime,shared_ptr<DTOFHitMatchParams>& locTOFHitMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
1255 {
1256  if(extrapolations.size()==0)
1257  return false;
1258 
1259  // Find the track projection to the TOF
1260  DVector3 locProjPos=extrapolations[0].position;
1261  DVector3 locProjMom=extrapolations[0].momentum;
1262  double locFlightTime=extrapolations[0].t;
1263  double locPathLength=extrapolations[0].s;
1264  double locFlightTimeVariance=0.; // fill this in!
1265 
1266  //If position was not well-defined, correct time due to propagation along
1267  //paddle
1268  double locHitTime = Get_CorrectedHitTime(locTOFPoint,locProjPos);
1269  // Check that the hit is not out of time with respect to the track
1270  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
1271  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
1272  return false;
1273 
1274  //If position was not well-defined, correct deposited energy due to
1275  //attenuation
1276  float locHitEnergy = Get_CorrectedHitEnergy(locTOFPoint,locProjPos);
1277  double locHitTimeVariance = locTOFPoint->tErr*locTOFPoint->tErr;
1278 
1279  if(locOutputProjMom != nullptr)
1280  {
1281  *locOutputProjPos = locProjPos;
1282  *locOutputProjMom = locProjMom;
1283  }
1284  DVector3 tof_pos=locTOFPoint->pos;
1285  double locDeltaX = locTOFPoint->Is_XPositionWellDefined() ? tof_pos.X() - locProjPos.X() : 999.0;
1286  double locDeltaY = locTOFPoint->Is_YPositionWellDefined() ? tof_pos.Y() - locProjPos.Y() : 999.0;
1287 
1288  //SET MATCHING INFORMATION
1289  if(locTOFHitMatchParams == nullptr)
1290  locTOFHitMatchParams = std::make_shared<DTOFHitMatchParams>();
1291 
1292  double dx = 2.54*locProjMom.Mag()/locProjMom.Dot(DVector3(0.0,0.,1.));
1293  locTOFHitMatchParams->dTOFPoint = locTOFPoint;
1294 
1295  locTOFHitMatchParams->dHitTime = locHitTime;
1296  locTOFHitMatchParams->dHitTimeVariance = locHitTimeVariance;
1297  locTOFHitMatchParams->dHitEnergy = locHitEnergy;
1298 
1299  locTOFHitMatchParams->dEdx = locHitEnergy/dx;
1300  locTOFHitMatchParams->dFlightTime = locFlightTime;
1301  locTOFHitMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1302  locTOFHitMatchParams->dPathLength = locPathLength;
1303  locTOFHitMatchParams->dDeltaXToHit = locDeltaX;
1304  locTOFHitMatchParams->dDeltaYToHit = locDeltaY;
1305 
1306  return true;
1307 }
1308 
1309 bool DParticleID::Distance_ToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DSCHit* locSCHit, double locInputStartTime,shared_ptr<DSCHitMatchParams>& locSCHitMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
1310 {
1311  if(extrapolations.size()==0)
1312  return false;
1313 
1314  // Find the track projection to the Start Counter
1315  DVector3 locProjPos=extrapolations[0].position;
1316  DVector3 locProjMom=extrapolations[0].momentum;
1317  double locFlightTime=extrapolations[0].t;
1318  double locPathLength=extrapolations[0].s;
1319  double locFlightTimeVariance=0.; // fill this in!
1320 
1321  //Now, the input SC hit may have been on a separate SC paddle than the projection
1322  //So, we have to assume that the locProjPos.Z() for the projected paddle is accurate enough for the hit paddle (no other way to get it).
1323  //In fact, we assume that everything from the above is accurate except for locDeltaPhi (we'll recalculate it at the end)
1324 
1325  // Check that the hit is not out of time with respect to the track
1326  if(fabs(locSCHit->t - locFlightTime - locInputStartTime) > OUT_OF_TIME_CUT)
1327  return false;
1328 
1329  // Get corrected start counter time and energy deposition
1330  double locCorrectedHitEnergy=Get_CorrectedHitEnergy(locSCHit,locProjPos);
1331  double locCorrectedHitTime=Get_CorrectedHitTime(locSCHit,locProjPos);
1332 
1333  if(locOutputProjMom != nullptr)
1334  {
1335  *locOutputProjPos = locProjPos;
1336  *locOutputProjMom = locProjMom;
1337  }
1338 
1339  // Correct the locDeltaPhi in case the projected and input SC hit paddles are different
1340  unsigned int sc_index=locSCHit->sector-1;
1341  double z=locProjPos.z();
1342  unsigned int locSCPlane=0;
1343  if (z>sc_pos[sc_index][0].z()){
1344  for (unsigned int j=0;j<sc_pos[sc_index].size();j++){
1345  if (z>sc_pos[sc_index][j].z()) continue;
1346 
1347  locSCPlane=j-1;
1348  break;
1349  }
1350  }
1351 
1352  DVector3 sc_pos_at_projz = sc_pos[sc_index][locSCPlane] + (locProjPos.Z() - sc_pos[sc_index][locSCPlane].z())*sc_dir[sc_index][locSCPlane];
1353  double locDeltaPhi = sc_pos_at_projz.Phi() - locProjPos.Phi();
1354  while(locDeltaPhi > TMath::Pi())
1355  locDeltaPhi -= M_TWO_PI;
1356  while(locDeltaPhi < -1.0*TMath::Pi())
1357  locDeltaPhi += M_TWO_PI;
1358 
1359  // Compute the track distance through the scintillator
1360  DVector3 locPaddleNorm=sc_norm[sc_index][locSCPlane];
1361  double ds = 0.3*locProjMom.Mag()/fabs(locProjMom.Dot(locPaddleNorm));
1362 
1363  // Start Counter geometry in hall coordinates, obtained from xml file
1364  double sc_pos_soss = sc_pos[sc_index][0].z(); // Start of straight section
1365  double sc_pos_eoss = sc_pos[sc_index][1].z(); // End of straight section
1366  double sc_pos_eobs = sc_pos[sc_index][sc_pos[sc_index].size() - 2].z(); // End of bend section
1367 
1368  // Check to see if hit occured in the straight section
1369  double L = 0.;
1370  if (locProjPos.Z() <= sc_pos_eoss) // Calculate hit distance along scintillator relative to upstream end
1371  L = locProjPos.Z() - sc_pos_soss;
1372  else if(locProjPos.Z() > sc_pos_eoss && locProjPos.Z() <= sc_pos_eobs) //check if in bend section: if so, apply corrections
1373  L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
1374  else // nose section: apply corrections
1375  L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
1376 
1377  // ============================
1378  // Figure out timing resolution
1379  // This is parameterized by
1380  double time_resolution = 0.;
1381  //double sc_local_z = locProjPos.Z() - sc_pos_soss; // resolutions are stored as a function of the z distance from the upstream end of the SC
1382 
1383  if(L < SC_BOUNDARY1[sc_index]) {
1384  time_resolution = SC_SECTION1_P0[sc_index] + SC_SECTION1_P1[sc_index]*L;
1385  } else if(L < SC_BOUNDARY2[sc_index]) {
1386  time_resolution = SC_SECTION2_P0[sc_index] + SC_SECTION2_P1[sc_index]*L;
1387  } else if(L < SC_BOUNDARY3[sc_index]) {
1388  time_resolution = SC_SECTION3_P0[sc_index] + SC_SECTION3_P1[sc_index]*L;
1389  } else {
1390  time_resolution = SC_SECTION4_P0[sc_index] + SC_SECTION4_P1[sc_index]*L;
1391  }
1392 
1393 
1394  //SET MATCHING INFORMATION
1395  if(locSCHitMatchParams == nullptr)
1396  locSCHitMatchParams = std::make_shared<DSCHitMatchParams>();
1397  locSCHitMatchParams->dSCHit = locSCHit;
1398  locSCHitMatchParams->dHitEnergy = locCorrectedHitEnergy;
1399  locSCHitMatchParams->dEdx = locSCHitMatchParams->dHitEnergy/ds;
1400  locSCHitMatchParams->dHitTime = locCorrectedHitTime;
1401  locSCHitMatchParams->dHitTimeVariance = time_resolution*time_resolution;
1402  locSCHitMatchParams->dFlightTime = locFlightTime;
1403  locSCHitMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1404  locSCHitMatchParams->dPathLength = locPathLength;
1405  locSCHitMatchParams->dDeltaPhiToHit = locDeltaPhi;
1406 
1407  return true;
1408 }
1409 
1410 
1411 
1412 bool DParticleID::Distance_ToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DBCALShower* locBCALShower, double locInputStartTime,shared_ptr<DBCALShowerMatchParams>& locShowerMatchParams, DVector3* locOutputProjPos, DVector3* locOutputProjMom) const
1413 {
1414  if(extrapolations.size()<2)
1415  return false;
1416 
1417  // Check that the hit is not out of time with respect to the track. Use
1418  // extrapolation point at entrance to BCAL for a rough guess for flight time
1419  double locDeltaT = locBCALShower->t - extrapolations[0].t - locInputStartTime;
1420  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
1421  return false;
1422 
1423  // Get the BCAL cluster position
1424  DVector3 bcal_pos(locBCALShower->x, locBCALShower->y, locBCALShower->z);
1425 
1426  // track quantities: initialize to the point at which the track enters the
1427  // BCAL; will refine below.
1428  double locFlightTime = extrapolations[0].t;
1429  double locPathLength = extrapolations[0].s, locFlightTimeVariance = 9.9E9;
1430  DVector3 locProjPos=extrapolations[0].position;
1431  DVector3 locProjMom=extrapolations[0].momentum;
1432 
1433  // Find the closest extrapolated position to this BCAL shower
1434  double doca_old=1e6;
1435  for (unsigned int i=1;i<extrapolations.size();i++){
1436  double doca=(extrapolations[i].position-bcal_pos).Mag();
1437  if (doca>doca_old){
1438  unsigned int index=i-1;
1439  locProjPos=extrapolations[index].position;
1440  locProjMom=extrapolations[index].momentum;
1441  locPathLength=extrapolations[index].s;
1442  locFlightTime=extrapolations[index].t;
1443 
1444  break;
1445  }
1446  doca_old=doca;
1447  }
1448 
1449  if(locOutputProjMom != nullptr)
1450  {
1451  *locOutputProjPos = locProjPos;
1452  *locOutputProjMom = locProjMom;
1453  }
1454 
1455  // Difference in z
1456  double locDeltaZ = bcal_pos.z() - locProjPos.z();
1457  // Difference in phi (will try to refine with points below
1458  double locDeltaPhiMin=bcal_pos.Phi()-locProjPos.Phi();
1459  while(locDeltaPhiMin > M_PI)
1460  locDeltaPhiMin -= M_TWO_PI;
1461  while(locDeltaPhiMin < -M_PI)
1462  locDeltaPhiMin += M_TWO_PI;
1463 
1464  // Find intersection of track with inner radius of BCAL to get dx
1465  double locDx = (locProjPos - extrapolations[0].position).Mag();
1466 
1467  // The next part of the code tries to take into account curvature
1468  // of shower cluster distribution
1469 
1470  // Get clusters associated with this shower
1471  vector<const DBCALCluster*>clusters;
1472  locBCALShower->Get(clusters);
1473 
1474  // make list of points associated with the shower
1475  vector<const DBCALPoint*> points;
1476  if(!clusters.empty())
1477  {
1478  // classic BCAL shower objects are built from the output of the clusterizer
1479  // so the points need to be accessed as shower -> cluster -> points
1480  for (unsigned int k=0;k<clusters.size();k++)
1481  {
1482  vector<const DBCALPoint*> cluster_points=clusters[k]->points();
1483  points.insert(points.end(), cluster_points.begin(), cluster_points.end());
1484  }
1485  }
1486  else
1487  {
1488  // other BCAL shower objects directly keep a list of the points associated with the shower
1489  // (e.g. "CURVATURE" showers)
1490  locBCALShower->Get(points);
1491  }
1492 
1493  // loop over points associated with this shower, finding
1494  // the closest match between a point and the track
1495  for (unsigned int m=0;m<points.size();m++){
1496  DVector3 locPointProjPos=extrapolations[0].position;
1497  double R=points[m]->r();
1498  if (fitter->ExtrapolateToRadius(R,extrapolations,locPointProjPos)==false)
1499  continue;
1500 
1501  double mydphi=points[m]->phi()-locPointProjPos.Phi();
1502  while(mydphi > M_PI)
1503  mydphi -= M_TWO_PI;
1504  while(mydphi < -M_PI)
1505  mydphi += M_TWO_PI;
1506  if(fabs(mydphi) >= fabs(locDeltaPhiMin))
1507  continue;
1508 
1509  locDeltaPhiMin=mydphi;
1510  }
1511 
1512  //SET MATCHING INFORMATION
1513  if(locShowerMatchParams == nullptr)
1514  locShowerMatchParams = std::make_shared<DBCALShowerMatchParams>();
1515  locShowerMatchParams->dBCALShower = locBCALShower;
1516  locShowerMatchParams->dx = locDx;
1517  locShowerMatchParams->dFlightTime = locFlightTime;
1518  locShowerMatchParams->dFlightTimeVariance = locFlightTimeVariance;
1519  locShowerMatchParams->dPathLength = locPathLength;
1520  locShowerMatchParams->dDeltaPhiToShower = locDeltaPhiMin;
1521  // locShowerMatchParams->dDeltaPhiToShowerCut=BCAL_PHI_CUT_PAR1
1522  // + BCAL_PHI_CUT_PAR2*exp(-1.0*BCAL_PHI_CUT_PAR3*locProjMom.Mag());
1523  locShowerMatchParams->dDeltaZToShower = locDeltaZ;
1524 
1525  return true;
1526 }
1527 
1528 /********************************************************** CUT MATCH DISTANCE **********************************************************/
1529 
1530 bool DParticleID::Cut_MatchDistance(const DReferenceTrajectory* rt, const DBCALShower* locBCALShower, double locInputStartTime, shared_ptr<DBCALShowerMatchParams>& locShowerMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1531 {
1532  if(rt == nullptr)
1533  return false;
1534 
1535  DVector3 locProjPos, locProjMom;
1536  if(!Distance_ToTrack(rt, locBCALShower, locInputStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1537  return false;
1538 
1539  if(locOutputProjMom != nullptr)
1540  {
1541  *locOutputProjPos = locProjPos;
1542  *locOutputProjMom = locProjMom;
1543  }
1544 
1545  // cut on shower delta-z
1546  if(fabs(locShowerMatchParams->dDeltaZToShower) > BCAL_Z_CUT)
1547  return false;
1548 
1549  // cut on shower delta-phi
1550  double locP = locProjMom.Mag();
1551  double locDeltaPhi = 180.0*locShowerMatchParams->dDeltaPhiToShower/TMath::Pi();
1552  double locPhiCut = BCAL_PHI_CUT_PAR1 + BCAL_PHI_CUT_PAR2*exp(-1.0*BCAL_PHI_CUT_PAR3*locP);
1553  if(fabs(locDeltaPhi) > locPhiCut)
1554  return false;
1555 
1556  //successful match
1557  return true;
1558 }
1559 
1560 bool DParticleID::Cut_MatchDistance(const DReferenceTrajectory* rt, const DTOFPoint* locTOFPoint, double locInputStartTime, shared_ptr<DTOFHitMatchParams>& locTOFHitMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1561 {
1562  if(rt == nullptr)
1563  return false;
1564 
1565  // Find the distance of closest approach between the track trajectory
1566  // and the tof cluster position, looking for the minimum
1567 
1568  DVector3 locProjPos, locProjMom;
1569  if(!Distance_ToTrack(rt, locTOFPoint, locInputStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
1570  return false;
1571 
1572  if(locOutputProjMom != nullptr)
1573  {
1574  *locOutputProjPos = locProjPos;
1575  *locOutputProjMom = locProjMom;
1576  }
1577 
1578  //If the position in one dimension is not well-defined, compare distance only in the other direction
1579  //Otherwise, cut in R
1580  double locMatchCut_2D = exp(-1.0*TOF_CUT_PAR1*locProjMom.Mag() + TOF_CUT_PAR2) + TOF_CUT_PAR3;
1581  double locTheta=locProjMom.Theta()*180./M_PI;
1582  locMatchCut_2D*=1.+TOF_CUT_PAR4*locTheta*locTheta;
1583  double locMatchCut_1D = locMatchCut_2D;
1584 
1585  double locDeltaX = locTOFHitMatchParams->dDeltaXToHit;
1586  double locDeltaY = locTOFHitMatchParams->dDeltaYToHit;
1587  if(!locTOFPoint->Is_XPositionWellDefined())
1588  {
1589  //Is unmatched horizontal paddle with only one hit above threshold: Only compare y-distance
1590  if(fabs(locDeltaY) > locMatchCut_1D)
1591  return false;
1592  }
1593  else if(!locTOFPoint->Is_YPositionWellDefined())
1594  {
1595  //Is unmatched vertical paddle with only one hit above threshold: Only compare x-distance
1596  if(fabs(locDeltaX) > locMatchCut_1D)
1597  return false;
1598  }
1599  else
1600  {
1601  //Both are good, cut on R
1602  double locDistance = sqrt(locDeltaX*locDeltaX + locDeltaY*locDeltaY);
1603  if(locDistance > locMatchCut_2D)
1604  return false;
1605  }
1606 
1607  return true;
1608 }
1609 
1610 bool DParticleID::Cut_MatchDistance(const DReferenceTrajectory* rt, const DSCHit* locSCHit, double locInputStartTime, shared_ptr<DSCHitMatchParams>& locSCHitMatchParams, bool locIsTimeBased, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1611 {
1612  if(rt == nullptr)
1613  return false;
1614  if (! START_EXIST)
1615  return false; // if no Start Counter in geometry
1616 
1617 
1618  DVector3 locProjPos, locProjMom;
1619  if(!Distance_ToTrack(rt, locSCHit, locInputStartTime, locSCHitMatchParams, &locProjPos, &locProjMom))
1620  return false;
1621 
1622  if(locOutputProjMom != nullptr)
1623  {
1624  *locOutputProjPos = locProjPos;
1625  *locOutputProjMom = locProjMom;
1626  }
1627 
1628  // Look for a match in phi
1629  auto& locSCCutPars = locIsTimeBased ? dSCCutPars_TimeBased : dSCCutPars_WireBased;
1630  double sc_dphi_cut = locSCCutPars[0] + locSCCutPars[1]*exp(locSCCutPars[2]*(locProjPos.Z() - locSCCutPars[3]));
1631  double locDeltaPhi = 180.0*locSCHitMatchParams->dDeltaPhiToHit/TMath::Pi();
1632  return (fabs(locDeltaPhi) <= sc_dphi_cut);
1633 }
1634 
1635 bool DParticleID::Cut_MatchDistance(const DReferenceTrajectory* rt, const DFCALShower* locFCALShower, double locInputStartTime, shared_ptr<DFCALShowerMatchParams>& locShowerMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1636 {
1637  if(rt == nullptr)
1638  return false;
1639 
1640  DVector3 locProjPos, locProjMom;
1641  if(!Distance_ToTrack(rt, locFCALShower, locInputStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1642  return false;
1643 
1644  if(locOutputProjMom != nullptr)
1645  {
1646  *locOutputProjPos = locProjPos;
1647  *locOutputProjMom = locProjMom;
1648  }
1649 
1650  double p=locProjMom.Mag();
1651  double cut=FCAL_CUT_PAR1+FCAL_CUT_PAR2/p;
1652  return (locShowerMatchParams->dDOCAToShower < cut);
1653 }
1654 
1655 // The following routines use the extrapolations from the track
1656 
1657 bool DParticleID::Cut_MatchDistance(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DBCALShower* locBCALShower, double locInputStartTime,shared_ptr<DBCALShowerMatchParams>& locShowerMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1658 {
1659 
1660  DVector3 locProjPos, locProjMom;
1661  if(!Distance_ToTrack(extrapolations, locBCALShower, locInputStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1662  return false;
1663 
1664  if(locOutputProjMom != nullptr)
1665  {
1666  *locOutputProjPos = locProjPos;
1667  *locOutputProjMom = locProjMom;
1668  }
1669 
1670  // cut on shower delta-z
1671  if(fabs(locShowerMatchParams->dDeltaZToShower) > BCAL_Z_CUT)
1672  return false;
1673 
1674  // cut on shower delta-phi
1675  double locP = locProjMom.Mag();
1676  double locDeltaPhi = 180.0*locShowerMatchParams->dDeltaPhiToShower/TMath::Pi();
1677  double locPhiCut = BCAL_PHI_CUT_PAR1 + BCAL_PHI_CUT_PAR2*exp(-1.0*BCAL_PHI_CUT_PAR3*locP);
1678 
1679  if(fabs(locDeltaPhi) > locPhiCut)
1680  return false;
1681 
1682  //successful match
1683  return true;
1684 }
1685 
1686 
1687 bool DParticleID::Cut_MatchDistance(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DFCALShower* locFCALShower, double locInputStartTime,shared_ptr<DFCALShowerMatchParams>& locShowerMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1688 {
1689  DVector3 locProjPos, locProjMom;
1690  if(!Distance_ToTrack(extrapolations, locFCALShower, locInputStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1691  return false;
1692 
1693  if(locOutputProjMom != nullptr)
1694  {
1695  *locOutputProjPos = locProjPos;
1696  *locOutputProjMom = locProjMom;
1697  }
1698 
1699  double p=locProjMom.Mag();
1700  double theta=locProjMom.Theta()*180./M_PI;
1701  double cut=(FCAL_CUT_PAR1+FCAL_CUT_PAR2/p)*(1.+FCAL_CUT_PAR3*theta*theta);
1702  return (locShowerMatchParams->dDOCAToShower < cut);
1703 }
1704 
1705 bool DParticleID::Cut_MatchDistance(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DTOFPoint* locTOFPoint, double locInputStartTime,shared_ptr<DTOFHitMatchParams>& locTOFHitMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1706 {
1707  DVector3 locProjPos, locProjMom;
1708  if(!Distance_ToTrack(extrapolations, locTOFPoint, locInputStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
1709  return false;
1710 
1711  if(locOutputProjMom != nullptr)
1712  {
1713  *locOutputProjPos = locProjPos;
1714  *locOutputProjMom = locProjMom;
1715  }
1716 
1717  //If the position in one dimension is not well-defined, compare distance only in the other direction
1718  //Otherwise, cut in R
1719  double locMatchCut_2D = exp(-1.0*TOF_CUT_PAR1*locProjMom.Mag() + TOF_CUT_PAR2) + TOF_CUT_PAR3;
1720  double locMatchCut_1D = locMatchCut_2D;
1721 
1722  double locDeltaX = locTOFHitMatchParams->dDeltaXToHit;
1723  double locDeltaY = locTOFHitMatchParams->dDeltaYToHit;
1724  if(!locTOFPoint->Is_XPositionWellDefined())
1725  {
1726  //Is unmatched horizontal paddle with only one hit above threshold: Only compare y-distance
1727  if(fabs(locDeltaY) > locMatchCut_1D)
1728  return false;
1729  }
1730  else if(!locTOFPoint->Is_YPositionWellDefined())
1731  {
1732  //Is unmatched vertical paddle with only one hit above threshold: Only compare x-distance
1733  if(fabs(locDeltaX) > locMatchCut_1D)
1734  return false;
1735  }
1736  else
1737  {
1738  //Both are good, cut on R
1739  double locDistance = sqrt(locDeltaX*locDeltaX + locDeltaY*locDeltaY);
1740  if(locDistance > locMatchCut_2D)
1741  return false;
1742  }
1743 
1744  return true;
1745 }
1746 
1747 bool DParticleID::Cut_MatchDistance(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const DSCHit* locSCHit, double locInputStartTime,shared_ptr<DSCHitMatchParams>& locSCHitMatchParams, bool locIsTimeBased, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1748 {
1749  DVector3 locProjPos, locProjMom;
1750  if(!Distance_ToTrack(extrapolations, locSCHit, locInputStartTime, locSCHitMatchParams, &locProjPos, &locProjMom))
1751  return false;
1752 
1753  if(locOutputProjMom != nullptr)
1754  {
1755  *locOutputProjPos = locProjPos;
1756  *locOutputProjMom = locProjMom;
1757  }
1758 
1759  // Look for a match in phi
1760  auto& locSCCutPars = locIsTimeBased ? dSCCutPars_TimeBased : dSCCutPars_WireBased;
1761  double sc_dphi_cut = locSCCutPars[0] + locSCCutPars[1]*exp(locSCCutPars[2]*(locProjPos.Z() - locSCCutPars[3]));
1762  double locDeltaPhi = 180.0*locSCHitMatchParams->dDeltaPhiToHit/TMath::Pi();
1763  return (fabs(locDeltaPhi) <= sc_dphi_cut);
1764 }
1765 
1766 
1767 bool DParticleID::Cut_MatchDIRC(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DDIRCPmtHit*> locDIRCHits, double locInputStartTime, Particle_t locPID, shared_ptr<DDIRCMatchParams>& locDIRCMatchParams, const vector<const DDIRCTruthBarHit*> locDIRCBarHits, map<shared_ptr<const DDIRCMatchParams>, vector<const DDIRCPmtHit*> >& locDIRCTrackMatchParams, DVector3 *locOutputProjPos, DVector3 *locOutputProjMom) const
1768 {
1769  if (extrapolations.size()==0)
1770  return false;
1771 
1772  DVector3 locProjPos = extrapolations[0].position;
1773  DVector3 locProjMom = extrapolations[0].momentum;
1774  double locFlightTime = locInputStartTime + extrapolations[0].t;
1775 
1776  if(locOutputProjMom != nullptr) {
1777  *locOutputProjPos = locProjPos;
1778  *locOutputProjMom = locProjMom;
1779  }
1780 
1781  // Calculate DIRC LUT
1782  return dDIRCLut->CalcLUT(locProjPos, locProjMom, locDIRCHits, locFlightTime, locPID, locDIRCMatchParams, locDIRCBarHits, locDIRCTrackMatchParams);
1783 
1784 }
1785 
1786 
1787 /********************************************************** GET BEST MATCH **********************************************************/
1788 
1789 bool DParticleID::Get_BestBCALMatchParams(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches, shared_ptr<const DBCALShowerMatchParams>& locBestMatchParams) const
1790 {
1791  //choose the "best" shower to use for computing quantities
1792  vector<shared_ptr<const DBCALShowerMatchParams> > locShowerMatchParams;
1793  if(!locDetectorMatches->Get_BCALMatchParams(locTrack, locShowerMatchParams))
1794  return false;
1795 
1796  locBestMatchParams = Get_BestBCALMatchParams(locTrack->momentum(), locShowerMatchParams);
1797  return true;
1798 }
1799 
1800 shared_ptr<const DBCALShowerMatchParams> DParticleID::Get_BestBCALMatchParams(DVector3 locMomentum, vector<shared_ptr<const DBCALShowerMatchParams> >& locShowerMatchParams) const
1801 {
1802  double locMinChiSq = 9.9E9;
1803  double locP = locMomentum.Mag();
1804  shared_ptr<const DBCALShowerMatchParams> locBestMatchParams;
1805  for(size_t loc_i = 0; loc_i < locShowerMatchParams.size(); ++loc_i)
1806  {
1807  double locDeltaPhiCut = BCAL_PHI_CUT_PAR1 + BCAL_PHI_CUT_PAR2*exp(-1.0*BCAL_PHI_CUT_PAR3*locP);
1808  double locDeltaPhiError = locDeltaPhiCut/3.0; //Cut is "3 sigma"
1809  double locDeltaPhi = 180.0*locShowerMatchParams[loc_i]->dDeltaPhiToShower/TMath::Pi();
1810  double locMatchChiSq = locDeltaPhi*locDeltaPhi/(locDeltaPhiError*locDeltaPhiError);
1811 
1812  double locDeltaZError = BCAL_Z_CUT/3.0; //Cut is "3 sigma"
1813  locMatchChiSq += locShowerMatchParams[loc_i]->dDeltaZToShower*locShowerMatchParams[loc_i]->dDeltaZToShower/(locDeltaZError*locDeltaZError);
1814 
1815  if(locMatchChiSq >= locMinChiSq)
1816  continue;
1817 
1818  locMinChiSq = locMatchChiSq;
1819  locBestMatchParams = locShowerMatchParams[loc_i];
1820  }
1821 
1822  return locBestMatchParams;
1823 }
1824 
1825 bool DParticleID::Get_BestSCMatchParams(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches, shared_ptr<const DSCHitMatchParams>& locBestMatchParams) const
1826 {
1827  //choose the "best" detector hit to use for computing quantities
1828  vector<shared_ptr<const DSCHitMatchParams> > locSCHitMatchParams;
1829  if(!locDetectorMatches->Get_SCMatchParams(locTrack, locSCHitMatchParams))
1830  return false;
1831 
1832  locBestMatchParams = Get_BestSCMatchParams(locSCHitMatchParams);
1833  return true;
1834 }
1835 
1836 shared_ptr<const DSCHitMatchParams> DParticleID::Get_BestSCMatchParams(vector<shared_ptr<const DSCHitMatchParams> >& locSCHitMatchParams) const
1837 {
1838  double locMinDeltaPhi = 9.9E9;
1839  shared_ptr<const DSCHitMatchParams> locBestMatchParams;
1840  for(size_t loc_i = 0; loc_i < locSCHitMatchParams.size(); ++loc_i)
1841  {
1842  if(fabs(locSCHitMatchParams[loc_i]->dDeltaPhiToHit) >= locMinDeltaPhi)
1843  continue;
1844  locMinDeltaPhi = fabs(locSCHitMatchParams[loc_i]->dDeltaPhiToHit);
1845  locBestMatchParams = locSCHitMatchParams[loc_i];
1846  }
1847  return locBestMatchParams;
1848 }
1849 
1850 bool DParticleID::Get_BestTOFMatchParams(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches, shared_ptr<const DTOFHitMatchParams>& locBestMatchParams) const
1851 {
1852  //choose the "best" hit to use for computing quantities
1853  vector<shared_ptr<const DTOFHitMatchParams> > locTOFHitMatchParams;
1854  if(!locDetectorMatches->Get_TOFMatchParams(locTrack, locTOFHitMatchParams))
1855  return false;
1856 
1857  locBestMatchParams = Get_BestTOFMatchParams(locTOFHitMatchParams);
1858  return true;
1859 }
1860 
1861 shared_ptr<const DTOFHitMatchParams> DParticleID::Get_BestTOFMatchParams(vector<shared_ptr<const DTOFHitMatchParams> >& locTOFHitMatchParams) const
1862 {
1863  double locMinDistance = 9.9E9;
1864  shared_ptr<const DTOFHitMatchParams> locBestMatchParams;
1865  for(size_t loc_i = 0; loc_i < locTOFHitMatchParams.size(); ++loc_i)
1866  {
1867  double locDeltaR = sqrt(locTOFHitMatchParams[loc_i]->dDeltaXToHit*locTOFHitMatchParams[loc_i]->dDeltaXToHit + locTOFHitMatchParams[loc_i]->dDeltaYToHit*locTOFHitMatchParams[loc_i]->dDeltaYToHit);
1868  if(locDeltaR >= locMinDistance)
1869  continue;
1870  locMinDistance = locDeltaR;
1871  locBestMatchParams = locTOFHitMatchParams[loc_i];
1872  }
1873  return locBestMatchParams;
1874 }
1875 
1876 bool DParticleID::Get_BestFCALMatchParams(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches, shared_ptr<const DFCALShowerMatchParams>& locBestMatchParams) const
1877 {
1878  //choose the "best" shower to use for computing quantities
1879  vector<shared_ptr<const DFCALShowerMatchParams> > locShowerMatchParams;
1880  if(!locDetectorMatches->Get_FCALMatchParams(locTrack, locShowerMatchParams))
1881  return false;
1882 
1883  locBestMatchParams = Get_BestFCALMatchParams(locShowerMatchParams);
1884  return true;
1885 }
1886 
1887 shared_ptr<const DFCALShowerMatchParams> DParticleID::Get_BestFCALMatchParams(vector<shared_ptr<const DFCALShowerMatchParams> >& locShowerMatchParams) const
1888 {
1889  double locMinDistance = 9.9E9;
1890  shared_ptr<const DFCALShowerMatchParams> locBestMatchParams;
1891  for(size_t loc_i = 0; loc_i < locShowerMatchParams.size(); ++loc_i)
1892  {
1893  if(locShowerMatchParams[loc_i]->dDOCAToShower >= locMinDistance)
1894  continue;
1895  locMinDistance = locShowerMatchParams[loc_i]->dDOCAToShower;
1896  locBestMatchParams = locShowerMatchParams[loc_i];
1897  }
1898  return locBestMatchParams;
1899 }
1900 
1901 bool DParticleID::Get_DIRCMatchParams(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches, shared_ptr<const DDIRCMatchParams>& locBestMatchParams) const
1902 {
1903  //choose the "best" shower to use for computing quantities
1904  shared_ptr<const DDIRCMatchParams> locDIRCMatchParams;
1905  if(!locDetectorMatches->Get_DIRCMatchParams(locTrack, locDIRCMatchParams))
1906  return false;
1907 
1908  locBestMatchParams = locDIRCMatchParams;
1909  return true;
1910 }
1911 
1912 /********************************************************** GET CLOSEST TO TRACK **********************************************************/
1913 
1914 // NOTE: an initial guess for start time is expected as input so that out-of-time hits can be skipped
1915 bool DParticleID::Get_ClosestToTrack(const DReferenceTrajectory* rt, const vector<const DBCALShower*>& locBCALShowers, bool locCutFlag, double& locStartTime, shared_ptr<const DBCALShowerMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
1916 {
1917  if(rt == nullptr)
1918  return false;
1919 
1920  //Loop over bcal showers
1921  vector<shared_ptr<const DBCALShowerMatchParams> > locShowerMatchParamsVector;
1922  vector<pair<shared_ptr<DBCALShowerMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
1923  for(size_t loc_i = 0; loc_i < locBCALShowers.size(); ++loc_i)
1924  {
1925  shared_ptr<DBCALShowerMatchParams> locShowerMatchParams;
1926  DVector3 locProjPos, locProjMom;
1927  if(locCutFlag)
1928  {
1929  if(!Cut_MatchDistance(rt, locBCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1930  continue;
1931  }
1932  else
1933  {
1934  if(!Distance_ToTrack(rt, locBCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
1935  continue;
1936  }
1937  locShowerMatchParamsVector.push_back(locShowerMatchParams);
1938  auto locMatchProjectionPair = make_pair(locShowerMatchParams, make_pair(locProjPos, locProjMom));
1939  locMatchProjectionPairs.push_back(locMatchProjectionPair);
1940  }
1941  if(locShowerMatchParamsVector.empty())
1942  return false;
1943 
1944  locBestMatchParams = Get_BestBCALMatchParams(rt->swim_steps[0].mom, locShowerMatchParamsVector);
1945 
1946  if(locStartTimeVariance != nullptr)
1947  {
1948  locStartTime = locBestMatchParams->dBCALShower->t - locBestMatchParams->dFlightTime;
1949  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dBCALShower->dCovarianceMatrix(4, 4); //uncomment when ready!!
1950  *locStartTimeVariance = 0.3*0.3+locBestMatchParams->dFlightTimeVariance;
1951  }
1952 
1953  if(locBestProjMom != nullptr)
1954  {
1955  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
1956  {
1957  auto locParams = locMatchProjectionPair.first;
1958  if(locParams != locBestMatchParams)
1959  continue;
1960  *locBestProjPos = locMatchProjectionPair.second.first;
1961  *locBestProjMom = locMatchProjectionPair.second.second;
1962  break;
1963  }
1964  }
1965 
1966  return true;
1967 }
1968 
1969 bool DParticleID::Get_ClosestToTrack(const DReferenceTrajectory* rt, const vector<const DTOFPoint*>& locTOFPoints, bool locCutFlag, double& locStartTime, shared_ptr<const DTOFHitMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
1970 {
1971  if(rt == nullptr)
1972  return false;
1973 
1974  //Loop over tof points
1975  vector<shared_ptr<const DTOFHitMatchParams> > locTOFHitMatchParamsVector;
1976  vector<pair<shared_ptr<DTOFHitMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
1977  for(size_t loc_i = 0; loc_i < locTOFPoints.size(); ++loc_i)
1978  {
1979  shared_ptr<DTOFHitMatchParams> locTOFHitMatchParams;
1980  DVector3 locProjPos, locProjMom;
1981  if(locCutFlag)
1982  {
1983  if(!Cut_MatchDistance(rt, locTOFPoints[loc_i], locStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
1984  continue;
1985  }
1986  else
1987  {
1988  if(!Distance_ToTrack(rt, locTOFPoints[loc_i], locStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
1989  continue;
1990  }
1991  locTOFHitMatchParamsVector.push_back(locTOFHitMatchParams);
1992  auto locMatchProjectionPair = make_pair(locTOFHitMatchParams, make_pair(locProjPos, locProjMom));
1993  locMatchProjectionPairs.push_back(locMatchProjectionPair);
1994  }
1995  if(locTOFHitMatchParamsVector.empty())
1996  return false;
1997 
1998  locBestMatchParams = Get_BestTOFMatchParams(locTOFHitMatchParamsVector);
1999 
2000  if(locStartTimeVariance != nullptr)
2001  {
2002  locStartTime = locBestMatchParams->dHitTime - locBestMatchParams->dFlightTime;
2003  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dHitTimeVariance; //uncomment when ready!
2004  *locStartTimeVariance = 0.1*0.1+locBestMatchParams->dFlightTimeVariance;
2005  }
2006 
2007  if(locBestProjMom != nullptr)
2008  {
2009  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2010  {
2011  auto locParams = locMatchProjectionPair.first;
2012  if(locParams != locBestMatchParams)
2013  continue;
2014  *locBestProjPos = locMatchProjectionPair.second.first;
2015  *locBestProjMom = locMatchProjectionPair.second.second;
2016  break;
2017  }
2018  }
2019 
2020  return true;
2021 }
2022 
2023 bool DParticleID::Get_ClosestToTrack(const DReferenceTrajectory* rt, const vector<const DFCALShower*>& locFCALShowers, bool locCutFlag, double& locStartTime, shared_ptr<const DFCALShowerMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2024 {
2025  if(rt == nullptr)
2026  return false;
2027 
2028  //Loop over FCAL showers
2029  vector<shared_ptr<const DFCALShowerMatchParams> > locShowerMatchParamsVector;
2030  vector<pair<shared_ptr<DFCALShowerMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2031  for(size_t loc_i = 0; loc_i < locFCALShowers.size(); ++loc_i)
2032  {
2033  shared_ptr<DFCALShowerMatchParams> locShowerMatchParams;
2034  DVector3 locProjPos, locProjMom;
2035  if(locCutFlag)
2036  {
2037  if(!Cut_MatchDistance(rt, locFCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2038  continue;
2039  }
2040  else
2041  {
2042  if(!Distance_ToTrack(rt, locFCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2043  continue;
2044  }
2045  locShowerMatchParamsVector.push_back(locShowerMatchParams);
2046  auto locMatchProjectionPair = make_pair(locShowerMatchParams, make_pair(locProjPos, locProjMom));
2047  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2048  }
2049  if(locShowerMatchParamsVector.empty())
2050  return false;
2051 
2052  locBestMatchParams = Get_BestFCALMatchParams(locShowerMatchParamsVector);
2053 
2054  if(locStartTimeVariance != nullptr)
2055  {
2056  locStartTime = locBestMatchParams->dFCALShower->getTime() - locBestMatchParams->dFlightTime;
2057  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dFCALShower->dCovarianceMatrix(4, 4); //uncomment when ready!
2058  *locStartTimeVariance = 0.5*0.5+locBestMatchParams->dFlightTimeVariance;
2059  }
2060 
2061  if(locBestProjMom != nullptr)
2062  {
2063  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2064  {
2065  auto locParams = locMatchProjectionPair.first;
2066  if(locParams != locBestMatchParams)
2067  continue;
2068  *locBestProjPos = locMatchProjectionPair.second.first;
2069  *locBestProjMom = locMatchProjectionPair.second.second;
2070  break;
2071  }
2072  }
2073 
2074  return true;
2075 }
2076 
2077 bool DParticleID::Get_ClosestToTrack(const DReferenceTrajectory* rt, const vector<const DSCHit*>& locSCHits, bool locIsTimeBased, bool locCutFlag, double& locStartTime, shared_ptr<const DSCHitMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2078 {
2079  if(rt == nullptr)
2080  return false;
2081  if (! START_EXIST)
2082  return false; // if no Start Counter in geometry
2083 
2084 
2085  //Loop over SC points
2086  vector<shared_ptr<const DSCHitMatchParams> > locSCHitMatchParamsVector;
2087  vector<pair<shared_ptr<DSCHitMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2088  for(size_t loc_i = 0; loc_i < locSCHits.size(); ++loc_i)
2089  {
2090  shared_ptr<DSCHitMatchParams> locSCHitMatchParams;
2091  DVector3 locProjPos, locProjMom;
2092  if(locCutFlag)
2093  {
2094  if(!Cut_MatchDistance(rt, locSCHits[loc_i], locStartTime, locSCHitMatchParams, locIsTimeBased, &locProjPos, &locProjMom))
2095  continue;
2096  }
2097  else
2098  {
2099  if(!Distance_ToTrack(rt, locSCHits[loc_i], locStartTime, locSCHitMatchParams, &locProjPos, &locProjMom))
2100  continue;
2101  }
2102  locSCHitMatchParamsVector.push_back(std::const_pointer_cast<const DSCHitMatchParams>(locSCHitMatchParams));
2103  auto locMatchProjectionPair = make_pair(locSCHitMatchParams, make_pair(locProjPos, locProjMom));
2104  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2105  }
2106  if(locSCHitMatchParamsVector.empty())
2107  return false;
2108 
2109  locBestMatchParams = Get_BestSCMatchParams(locSCHitMatchParamsVector);
2110 
2111  if(locStartTimeVariance != nullptr)
2112  {
2113  locStartTime = locBestMatchParams->dHitTime - locBestMatchParams->dFlightTime;
2114  *locStartTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dHitTimeVariance;
2115  //locTimeVariance = 0.3*0.3+locBestMatchParams->dFlightTimeVariance;
2116  }
2117 
2118  if(locBestProjMom != nullptr)
2119  {
2120  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2121  {
2122  auto locParams = locMatchProjectionPair.first;
2123  if(locParams != locBestMatchParams)
2124  continue;
2125  *locBestProjPos = locMatchProjectionPair.second.first;
2126  *locBestProjMom = locMatchProjectionPair.second.second;
2127  break;
2128  }
2129  }
2130 
2131  return true;
2132 }
2133 
2134 const DTOFPaddleHit* DParticleID::Get_ClosestTOFPaddleHit_Horizontal(const DReferenceTrajectory* locReferenceTrajectory, const vector<const DTOFPaddleHit*>& locTOFPaddleHits, double locInputStartTime, double& locBestDeltaY, double& locBestDistance) const
2135 {
2136  if(locReferenceTrajectory == nullptr)
2137  return nullptr;
2138 
2139  DVector3 tof_pos(0.0, 0.0, dTOFGeometry->Get_CenterHorizPlane()); //a point on the TOF plane
2140  DVector3 norm(0.0, 0.0, 1.0); //normal vector to TOF plane
2141  DVector3 proj_pos, proj_mom;
2142  double locPathLength = 9.9E9, locFlightTime = 9.9E9;
2143  if(locReferenceTrajectory->GetIntersectionWithPlane(tof_pos, norm, proj_pos, proj_mom, &locPathLength, &locFlightTime, NULL, SYS_TOF) != NOERROR)
2144  return nullptr;
2145 
2146  const DTOFPaddleHit* locClosestPaddleHit = nullptr;
2147  locBestDistance = 999.0;
2148  locBestDeltaY = 999.0;
2149  for(auto& locTOFPaddleHit : locTOFPaddleHits)
2150  {
2151  if(locTOFPaddleHit->orientation != 1)
2152  continue; //horizontal orientation is 1
2153 
2154  bool locNorthIsGoodHitFlag = (locTOFPaddleHit->E_north > TOF_E_THRESHOLD);
2155  bool locSouthIsGoodHitFlag = (locTOFPaddleHit->E_south > TOF_E_THRESHOLD);
2156  if(!locNorthIsGoodHitFlag && !locSouthIsGoodHitFlag)
2157  continue; //hit is junk
2158 
2159  // Check that the hit is not out of time with respect to the track
2160 
2161  //Construct spacetime hit: averages times, or if only one end with hit, reports time at center of paddle
2163  double locHitTime = locSpacetimeHit->t;
2164 
2165  // if single-ended paddle, or only one side has a hit: time reported at center: must propagate to track location
2166  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2167  {
2168  //Paddle midpoint
2169  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
2170  if(!locSpacetimeHit->dIsDoubleEndedBar)
2171  locPaddleMidPoint = locNorthIsGoodHitFlag ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
2172 
2173  //correct the time
2174  double locDistanceToMidPoint = locNorthIsGoodHitFlag ? locPaddleMidPoint - proj_pos.X() : proj_pos.X() - locPaddleMidPoint;
2175  int id = 44 + locTOFPaddleHit->bar - 1; //for propation speed
2176  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
2177  }
2178 
2179  //time cut
2180  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
2181  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
2182  continue;
2183 
2184  // Check geometric distance, continue only if better than before
2185  double locDeltaY = dTOFGeometry->bar2y(locTOFPaddleHit->bar) - proj_pos.Y();
2186  double locDeltaX = locTOFPaddleHit->pos - proj_pos.X();
2187  double locDistance = sqrt(locDeltaY*locDeltaY + locDeltaX*locDeltaX);
2188  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2189  {
2190  //no position information along paddle: use delta-y cut only
2191  if(fabs(locDeltaY) > fabs(locBestDistance))
2192  continue;
2193  if(fabs(locDeltaY) > fabs(locBestDeltaY))
2194  continue; //no info on delta-x, so make sure not unfair comparison
2195  locBestDistance = fabs(locDeltaY);
2196  }
2197  else
2198  {
2199  if(locDistance > locBestDistance)
2200  continue;
2201  locBestDistance = locDistance;
2202  }
2203 
2204  locBestDeltaY = locDeltaY;
2205  locClosestPaddleHit = locTOFPaddleHit;
2206  }
2207 
2208  return locClosestPaddleHit;
2209 }
2210 
2211 const DTOFPaddleHit* DParticleID::Get_ClosestTOFPaddleHit_Vertical(const DReferenceTrajectory* locReferenceTrajectory, const vector<const DTOFPaddleHit*>& locTOFPaddleHits, double locInputStartTime, double& locBestDeltaX, double& locBestDistance) const
2212 {
2213  if(locReferenceTrajectory == nullptr)
2214  return nullptr;
2215 
2216  // Evaluate matching solely by physical geometry of the paddle: NOT the distance along the paddle of the hit
2217  DVector3 tof_pos(0.0, 0.0, dTOFGeometry->Get_CenterVertPlane()); //a point on the TOF plane
2218  DVector3 norm(0.0, 0.0, 1.0); //normal vector to TOF plane
2219  DVector3 proj_pos, proj_mom;
2220  double locPathLength = 9.9E9, locFlightTime = 9.9E9;
2221  if(locReferenceTrajectory->GetIntersectionWithPlane(tof_pos, norm, proj_pos, proj_mom, &locPathLength, &locFlightTime, NULL, SYS_TOF) != NOERROR)
2222  return nullptr;
2223 
2224  const DTOFPaddleHit* locClosestPaddleHit = nullptr;
2225  locBestDistance = 999.0;
2226  locBestDeltaX = 999.0;
2227  for(auto& locTOFPaddleHit : locTOFPaddleHits)
2228  {
2229  if(locTOFPaddleHit->orientation != 0)
2230  continue; //vertical orientation is 0
2231 
2232  bool locNorthIsGoodHitFlag = (locTOFPaddleHit->E_north > TOF_E_THRESHOLD);
2233  bool locSouthIsGoodHitFlag = (locTOFPaddleHit->E_south > TOF_E_THRESHOLD);
2234  if(!locNorthIsGoodHitFlag && !locSouthIsGoodHitFlag)
2235  continue; //hit is junk
2236 
2237  // Check that the hit is not out of time with respect to the track
2238 
2239  //Construct spacetime hit: averages times, or if only one end with hit, reports time at center of paddle
2241  double locHitTime = locSpacetimeHit->t;
2242 
2243  // if single-ended paddle, or only one side has a hit: time reported at center: must propagate to track location
2244  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2245  {
2246  //Paddle midpoint
2247  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
2248  if(!locSpacetimeHit->dIsDoubleEndedBar)
2249  locPaddleMidPoint = locNorthIsGoodHitFlag ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
2250 
2251  //correct the time
2252  double locDistanceToMidPoint = locNorthIsGoodHitFlag ? locPaddleMidPoint - proj_pos.Y() : proj_pos.Y() - locPaddleMidPoint;
2253  int id = locTOFPaddleHit->bar - 1; //for propation speed
2254  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
2255  }
2256 
2257  //time cut
2258  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
2259  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
2260  continue;
2261 
2262  // Check geometric distance, continue only if better than before
2263  double locDeltaX = dTOFGeometry->bar2y(locTOFPaddleHit->bar) - proj_pos.X();
2264  double locDeltaY = locTOFPaddleHit->pos - proj_pos.Y();
2265  double locDistance = sqrt(locDeltaY*locDeltaY + locDeltaX*locDeltaX);
2266  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2267  {
2268  //no position information along paddle: use delta-y cut only
2269  if(fabs(locDeltaX) > fabs(locBestDistance))
2270  continue;
2271  if(fabs(locDeltaX) > fabs(locBestDeltaX))
2272  continue; //no info on delta-x, so make sure not unfair comparison
2273  locBestDistance = fabs(locDeltaX);
2274  }
2275  else
2276  {
2277  if(locDistance > locBestDistance)
2278  continue;
2279  locBestDistance = locDistance;
2280  }
2281 
2282  locBestDeltaX = locDeltaX;
2283  locClosestPaddleHit = locTOFPaddleHit;
2284  }
2285 
2286  return locClosestPaddleHit;
2287 }
2288 
2289 // The following routines use extrapolations from the track
2290 bool DParticleID::Get_ClosestToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DBCALShower*>& locBCALShowers, bool locCutFlag, double& locStartTime,shared_ptr<const DBCALShowerMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2291 {
2292  if(extrapolations.size()==0)
2293  return false;
2294 
2295  //Loop over bcal showers
2296  vector<shared_ptr<const DBCALShowerMatchParams>> locShowerMatchParamsVector;
2297  vector<pair<shared_ptr<DBCALShowerMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2298  for(size_t loc_i = 0; loc_i < locBCALShowers.size(); ++loc_i)
2299  {
2300  shared_ptr<DBCALShowerMatchParams> locShowerMatchParams;
2301  DVector3 locProjPos, locProjMom;
2302  if(locCutFlag)
2303  {
2304  if(!Cut_MatchDistance(extrapolations, locBCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2305  continue;
2306  }
2307  else
2308  {
2309  if(!Distance_ToTrack(extrapolations, locBCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2310  continue;
2311  }
2312  locShowerMatchParamsVector.push_back(locShowerMatchParams);
2313  auto locMatchProjectionPair = make_pair(locShowerMatchParams, make_pair(locProjPos, locProjMom));
2314  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2315  }
2316  if(locShowerMatchParamsVector.empty())
2317  return false;
2318 
2319  locBestMatchParams = Get_BestBCALMatchParams(extrapolations[0].momentum,
2320  locShowerMatchParamsVector);
2321 
2322  if(locStartTimeVariance != nullptr)
2323  {
2324  locStartTime = locBestMatchParams->dBCALShower->t - locBestMatchParams->dFlightTime;
2325  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dBCALShower->dCovarianceMatrix(4, 4); //uncomment when ready!!
2326  *locStartTimeVariance = 0.3*0.3+locBestMatchParams->dFlightTimeVariance;
2327  }
2328 
2329  if(locBestProjMom != nullptr)
2330  {
2331  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2332  {
2333  auto locParams = locMatchProjectionPair.first;
2334  if(locParams != locBestMatchParams)
2335  continue;
2336  *locBestProjPos = locMatchProjectionPair.second.first;
2337  *locBestProjMom = locMatchProjectionPair.second.second;
2338  break;
2339  }
2340  }
2341 
2342  return true;
2343 }
2344 
2345 bool DParticleID::Get_ClosestToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DTOFPoint*>& locTOFPoints, bool locCutFlag, double& locStartTime, shared_ptr<const DTOFHitMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2346 {
2347  if(extrapolations.size()==0)
2348  return false;
2349 
2350  //Loop over tof points
2351  vector<shared_ptr<const DTOFHitMatchParams> > locTOFHitMatchParamsVector;
2352  vector<pair<shared_ptr<DTOFHitMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2353  for(size_t loc_i = 0; loc_i < locTOFPoints.size(); ++loc_i)
2354  {
2355  shared_ptr<DTOFHitMatchParams> locTOFHitMatchParams;
2356  DVector3 locProjPos, locProjMom;
2357  if(locCutFlag)
2358  {
2359  if(!Cut_MatchDistance(extrapolations, locTOFPoints[loc_i], locStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
2360  continue;
2361  }
2362  else
2363  {
2364  if(!Distance_ToTrack(extrapolations, locTOFPoints[loc_i], locStartTime, locTOFHitMatchParams, &locProjPos, &locProjMom))
2365  continue;
2366  }
2367  locTOFHitMatchParamsVector.push_back(locTOFHitMatchParams);
2368  auto locMatchProjectionPair = make_pair(locTOFHitMatchParams, make_pair(locProjPos, locProjMom));
2369  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2370  }
2371  if(locTOFHitMatchParamsVector.empty())
2372  return false;
2373 
2374  locBestMatchParams = Get_BestTOFMatchParams(locTOFHitMatchParamsVector);
2375 
2376  if(locStartTimeVariance != nullptr)
2377  {
2378  locStartTime = locBestMatchParams->dHitTime - locBestMatchParams->dFlightTime;
2379  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dHitTimeVariance; //uncomment when ready!
2380  *locStartTimeVariance = 0.1*0.1+locBestMatchParams->dFlightTimeVariance;
2381  }
2382 
2383  if(locBestProjMom != nullptr)
2384  {
2385  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2386  {
2387  auto locParams = locMatchProjectionPair.first;
2388  if(locParams != locBestMatchParams)
2389  continue;
2390  *locBestProjPos = locMatchProjectionPair.second.first;
2391  *locBestProjMom = locMatchProjectionPair.second.second;
2392  break;
2393  }
2394  }
2395 
2396  return true;
2397 }
2398 
2399 bool DParticleID::Get_ClosestToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DFCALShower*>& locFCALShowers, bool locCutFlag, double& locStartTime,shared_ptr<const DFCALShowerMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2400 {
2401  if(extrapolations.size()==0)
2402  return false;
2403 
2404  //Loop over FCAL showers
2405  vector<shared_ptr<const DFCALShowerMatchParams> > locShowerMatchParamsVector;
2406  vector<pair<shared_ptr<DFCALShowerMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2407  for(size_t loc_i = 0; loc_i < locFCALShowers.size(); ++loc_i)
2408  {
2409  shared_ptr<DFCALShowerMatchParams> locShowerMatchParams;
2410  DVector3 locProjPos, locProjMom;
2411  if(locCutFlag)
2412  {
2413  if(!Cut_MatchDistance(extrapolations, locFCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2414  continue;
2415  }
2416  else
2417  {
2418  if(!Distance_ToTrack(extrapolations, locFCALShowers[loc_i], locStartTime, locShowerMatchParams, &locProjPos, &locProjMom))
2419  continue;
2420  }
2421  locShowerMatchParamsVector.push_back(locShowerMatchParams);
2422  auto locMatchProjectionPair = make_pair(locShowerMatchParams, make_pair(locProjPos, locProjMom));
2423  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2424  }
2425  if(locShowerMatchParamsVector.empty())
2426  return false;
2427 
2428  locBestMatchParams = Get_BestFCALMatchParams(locShowerMatchParamsVector);
2429 
2430  if(locStartTimeVariance != nullptr)
2431  {
2432  locStartTime = locBestMatchParams->dFCALShower->getTime() - locBestMatchParams->dFlightTime;
2433  // locTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dFCALShower->dCovarianceMatrix(4, 4); //uncomment when ready!
2434  *locStartTimeVariance = 0.5*0.5+locBestMatchParams->dFlightTimeVariance;
2435  }
2436 
2437  if(locBestProjMom != nullptr)
2438  {
2439  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2440  {
2441  auto locParams = locMatchProjectionPair.first;
2442  if(locParams != locBestMatchParams)
2443  continue;
2444  *locBestProjPos = locMatchProjectionPair.second.first;
2445  *locBestProjMom = locMatchProjectionPair.second.second;
2446  break;
2447  }
2448  }
2449 
2450  return true;
2451 }
2452 
2453 bool DParticleID::Get_ClosestToTrack(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DSCHit*>& locSCHits, bool locIsTimeBased, bool locCutFlag, double& locStartTime,shared_ptr<const DSCHitMatchParams>& locBestMatchParams, double* locStartTimeVariance, DVector3* locBestProjPos, DVector3* locBestProjMom) const
2454 {
2455  if(extrapolations.size()==0)
2456  return false;
2457 
2458  //Loop over SC points
2459  vector<shared_ptr<const DSCHitMatchParams> > locSCHitMatchParamsVector;
2460  vector<pair<shared_ptr<DSCHitMatchParams>, pair<DVector3, DVector3> > > locMatchProjectionPairs;
2461  for(size_t loc_i = 0; loc_i < locSCHits.size(); ++loc_i)
2462  {
2463  shared_ptr<DSCHitMatchParams> locSCHitMatchParams;
2464  DVector3 locProjPos, locProjMom;
2465  if(locCutFlag)
2466  {
2467  if(!Cut_MatchDistance(extrapolations, locSCHits[loc_i], locStartTime, locSCHitMatchParams, locIsTimeBased, &locProjPos, &locProjMom))
2468  continue;
2469  }
2470  else
2471  {
2472  if(!Distance_ToTrack(extrapolations, locSCHits[loc_i], locStartTime, locSCHitMatchParams, &locProjPos, &locProjMom))
2473  continue;
2474  }
2475  locSCHitMatchParamsVector.push_back(locSCHitMatchParams);
2476  auto locMatchProjectionPair = make_pair(locSCHitMatchParams, make_pair(locProjPos, locProjMom));
2477  locMatchProjectionPairs.push_back(locMatchProjectionPair);
2478  }
2479  if(locSCHitMatchParamsVector.empty())
2480  return false;
2481 
2482  locBestMatchParams = Get_BestSCMatchParams(locSCHitMatchParamsVector);
2483 
2484  if(locStartTimeVariance != nullptr)
2485  {
2486  locStartTime = locBestMatchParams->dHitTime - locBestMatchParams->dFlightTime;
2487  *locStartTimeVariance = locBestMatchParams->dFlightTimeVariance + locBestMatchParams->dHitTimeVariance;
2488  //locTimeVariance = 0.3*0.3+locBestMatchParams->dFlightTimeVariance;
2489  }
2490 
2491  if(locBestProjMom != nullptr)
2492  {
2493  for(auto& locMatchProjectionPair : locMatchProjectionPairs)
2494  {
2495  auto locParams = locMatchProjectionPair.first;
2496  if(locParams != locBestMatchParams)
2497  continue;
2498  *locBestProjPos = locMatchProjectionPair.second.first;
2499  *locBestProjMom = locMatchProjectionPair.second.second;
2500  break;
2501  }
2502  }
2503 
2504  return true;
2505 }
2506 
2507 const DTOFPaddleHit* DParticleID::Get_ClosestTOFPaddleHit_Horizontal(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DTOFPaddleHit*>& locTOFPaddleHits, double locInputStartTime, double& locBestDeltaY, double& locBestDistance) const
2508 {
2509  if(extrapolations.size()==0)
2510  return nullptr;
2511 
2512  // Find the track projection to the TOF
2513  DVector3 proj_pos=extrapolations[0].position;
2514  DVector3 proj_mom=extrapolations[0].momentum;
2515  double dz=dTOFGeometry->Get_CenterHorizPlane()-proj_pos.z();
2516  double px=proj_mom.Px();
2517  double py=proj_mom.Py();
2518  double pz=proj_mom.Pz();
2519  double tx=px/pz;
2520  double ty=py/pz;
2521  DVector3 delta(tx*dz,ty*dz,dz);
2522  proj_pos+=delta;
2523  double locFlightTime=extrapolations[0].t;
2524 
2525  const DTOFPaddleHit* locClosestPaddleHit = nullptr;
2526  locBestDistance = 999.0;
2527  locBestDeltaY = 999.0;
2528  for(auto& locTOFPaddleHit : locTOFPaddleHits){
2529  if(locTOFPaddleHit->orientation != 1)
2530  continue; //horizontal orientation is 1
2531 
2532  bool locNorthIsGoodHitFlag = (locTOFPaddleHit->E_north > TOF_E_THRESHOLD);
2533  bool locSouthIsGoodHitFlag = (locTOFPaddleHit->E_south > TOF_E_THRESHOLD);
2534  if(!locNorthIsGoodHitFlag && !locSouthIsGoodHitFlag)
2535  continue; //hit is junk
2536 
2537  // Check that the hit is not out of time with respect to the track
2538 
2539  //Construct spacetime hit: averages times, or if only one end with hit, reports time at center of paddle
2541  double locHitTime = locSpacetimeHit->t;
2542 
2543  // if single-ended paddle, or only one side has a hit: time reported at center: must propagate to track location
2544  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2545  {
2546  //Paddle midpoint
2547  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
2548  if(!locSpacetimeHit->dIsDoubleEndedBar)
2549  locPaddleMidPoint = locNorthIsGoodHitFlag ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
2550 
2551  //correct the time
2552  double locDistanceToMidPoint = locNorthIsGoodHitFlag ? locPaddleMidPoint - proj_pos.X() : proj_pos.X() - locPaddleMidPoint;
2553  int id = 44 + locTOFPaddleHit->bar - 1; //for propation speed
2554  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
2555  }
2556 
2557  //time cut
2558  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
2559  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
2560  continue;
2561 
2562  // Check geometric distance, continue only if better than before
2563  double locDeltaY = dTOFGeometry->bar2y(locTOFPaddleHit->bar) - proj_pos.Y();
2564  double locDeltaX = locTOFPaddleHit->pos - proj_pos.X();
2565  double locDistance = sqrt(locDeltaY*locDeltaY + locDeltaX*locDeltaX);
2566  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2567  {
2568  //no position information along paddle: use delta-y cut only
2569  if(fabs(locDeltaY) > fabs(locBestDistance))
2570  continue;
2571  if(fabs(locDeltaY) > fabs(locBestDeltaY))
2572  continue; //no info on delta-x, so make sure not unfair comparison
2573  locBestDistance = fabs(locDeltaY);
2574  }
2575  else
2576  {
2577  if(locDistance > locBestDistance)
2578  continue;
2579  locBestDistance = locDistance;
2580  }
2581 
2582  locBestDeltaY = locDeltaY;
2583  locClosestPaddleHit = locTOFPaddleHit;
2584  }
2585 
2586  return locClosestPaddleHit;
2587 }
2588 
2589 const DTOFPaddleHit* DParticleID::Get_ClosestTOFPaddleHit_Vertical(const vector<DTrackFitter::Extrapolation_t> &extrapolations, const vector<const DTOFPaddleHit*>& locTOFPaddleHits, double locInputStartTime, double& locBestDeltaX, double& locBestDistance) const
2590 {
2591  if(extrapolations.size()==0)
2592  return nullptr;
2593 
2594  // Find the track projection to the TOF
2595  DVector3 proj_pos=extrapolations[0].position;
2596  DVector3 proj_mom=extrapolations[0].momentum;
2597  double dz=dTOFGeometry->Get_CenterVertPlane()-proj_pos.z();
2598  double px=proj_mom.Px();
2599  double py=proj_mom.Py();
2600  double pz=proj_mom.Pz();
2601  double tx=px/pz;
2602  double ty=py/pz;
2603  DVector3 delta(tx*dz,ty*dz,dz);
2604  proj_pos+=delta;
2605  double locFlightTime=extrapolations[0].t;
2606 
2607  // Evaluate matching solely by physical geometry of the paddle: NOT the distance along the paddle of the hit
2608  const DTOFPaddleHit* locClosestPaddleHit = nullptr;
2609  locBestDistance = 999.0;
2610  locBestDeltaX = 999.0;
2611  for(auto& locTOFPaddleHit : locTOFPaddleHits)
2612  {
2613  if(locTOFPaddleHit->orientation != 0)
2614  continue; //vertical orientation is 0
2615 
2616  bool locNorthIsGoodHitFlag = (locTOFPaddleHit->E_north > TOF_E_THRESHOLD);
2617  bool locSouthIsGoodHitFlag = (locTOFPaddleHit->E_south > TOF_E_THRESHOLD);
2618  if(!locNorthIsGoodHitFlag && !locSouthIsGoodHitFlag)
2619  continue; //hit is junk
2620 
2621  // Check that the hit is not out of time with respect to the track
2622 
2623  //Construct spacetime hit: averages times, or if only one end with hit, reports time at center of paddle
2625  double locHitTime = locSpacetimeHit->t;
2626 
2627  // if single-ended paddle, or only one side has a hit: time reported at center: must propagate to track location
2628  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2629  {
2630  //Paddle midpoint
2631  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
2632  if(!locSpacetimeHit->dIsDoubleEndedBar)
2633  locPaddleMidPoint = locNorthIsGoodHitFlag ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
2634 
2635  //correct the time
2636  double locDistanceToMidPoint = locNorthIsGoodHitFlag ? locPaddleMidPoint - proj_pos.Y() : proj_pos.Y() - locPaddleMidPoint;
2637  int id = locTOFPaddleHit->bar - 1; //for propation speed
2638  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
2639  }
2640 
2641  //time cut
2642  double locDeltaT = locHitTime - locFlightTime - locInputStartTime;
2643  if(fabs(locDeltaT) > OUT_OF_TIME_CUT)
2644  continue;
2645 
2646  // Check geometric distance, continue only if better than before
2647  double locDeltaX = dTOFGeometry->bar2y(locTOFPaddleHit->bar) - proj_pos.X();
2648  double locDeltaY = locTOFPaddleHit->pos - proj_pos.Y();
2649  double locDistance = sqrt(locDeltaY*locDeltaY + locDeltaX*locDeltaX);
2650  if(locNorthIsGoodHitFlag != locSouthIsGoodHitFlag)
2651  {
2652  //no position information along paddle: use delta-y cut only
2653  if(fabs(locDeltaX) > fabs(locBestDistance))
2654  continue;
2655  if(fabs(locDeltaX) > fabs(locBestDeltaX))
2656  continue; //no info on delta-x, so make sure not unfair comparison
2657  locBestDistance = fabs(locDeltaX);
2658  }
2659  else
2660  {
2661  if(locDistance > locBestDistance)
2662  continue;
2663  locBestDistance = locDistance;
2664  }
2665 
2666  locBestDeltaX = locDeltaX;
2667  locClosestPaddleHit = locTOFPaddleHit;
2668  }
2669 
2670  return locClosestPaddleHit;
2671 }
2672 
2673 
2674 /********************************************************** PREDICT HIT ELEMENT **********************************************************/
2675 
2676 bool DParticleID::PredictFCALHit(const DReferenceTrajectory *rt, unsigned int &row, unsigned int &col, DVector3 *intersection) const
2677 {
2678  // Initialize output variables
2679  row=0;
2680  col=0;
2681  if(rt == nullptr)
2682  return false;
2683 
2684  // Find intersection with FCAL plane given by fcal_pos
2685  DVector3 fcal_pos(0,0,dFCALz);
2686  DVector3 norm(0.0, 0.0, 1.0); //normal vector to FCAL plane
2687  DVector3 proj_mom,proj_pos;
2688  if(rt->GetIntersectionWithPlane(fcal_pos, norm, proj_pos, proj_mom, NULL,NULL,NULL,SYS_FCAL) != NOERROR)
2689  return false;
2690 
2691  if (intersection) *intersection=proj_pos;
2692 
2693  double x=proj_pos.x();
2694  double y=proj_pos.y();
2695  row=dFCALGeometry->row(float(y));
2696  col=dFCALGeometry->column(float(x));
2697  return (dFCALGeometry->isBlockActive(row,col));
2698 }
2699 
2700 // Given a reference trajectory from a track, predict which BCAL wedge should
2701 // have a hit
2702 bool DParticleID::PredictBCALWedge(const DReferenceTrajectory *rt, unsigned int &module,unsigned int &sector, DVector3 *intersection) const
2703 {
2704  //initialize output variables
2705  sector=0;
2706  module=0;
2707  if(rt == nullptr)
2708  return false;
2709 
2710  // Find intersection of track with inner radius of BCAL
2711  DVector3 proj_pos;
2712  if (rt->GetIntersectionWithRadius(65.0, proj_pos) != NOERROR)
2713  return false;
2714 
2715  double phi=180./M_PI*proj_pos.Phi();
2716  if (phi<0) phi+=360.;
2717  double slice=phi/7.5;
2718  double mid_slice=round(slice);
2719  module=int(mid_slice)+1;
2720  if(module == 49)
2721  module = 1; //e.g. for phi = 357, above gives module = 49 //phi = 0 is middle of module 1
2722  sector=int(floor((phi-7.5*mid_slice+3.75)/1.875))+1;
2723 
2724  if (intersection) *intersection=proj_pos;
2725 
2726  return true;
2727 }
2728 
2729 // Given a reference trajectory from a track, predict which TOF paddles should
2730 // fire due to the charged particle passing through the TOF planes.
2731 bool DParticleID::PredictTOFPaddles(const DReferenceTrajectory *rt, unsigned int &hbar,unsigned int &vbar, DVector3 *intersection) const
2732 {
2733  // Initialize output variables
2734  vbar=0;
2735  hbar=0;
2736  if(rt == nullptr)
2737  return false;
2738 
2739  // Find intersection with TOF plane given by tof_pos
2740  DVector3 tof_pos(0,0,dTOFGeometry->Get_CenterMidPlane());
2741  DVector3 norm(0.0, 0.0, 1.0); //normal vector to TOF plane
2742  DVector3 proj_mom,proj_pos;
2743  if(rt->GetIntersectionWithPlane(tof_pos, norm, proj_pos, proj_mom, NULL,NULL,NULL,SYS_TOF) != NOERROR)
2744  return false;
2745 
2746  double x=proj_pos.x();
2747  double y=proj_pos.y();
2748 
2749  vbar=dTOFGeometry->y2bar(x);
2750  hbar=dTOFGeometry->y2bar(y);
2751 
2752  if (intersection) *intersection=proj_pos;
2753 
2754  return true;
2755 }
2756 
2757 // Predict the start counter paddle that would match a track whose reference
2758 // trajectory is given by rt.
2759 unsigned int DParticleID::PredictSCSector(const DReferenceTrajectory* rt, DVector3* locOutputProjPos, bool* locProjBarrelRegion, double* locMinDPhi) const
2760 {
2761  if(rt == nullptr)
2762  return 0;
2763  if (! START_EXIST)
2764  return false; // if no Start Counter in geometry
2765 
2766 
2767  DVector3 locProjPos, locProjMom, locPaddleNorm;
2768  double locDeltaPhi, locPathLength, locFlightTime, locFlightTimeVariance;
2769  int locSCPlane;
2770  unsigned int locBestSCSector = PredictSCSector(rt, locDeltaPhi, locProjPos, locProjMom, locPaddleNorm, locPathLength, locFlightTime, locFlightTimeVariance, locSCPlane);
2771  if(locBestSCSector == 0)
2772  return 0;
2773 
2774  if(locProjBarrelRegion != NULL)
2775  *locProjBarrelRegion = (locProjPos.Z() < sc_pos[locBestSCSector - 1][1].Z()); // End of straight section
2776 
2777  if(locMinDPhi != NULL)
2778  *locMinDPhi = locDeltaPhi;
2779 
2780  if(locOutputProjPos != NULL)
2781  *locOutputProjPos = locProjPos;
2782  return locBestSCSector;
2783 }
2784 
2785 // Predict the start counter paddle that would match a track whose reference
2786 // trajectory is given by rt.
2787 unsigned int DParticleID::PredictSCSector(const DReferenceTrajectory* rt, double& locDeltaPhi, DVector3& locProjPos, DVector3& locProjMom, DVector3& locPaddleNorm, double& locPathLength, double& locFlightTime, double& locFlightTimeVariance, int& locSCPlane) const{
2788  if(rt == nullptr)
2789  return 0;
2790  if (rt->Nswim_steps==0) return 0;
2791  // If the starting point of the track is outside the start counter, bail.
2792  if (rt->swim_steps[0].origin.Perp()>sc_pos[0][0].Perp()){
2793  return 0;
2794  }
2795  int index=0,istep=0;
2796  double d_old=1000.,d=1000.,dphi=0.;
2797  for (unsigned int m=0;m<12;m++){
2798  for (int i=0;i<rt->Nswim_steps;i++){
2799  locProjPos=rt->swim_steps[i].origin;
2800  if (!isfinite(locProjPos.Phi())){
2801  return 0;
2802  }
2803  dphi=locProjPos.Phi()-sc_pos[0][0].Phi();
2804  if (dphi<0) dphi+=2.*M_PI;
2805  index=int(floor(dphi/(2.*M_PI/30.)));
2806  if (index>29) index=0;
2807  d=sc_norm[index][m].Dot(locProjPos-sc_pos[index][m]);
2808  if (d*d_old<0){ // break if we cross the current plane
2809  istep=i;
2810  break;
2811  }
2812  d_old=d;
2813  }
2814  // if the z position would be beyond the current segment along z of
2815  // the start counter, move to the next plane
2816  double z=locProjPos.z();
2817  if (z>sc_pos[index][m+1].z()&&m<11){
2818  continue;
2819  }
2820  // allow for a little slop at the end of the nose
2821  else if (z<sc_pos[index][sc_pos[0].size()-1].z()+1.){
2822  // Hone in on intersection with the appropriate segment of the start
2823  // counter
2824  locProjMom=rt->swim_steps[istep].mom;
2825  double ds=-d*locProjMom.Mag()/sc_norm[index][m].Dot(locProjMom);
2826  DVector3 B=rt->swim_steps[istep].B;
2827 
2828  // Current position and momentum
2829  double x=locProjPos.x(),y=locProjPos.y();
2830  double px=locProjMom.x(),py=locProjMom.y(),pz=locProjMom.z();
2831  double p=locProjMom.Mag();
2832 
2833  // Compute convenience terms involving Bx, By, Bz
2834  double k_q=0.003*rt->q;
2835  double ds_over_p=ds/p;
2836  double factor=k_q*(0.25*ds_over_p);
2837  double Bx=B.x(),By=B.y(),Bz=B.z();
2838  double Ax=factor*Bx,Ay=factor*By,Az=factor*Bz;
2839  double Ax2=Ax*Ax,Ay2=Ay*Ay,Az2=Az*Az;
2840  double AxAy=Ax*Ay,AxAz=Ax*Az,AyAz=Ay*Az;
2841  double one_plus_Ax2=1.+Ax2;
2842  double scale=ds_over_p/(one_plus_Ax2+Ay2+Az2);
2843 
2844  // Compute position increments
2845  double dx=scale*(px*one_plus_Ax2+py*(AxAy+Az)+pz*(AxAz-Ay));
2846  double dy=scale*(px*(AxAy-Az)+py*(1.+Ay2)+pz*(AyAz+Ax));
2847  double dz=scale*(px*(AxAz+Ay)+py*(AyAz-Ax)+pz*(1.+Az2));
2848 
2849  locProjPos.SetXYZ(x+dx,y+dy,z+dz);
2850  locProjMom.SetXYZ(px+k_q*(Bz*dy-By*dz),py+k_q*(Bx*dz-Bz*dx),
2851  pz+k_q*(By*dx-Bx*dy));
2852  dphi=locProjPos.Phi()-sc_pos[index][m].Phi();
2853  if (dphi<0) dphi+=2.*M_PI;
2854  locDeltaPhi=dphi;
2855  locPaddleNorm=sc_norm[index][m];
2856  // Flight time
2857  double mass=rt->GetMass();
2858  double one_over_betasq=1.+mass*mass/locProjMom.Mag2();
2859  locFlightTime=rt->swim_steps[istep].t
2860  +ds*sqrt(one_over_betasq)/SPEED_OF_LIGHT;
2861  locPathLength=rt->swim_steps[istep].s+ds;
2862  locFlightTimeVariance=rt->swim_steps[istep].cov_t_t;
2863  locSCPlane=m;
2864 
2865  return index+1;
2866  }
2867 
2868  }
2869  return 0;
2870 }
2871 
2872 // The following routines use the extrapolations from the track
2873 
2874 // Predict the start counter paddle that would match a track whose reference
2875 // trajectory is given by rt.
2876 unsigned int DParticleID::PredictSCSector(const vector<DTrackFitter::Extrapolation_t> &extrapolations, double& locDeltaPhi, DVector3& locProjPos, DVector3& locProjMom, DVector3& locPaddleNorm, double& locPathLength, double& locFlightTime, double& locFlightTimeVariance, int& locSCPlane) const{
2877  if(extrapolations.size()==0)
2878  return 0;
2879  double max_z=sc_pos[0][sc_pos[0].size()-1].z();
2880  double z=extrapolations[0].position.z();
2881  if (z>max_z+1. ){ // allow for some slop at end of nose
2882  return 0;
2883  }
2884 
2885  // Find the track projection to the Start Counter
2886  locProjPos=extrapolations[0].position;
2887  locProjMom=extrapolations[0].momentum;
2888  locFlightTime=extrapolations[0].t;
2889  locPathLength=extrapolations[0].s;
2890  locFlightTimeVariance=0.; // fill this in;
2891 
2892  double dphi_min=1e6;
2893  unsigned int best_index=0;
2894  for (unsigned int index=0;index<30;index++){
2895  for (unsigned int i=1;i<sc_pos[index].size();i++){
2896  if (z>sc_pos[index][i].z() && z<max_z) continue;
2897 
2898  unsigned int prev_i=i-1;
2899  DVector3 sc_pos_at_projz = sc_pos[index][prev_i]
2900  + (locProjPos.Z() - sc_pos[index][prev_i].z())*sc_dir[index][prev_i];
2901  double myDeltaPhi=sc_pos_at_projz.Phi()-locProjPos.Phi();
2902  if (myDeltaPhi<M_PI) myDeltaPhi+=2.*M_PI;
2903  if (myDeltaPhi>M_PI) myDeltaPhi-=2.*M_PI;
2904  if (fabs(myDeltaPhi)<dphi_min){
2905  locDeltaPhi=myDeltaPhi;
2906  dphi_min=fabs(locDeltaPhi);
2907  best_index=index;
2908  locSCPlane=prev_i;
2909  }
2910  break;
2911  }
2912  }
2913  //printf("SC %d\n",best_index+1);
2914 
2915  locPaddleNorm=sc_norm[best_index][locSCPlane];
2916  return best_index+1;
2917 }
2918 
2919 // Predict the start counter paddle that would match a track
2920 unsigned int DParticleID::PredictSCSector(const vector<DTrackFitter::Extrapolation_t> &extrapolations, DVector3* locOutputProjPos, bool* locProjBarrelRegion, double* locMinDPhi) const
2921 {
2922  if(extrapolations.size()==0)
2923  return 0;
2924 
2925  DVector3 locProjPos, locProjMom, locPaddleNorm;
2926  double locDeltaPhi, locPathLength, locFlightTime, locFlightTimeVariance;
2927  int locSCPlane;
2928  unsigned int locBestSCSector = PredictSCSector(extrapolations, locDeltaPhi, locProjPos, locProjMom, locPaddleNorm, locPathLength, locFlightTime, locFlightTimeVariance, locSCPlane);
2929  if(locBestSCSector == 0)
2930  return 0;
2931 
2932  if(locProjBarrelRegion != NULL)
2933  *locProjBarrelRegion = (locProjPos.Z() < sc_pos[locBestSCSector - 1][1].Z()); // End of straight section
2934 
2935  if(locMinDPhi != NULL)
2936  *locMinDPhi = locDeltaPhi;
2937 
2938  if(locOutputProjPos != NULL)
2939  *locOutputProjPos = locProjPos;
2940  return locBestSCSector;
2941 }
2942 
2943 bool DParticleID::PredictFCALHit(const vector<DTrackFitter::Extrapolation_t>&extrapolations, unsigned int &row, unsigned int &col, DVector3 *intersection) const
2944 {
2945  // Initialize output variables
2946  row=0;
2947  col=0;
2948  if(extrapolations.size()==0)
2949  return false;
2950 
2951  // Find intersection with FCAL plane given by fcal_pos
2952  DVector3 fcal_pos(0,0,dFCALz);
2953  DVector3 norm(0.0, 0.0, 1.0); //normal vector to FCAL plane
2954  DVector3 proj_mom=extrapolations[0].momentum;
2955  DVector3 proj_pos=extrapolations[0].position;
2956 
2957  if (intersection) *intersection=proj_pos;
2958 
2959  double x=proj_pos.x();
2960  double y=proj_pos.y();
2961  row=dFCALGeometry->row(float(y));
2962  col=dFCALGeometry->column(float(x));
2963  return (dFCALGeometry->isBlockActive(row,col));
2964 }
2965 
2966 // Given a track, predict which BCAL wedge should have a hit
2967 bool DParticleID::PredictBCALWedge(const vector<DTrackFitter::Extrapolation_t>&extrapolations, unsigned int &module,unsigned int &sector, DVector3 *intersection) const
2968 {
2969  //initialize output variables
2970  sector=0;
2971  module=0;
2972  if(extrapolations.size()==0)
2973  return false;
2974 
2975  // Find intersection of track with inner radius of BCAL
2976  DVector3 proj_pos=extrapolations[0].position;
2977 
2978  double phi=180./M_PI*proj_pos.Phi();
2979  if (phi<0) phi+=360.;
2980  double slice=phi/7.5;
2981  double mid_slice=round(slice);
2982  module=int(mid_slice)+1;
2983  sector=int(floor((phi-7.5*mid_slice+3.75)/1.875))+1;
2984 
2985  if (intersection) *intersection=proj_pos;
2986 
2987  return true;
2988 }
2989 
2990 
2991 // Given a track, predict which TOF paddles should
2992 // fire due to the charged particle passing through the TOF planes.
2993 bool DParticleID::PredictTOFPaddles(const vector<DTrackFitter::Extrapolation_t>&extrapolations, unsigned int &hbar,unsigned int &vbar, DVector3 *intersection) const
2994 {
2995  // Initialize output variables
2996  vbar=0;
2997  hbar=0;
2998  if(extrapolations.size()==0)
2999  return false;
3000 
3001  // Find intersection with TOF plane given by tof_pos
3002  DVector3 tof_pos(0,0,dTOFGeometry->Get_CenterMidPlane());
3003  DVector3 norm(0.0, 0.0, 1.0); //normal vector to TOF plane
3004  DVector3 proj_mom=extrapolations[0].momentum;
3005  DVector3 proj_pos=extrapolations[0].position;
3006 
3007  double x=proj_pos.x();
3008  double y=proj_pos.y();
3009 
3010  vbar=dTOFGeometry->y2bar(x);
3011  hbar=dTOFGeometry->y2bar(y);
3012 
3013  if (intersection) *intersection=proj_pos;
3014 
3015  return true;
3016 }
3017 
3018 /************* Routines to get the start time for the track ************/
3019 
3020 bool DParticleID::Get_StartTime(const vector<DTrackFitter::Extrapolation_t> &extrapolations,
3021  const vector<const DFCALShower*>& FCALShowers,
3022  double& StartTime) const{
3023  if (FCALShowers.size()==0) return false;
3024  if (extrapolations.size()==0) return false;
3025  double StartTimeGuess=StartTime;
3026  DVector3 trackpos=extrapolations[0].position;
3027  double d_min=1e6;
3028  unsigned int best_fcal_match=0;
3029  for (unsigned int i=0;i<FCALShowers.size();i++){
3030  const DFCALShower *fcal_shower=FCALShowers[i];
3031  double d=Distance_ToTrack(fcal_shower,trackpos);
3032  if (d<d_min){
3033  d_min=d;
3034  best_fcal_match=i;
3035  }
3036  }
3037  StartTime=FCALShowers[best_fcal_match]->getTime()-extrapolations[0].t;
3038  if (fabs(StartTime-StartTimeGuess)>OUT_OF_TIME_CUT) return false;
3039 
3040  double p=extrapolations[0].momentum.Mag();
3041  double cut=FCAL_CUT_PAR1+FCAL_CUT_PAR2/p;
3042  if (d_min<cut) return true;
3043 
3044  return false;
3045 }
3046 
3047 bool DParticleID::Get_StartTime(const vector<DTrackFitter::Extrapolation_t> &extrapolations,
3048  const vector<const DSCHit*>& SCHits,
3049  double& StartTime) const{
3050  if (SCHits.size()==0) return false;
3051  if (extrapolations.size()==0) return false;
3052 
3053  double StartTimeGuess=StartTime;
3054  DVector3 trackpos=extrapolations[0].position;
3055  double z=trackpos.z();
3056  double dphi_min=1000.;
3057  unsigned int best_sc_match=0;
3058  for (unsigned int i=0;i<SCHits.size();i++){
3059  unsigned int sc_index=SCHits[i]->sector - 1;
3060  for (unsigned int j=0;j<sc_pos[sc_index].size();j++){
3061  if (z>sc_pos[sc_index][j].z()) continue;
3062  double dphi=trackpos.Phi()-sc_pos[sc_index][j].Phi();
3063  if (dphi<-M_PI) dphi+=2.*M_PI;
3064  if (dphi>M_PI) dphi-=2*M_PI;
3065 
3066  if (fabs(dphi)<dphi_min){
3067  dphi_min=dphi;
3068  best_sc_match=i;
3069  }
3070  }
3071  }
3072  double sc_corrected_time=Get_CorrectedHitTime(SCHits[best_sc_match],trackpos);
3073  StartTime=sc_corrected_time-extrapolations[0].t;
3074  if (fabs(StartTime-StartTimeGuess)>OUT_OF_TIME_CUT) return false;
3075 
3076  double sc_dphi_cut = dSCCutPars_WireBased[0] + dSCCutPars_WireBased[1]*exp(dSCCutPars_WireBased[2]*(trackpos.Z() - dSCCutPars_WireBased[3]));
3077  if (fabs(180.*dphi_min/M_PI) <= sc_dphi_cut) return true;
3078 
3079  return false;
3080 }
3081 
3082 bool DParticleID::Get_StartTime(const vector<DTrackFitter::Extrapolation_t> &extrapolations,
3083  const vector<const DTOFPoint*>& TOFPoints,
3084  double& StartTime) const{
3085  if (TOFPoints.size()==0) return false;
3086  if (extrapolations.size()==0) return false;
3087 
3088  double StartTimeGuess=StartTime;
3089  DVector3 trackpos=extrapolations[0].position;
3090  // Set up cuts
3091  double locMatchCut_2D = exp(-1.0*TOF_CUT_PAR1*extrapolations[0].momentum.Mag() + TOF_CUT_PAR2) + TOF_CUT_PAR3;
3092  double locMatchCut_1D = locMatchCut_2D;
3093 
3094  // loop over TOF points, looking for closest match to track position
3095  double d2_min=1.0e6,dy_at_min=0.,dx_at_min=0.;
3096  unsigned int best_tof_match=0;
3097  for (unsigned int i=0;i<TOFPoints.size();i++){
3098  const DTOFPoint *locTOFPoint = TOFPoints[i];
3099  DVector3 diff=locTOFPoint->pos-trackpos;
3100  double d2=diff.Perp2();
3101  if (d2<d2_min){
3102  d2_min=d2;
3103  dy_at_min=diff.y();
3104  dx_at_min=diff.x();
3105  best_tof_match=i;
3106  }
3107  }
3108  // Get the start time and check that it is consistent with an initial guess
3109  // to within some OUT_OF_TIME_CUT
3110  StartTime=Get_CorrectedHitTime(TOFPoints[best_tof_match],trackpos)
3111  -extrapolations[0].t;
3112  if (fabs(StartTime-StartTimeGuess)>OUT_OF_TIME_CUT) return false;
3113 
3114  // Apply matching criteria
3115  if (TOFPoints[best_tof_match]->Is_XPositionWellDefined()==false){
3116  if (dy_at_min<locMatchCut_1D){
3117  return true;
3118  }
3119  }
3120  else if (TOFPoints[best_tof_match]->Is_YPositionWellDefined()==false){
3121  if (dx_at_min<locMatchCut_1D){
3122  return true;
3123  }
3124  }
3125  else{
3126  if (sqrt(d2_min)<locMatchCut_2D){
3127  return true;
3128  }
3129  }
3130 
3131  return false;
3132 }
3133 
3134 bool DParticleID::Get_StartTime(const vector<DTrackFitter::Extrapolation_t> &extrapolations,
3135  const vector<const DBCALShower*>& locBCALShowers,
3136  double& StartTime) const{
3137  if (locBCALShowers.size()==0) return false;
3138  if (extrapolations.size()==0) return false;
3139 
3140  double StartTimeGuess=StartTime;
3141  double dphi_min=1e6;
3142  double locP=0.,dz=0.;
3143  for (unsigned int i=0;i<locBCALShowers.size();i++){
3144  DVector3 bcalpos(locBCALShowers[i]->x,locBCALShowers[i]->y,
3145  locBCALShowers[i]->z);
3146  double R=bcalpos.Perp();
3147  DVector3 pos,mom;
3148  double s=0,t=0;
3149  if (fitter->ExtrapolateToRadius(R,extrapolations,pos,mom,t,s)){
3150  double dphi=pos.Phi()-bcalpos.Phi();
3151  if (dphi<-M_PI) dphi+=2.*M_PI;
3152  if (dphi>M_PI) dphi-=2.*M_PI;
3153  if (fabs(dphi)<dphi_min){
3154  dphi_min=dphi;
3155  dz=pos.z()-bcalpos.z();
3156  locP=mom.Mag();
3157  StartTime=locBCALShowers[i]->t-t;
3158  }
3159  }
3160  }
3161  // Check that the "start time" is not too far out of time with the rest of
3162  // the event
3163  if (fabs(StartTime-StartTimeGuess)>OUT_OF_TIME_CUT) return false;
3164 
3165  // look for a match in z-position
3166  if(fabs(dz) > BCAL_Z_CUT) return false;
3167 
3168  // .. and in phi
3169  double locDeltaPhi = 180.0*dphi_min/M_PI;
3170  double locPhiCut = BCAL_PHI_CUT_PAR1 + BCAL_PHI_CUT_PAR2*exp(-1.0*BCAL_PHI_CUT_PAR3*locP);
3171  if (fabs(locDeltaPhi)<locPhiCut){
3172  return true;
3173  }
3174 
3175  return false;
3176 }
3177 
3178 
3179 
3180 /****************************************************** MISCELLANEOUS ******************************************************/
3181 
3182 double DParticleID::Calc_BCALFlightTimePCorrelation(const DTrackingData* locTrack, DDetectorMatches* locDetectorMatches) const
3183 {
3184  shared_ptr<const DBCALShowerMatchParams> locBCALShowerMatchParams;
3185  if(!Get_BestBCALMatchParams(locTrack, locDetectorMatches, locBCALShowerMatchParams))
3186  return numeric_limits<double>::quiet_NaN();
3187  double locFlightTimePCorrelation = 0.0; //SET ME!!!
3188  return locFlightTimePCorrelation;
3189 }
3190 
3191 double DParticleID::Calc_FCALFlightTimePCorrelation(const DTrackingData* locTrack, DDetectorMatches* locDetectorMatches) const
3192 {
3193  shared_ptr<const DFCALShowerMatchParams> locFCALShowerMatchParams;
3194  if(!Get_BestFCALMatchParams(locTrack, locDetectorMatches, locFCALShowerMatchParams))
3195  return numeric_limits<double>::quiet_NaN();
3196  double locFlightTimePCorrelation = 0.0; //SET ME!!!
3197  return locFlightTimePCorrelation;
3198 }
3199 
3200 double DParticleID::Calc_TOFFlightTimePCorrelation(const DTrackingData* locTrack, DDetectorMatches* locDetectorMatches) const
3201 {
3202  shared_ptr<const DTOFHitMatchParams> locTOFHitMatchParams;
3203  if(!Get_BestTOFMatchParams(locTrack, locDetectorMatches, locTOFHitMatchParams))
3204  return numeric_limits<double>::quiet_NaN();
3205  double locFlightTimePCorrelation = 0.0; //SET ME!!!
3206  return locFlightTimePCorrelation;
3207 }
3208 
3209 double DParticleID::Calc_SCFlightTimePCorrelation(const DTrackingData* locTrack, const DDetectorMatches* locDetectorMatches) const
3210 {
3211  shared_ptr<const DSCHitMatchParams> locSCHitMatchParams;
3212  if(!Get_BestSCMatchParams(locTrack, locDetectorMatches, locSCHitMatchParams))
3213  return numeric_limits<double>::quiet_NaN();
3214  double locFlightTimePCorrelation = 0.0; //SET ME!!!
3215  return locFlightTimePCorrelation;
3216 }
3217 
3218 double DParticleID::Calc_PropagatedRFTime(const DKinematicData* locKinematicData, const DEventRFBunch* locEventRFBunch) const
3219 {
3220  //Propagate RF time to the track vertex-z
3221  return locEventRFBunch->dTime + (locKinematicData->z() - dTargetZCenter)/SPEED_OF_LIGHT;
3222 }
3223 
3224 double DParticleID::Calc_TimingChiSq(const DChargedTrackHypothesis* locChargedHypo, unsigned int &locNDF, double& locPull) const
3225 {
3226  double locT0=locChargedHypo->t0();
3227  const DTrackTimeBased *locTrack=locChargedHypo->Get_TrackTimeBased();
3228  double locP=locTrack->momentum().Mag();
3229  Particle_t locPID=locChargedHypo->PID();
3230 
3231  double locChiSq_sum=0.;
3232  locNDF = 0;
3233  locPull = 0.0;
3234 
3235  shared_ptr<const DTOFHitMatchParams>locTofParms=locChargedHypo->Get_TOFHitMatchParams();
3236  if (locTofParms!=NULL){
3237  double dt_tof=locTofParms->dHitTime-locTofParms->dFlightTime-locT0;
3238  double vart_tof=GetTimeVariance(SYS_TOF,locPID,locP);
3239  locChiSq_sum+=(dt_tof*dt_tof)/vart_tof;
3240  locNDF++;
3241  }
3242 
3243  shared_ptr<const DBCALShowerMatchParams>locBcalParms=locChargedHypo->Get_BCALShowerMatchParams();
3244  if (locBcalParms!=NULL){
3245  double dt_bcal=locBcalParms->dBCALShower->t-locBcalParms->dFlightTime-locT0;
3246  double vart_bcal=GetTimeVariance(SYS_BCAL,locPID,locP);
3247  locChiSq_sum+=(dt_bcal*dt_bcal)/vart_bcal;
3248  locNDF++;
3249  }
3250 
3251  shared_ptr<const DFCALShowerMatchParams>locFcalParms=locChargedHypo->Get_FCALShowerMatchParams();
3252  if (locFcalParms!=NULL){
3253  double dt_fcal=locFcalParms->dFCALShower->getTime()-locFcalParms->dFlightTime-locT0;
3254  double vart_fcal=GetTimeVariance(SYS_FCAL,locPID,locP);
3255  locChiSq_sum+=(dt_fcal*dt_fcal)/vart_fcal;
3256  locNDF++;
3257  }
3258 
3259  locPull=sqrt(locChiSq_sum);
3260  return locChiSq_sum;
3261 }
3262 
3263 double DParticleID::Calc_TimingChiSq(const DNeutralParticleHypothesis* locNeutralHypo, unsigned int &locNDF, double& locTimingPull) const
3264 {
3265  if((locNeutralHypo->t0_detector() == SYS_NULL) || (locNeutralHypo->t1_detector() == SYS_NULL))
3266  {
3267  // not matched to any hits
3268  locNDF = 0;
3269  locTimingPull = 0.0;
3270  return 0.0;
3271  }
3272 
3273  double locDeltaT = locNeutralHypo->t0() - locNeutralHypo->time();
3274  double locStartTimeError = locNeutralHypo->t0_err();
3275  double locTimeDifferenceVariance = 0.0;
3276  if(locNeutralHypo->errorMatrix() == nullptr)
3277  {
3278  //we are trying to save memory:
3279  //this is pre-kinfit, and the vertex will be fit, so this isn't the final say anyway
3280  //however, in case a pre-kinfit cut is used, we want it to be mostly accurate
3281  //assume error on hit time dominates (over error on vertex positions (i.e. path length)
3282  locTimeDifferenceVariance = (*(locNeutralHypo->Get_NeutralShower()->dCovarianceMatrix))(4, 4);
3283  }
3284  else
3285  locTimeDifferenceVariance = (*locNeutralHypo->errorMatrix())(6, 6) + locStartTimeError*locStartTimeError;
3286 
3287  locTimingPull = locDeltaT/sqrt(locTimeDifferenceVariance);
3288  locNDF = 1;
3289  return locTimingPull*locTimingPull;
3290 }
3291 
3292 void DParticleID::Calc_ChargedPIDFOM(DChargedTrackHypothesis* locChargedTrackHypothesis) const
3293 {
3294  CalcDCdEdxChiSq(locChargedTrackHypothesis);
3295  unsigned int locNDF_Total=locChargedTrackHypothesis->Get_NDF_DCdEdx();
3296  double locChiSq_Total=locChargedTrackHypothesis->Get_ChiSq_DCdEdx();
3297 
3298  // track momentum
3299  const DTrackTimeBased *track=locChargedTrackHypothesis->Get_TrackTimeBased();
3300  double p=track->momentum().Mag();
3301 
3302  // Add dEdx from SC for protons/antiprotons
3303  if (locChargedTrackHypothesis->PID()==Proton
3304  || locChargedTrackHypothesis->PID()==AntiProton){
3305  shared_ptr<const DSCHitMatchParams>scparms=locChargedTrackHypothesis->Get_SCHitMatchParams();
3306  if (scparms!=NULL){
3307  double beta=p/track->energy();
3308  double diff=scparms->dEdx-GetProtondEdxMean_SC(beta);
3309  double sigma=GetProtondEdxSigma_SC(beta);
3310  double chisq=diff*diff/(sigma*sigma);
3311  locChiSq_Total+=chisq;
3312  locNDF_Total+=1;
3313  }
3314  }
3315  // Add E/p for electrons/positrons
3316  if (locChargedTrackHypothesis->PID()==Electron
3317  || locChargedTrackHypothesis->PID()==Positron){
3318  shared_ptr<const DBCALShowerMatchParams>bcalparms=locChargedTrackHypothesis->Get_BCALShowerMatchParams();
3319  shared_ptr<const DFCALShowerMatchParams>fcalparms=locChargedTrackHypothesis->Get_FCALShowerMatchParams();
3320  if (bcalparms!=NULL){
3321  double E_over_p_mean=GetEOverPMean(SYS_BCAL,p);
3322  double diff=bcalparms->dBCALShower->E/p-E_over_p_mean;
3323  double sigma=GetEOverPSigma(SYS_BCAL,p);
3324  double chisq=diff*diff/(sigma*sigma);
3325  locChiSq_Total+=chisq;
3326  locNDF_Total+=1;
3327  }
3328  if (fcalparms!=NULL){
3329  double E_over_p_mean=GetEOverPMean(SYS_FCAL,p);
3330  double diff=fcalparms->dFCALShower->getEnergy()/p-E_over_p_mean;
3331  double sigma=GetEOverPSigma(SYS_FCAL,p);
3332  double chisq=diff*diff/(sigma*sigma);
3333  locChiSq_Total+=chisq;
3334  locNDF_Total+=1;
3335  }
3336  }
3337 
3338  unsigned int locTimingNDF = 0;
3339  double locTimingPull = 0.0;
3340  double locTimingChiSq = Calc_TimingChiSq(locChargedTrackHypothesis, locTimingNDF, locTimingPull);
3341  locChargedTrackHypothesis->Set_ChiSq_Timing(locTimingChiSq, locTimingNDF);
3342 
3343  locNDF_Total += locTimingNDF;
3344  locChiSq_Total += locTimingChiSq;
3345 
3346  double locFOM = (locNDF_Total > 0) ? TMath::Prob(locChiSq_Total, locNDF_Total) : numeric_limits<double>::quiet_NaN();
3347  locChargedTrackHypothesis->Set_ChiSq_Overall(locChiSq_Total, locNDF_Total, locFOM);
3348 }
3349 
3350 unsigned int DParticleID::Get_CDCRingBitPattern(vector<const DCDCTrackHit*>& locCDCTrackHits) const
3351 {
3352  unsigned int locBitPattern = 0;
3353  for(size_t loc_i = 0; loc_i < locCDCTrackHits.size(); ++loc_i)
3354  {
3355  //bit-shift to get bit for this ring, then bitwise-or
3356  unsigned int locBitShift = locCDCTrackHits[loc_i]->wire->ring - 1;
3357  unsigned int locBit = (1 << locBitShift); //if ring # is 1, shift 1 by 0
3358  locBitPattern |= locBit;
3359  }
3360  return locBitPattern;
3361 }
3362 
3363 unsigned int DParticleID::Get_FDCPlaneBitPattern(vector<const DFDCPseudo*>& locFDCPseudos) const
3364 {
3365  unsigned int locBitPattern = 0;
3366  for(size_t loc_i = 0; loc_i < locFDCPseudos.size(); ++loc_i)
3367  {
3368  //bit-shift to get bit for this ring, then bitwise-or
3369  unsigned int locBitShift = locFDCPseudos[loc_i]->wire->layer - 1;
3370  unsigned int locBit = (1 << locBitShift); //if ring # is 1, shift 1 by 0
3371  locBitPattern |= locBit;
3372  }
3373  return locBitPattern;
3374 }
3375 
3376 void DParticleID::Get_CDCRings(unsigned int locBitPattern, set<int>& locCDCRings) const
3377 {
3378  locCDCRings.clear();
3379  for(unsigned int locRing = 1; locRing <= 28; ++locRing)
3380  {
3381  unsigned int locBitShift = locRing - 1;
3382  unsigned int locBit = (1 << locBitShift); //if ring # is 1, shift 1 by 0
3383  if((locBitPattern & locBit) != 0)
3384  locCDCRings.insert(locRing);
3385  }
3386 }
3387 
3388 void DParticleID::Get_FDCPlanes(unsigned int locBitPattern, set<int>& locFDCPlanes) const
3389 {
3390  locFDCPlanes.clear();
3391  for(unsigned int locPlane = 1; locPlane <= 24; ++locPlane)
3392  {
3393  unsigned int locBitShift = locPlane - 1;
3394  unsigned int locBit = (1 << locBitShift); //if ring # is 1, shift 1 by 0
3395  if((locBitPattern & locBit) != 0)
3396  locFDCPlanes.insert(locPlane);
3397  }
3398 }
3399 
3400 void DParticleID::Get_CDCNumHitRingsPerSuperlayer(int locBitPattern, map<int, int>& locNumHitRingsPerSuperlayer) const
3401 {
3402  set<int> locCDCRings;
3403  Get_CDCRings(locBitPattern, locCDCRings);
3404  Get_CDCNumHitRingsPerSuperlayer(locCDCRings, locNumHitRingsPerSuperlayer);
3405 }
3406 
3407 void DParticleID::Get_CDCNumHitRingsPerSuperlayer(const set<int>& locCDCRings, map<int, int>& locNumHitRingsPerSuperlayer) const
3408 {
3409  locNumHitRingsPerSuperlayer.clear();
3410  for(int locCDCSuperlayer = 1; locCDCSuperlayer <= 7; ++locCDCSuperlayer)
3411  locNumHitRingsPerSuperlayer[locCDCSuperlayer] = 0;
3412 
3413  set<int>::const_iterator locIterator = locCDCRings.begin();
3414  for(; locIterator != locCDCRings.end(); ++locIterator)
3415  {
3416  int locCDCSuperlayer = ((*locIterator) - 1)/4 + 1;
3417  ++locNumHitRingsPerSuperlayer[locCDCSuperlayer];
3418  }
3419 }
3420 
3421 void DParticleID::Get_FDCNumHitPlanesPerPackage(int locBitPattern, map<int, int>& locNumHitPlanesPerPackage) const
3422 {
3423  set<int> locFDCPlanes;
3424  Get_FDCPlanes(locBitPattern, locFDCPlanes);
3425  Get_FDCNumHitPlanesPerPackage(locFDCPlanes, locNumHitPlanesPerPackage);
3426 }
3427 
3428 void DParticleID::Get_FDCNumHitPlanesPerPackage(const set<int>& locFDCPlanes, map<int, int>& locNumHitPlanesPerPackage) const
3429 {
3430  locNumHitPlanesPerPackage.clear();
3431  for(int locFDCPackage = 1; locFDCPackage <= 4; ++locFDCPackage)
3432  locNumHitPlanesPerPackage[locFDCPackage] = 0;
3433 
3434  set<int>::const_iterator locIterator = locFDCPlanes.begin();
3435  for(; locIterator != locFDCPlanes.end(); ++locIterator)
3436  {
3437  int locFDCPackage = ((*locIterator) - 1)/6 + 1;
3438 // map<int, int>::iterator locMapIterator = locNumHitPlanesPerPackage.find(locFDCPackage);
3439  ++locNumHitPlanesPerPackage[locFDCPackage];
3440  }
3441 }
3442 
3443 /**** Routines to make corrections to energy deposition and time using track
3444  information ********/
3445 
3447  const DVector3 &locProjPos) const {
3448  //If position was not well-defined, correct time due to propagation along paddle
3449  //This value was reported at the midpoint of the paddle
3450  double locHitTime = locTOFPoint->t;
3451  if(!locTOFPoint->Is_XPositionWellDefined())
3452  {
3453  //Is unmatched horizontal paddle with only one hit above threshold
3454  bool locNorthIsGoodHit = (locTOFPoint->dHorizontalBarStatus == 1); //+x
3455  int locBar = locTOFPoint->dHorizontalBar;
3456  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
3457 
3458  //Paddle midpoint
3459  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
3460  if(!locIsDoubleEndedBar)
3461  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
3462 
3463  //delta_x = delta_x_actual - delta_x_mid
3464  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
3465  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
3466  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.X() : locProjPos.X() - locPaddleMidPoint;
3467 
3468  //Time
3469  int id = 44 + locBar - 1;
3470  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
3471  //locHitTimeVariance = //UPDATE ME!!!
3472  }
3473  else if(!locTOFPoint->Is_YPositionWellDefined())
3474  {
3475  //Is unmatched vertical paddle with only one hit above threshold
3476  bool locNorthIsGoodHit = (locTOFPoint->dVerticalBarStatus == 1); //+y
3477  int locBar = locTOFPoint->dVerticalBar;
3478  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
3479 
3480  //Paddle midpoint
3481  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
3482  if(!locIsDoubleEndedBar)
3483  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
3484 
3485  //delta_x = delta_x_actual - delta_x_mid
3486  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
3487  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
3488  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.Y() : locProjPos.Y() - locPaddleMidPoint;
3489 
3490  //Time
3491  int id = locBar - 1;
3492  locHitTime -= locDistanceToMidPoint/propagation_speed[id];
3493  //locHitTimeVariance = //UPDATE ME!!!
3494  }
3495  return locHitTime;
3496 }
3497 
3499  const DVector3 &locProjPos) const{
3500  double locHitEnergy = locTOFPoint->dE;
3501  //If position was not well-defined, correct deposited energy due to attenuation.
3502  //This value was reported at the midpoint of the paddle
3503 
3504  if(!locTOFPoint->Is_XPositionWellDefined())
3505  {
3506  //Is unmatched horizontal paddle with only one hit above threshold
3507  bool locNorthIsGoodHit = (locTOFPoint->dHorizontalBarStatus == 1); //+x
3508  int locBar = locTOFPoint->dHorizontalBar;
3509  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
3510 
3511  //Paddle midpoint
3512  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
3513  if(!locIsDoubleEndedBar)
3514  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
3515 
3516  //delta_x = delta_x_actual - delta_x_mid
3517  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
3518  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
3519  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.X() : locProjPos.X() - locPaddleMidPoint;
3520 
3521  //Energy
3522  locHitEnergy *= exp(locDistanceToMidPoint/TOF_ATTEN_LENGTH);
3523  }
3524  else if(!locTOFPoint->Is_YPositionWellDefined())
3525  {
3526  //Is unmatched vertical paddle with only one hit above threshold
3527  bool locNorthIsGoodHit = (locTOFPoint->dVerticalBarStatus == 1); //+y
3528  int locBar = locTOFPoint->dVerticalBar;
3529  bool locIsDoubleEndedBar = ((locBar < dTOFGeometry->Get_FirstShortBar()) || (locBar > dTOFGeometry->Get_LastShortBar()));
3530 
3531  //Paddle midpoint
3532  double locPaddleMidPoint = 0.0; //is 0 except when is single-ended bar (22 & 23)
3533  if(!locIsDoubleEndedBar)
3534  locPaddleMidPoint = locNorthIsGoodHit ? ONESIDED_PADDLE_MIDPOINT_MAG : -1.0*ONESIDED_PADDLE_MIDPOINT_MAG;
3535 
3536  //delta_x = delta_x_actual - delta_x_mid
3537  //if end.x > 0: delta_x = (end.x - track.x) - (end.x - mid.x) = mid.x - track.x //if track.x > mid.x, delta_x < 0: decrease energy & increase time
3538  //if end.x < 0: delta_x = (track.x - end.x) - (mid.x - end.x) = track.x - mid.x //if track.x > mid.x, delta_x > 0: increase energy & decrease time
3539  double locDistanceToMidPoint = locNorthIsGoodHit ? locPaddleMidPoint - locProjPos.Y() : locProjPos.Y() - locPaddleMidPoint;
3540 
3541  //Energy
3542  locHitEnergy *= exp(locDistanceToMidPoint/TOF_ATTEN_LENGTH);
3543  }
3544 
3545  return locHitEnergy;
3546 }
3547 
3548 // Correct the hit energy in the start counter paddle for attenuation using
3549 // the projected track position in the start counter volume
3551  const DVector3 &locProjPos) const {
3552  // Start Counter geometry in hall coordinates, obtained from xml file
3553  unsigned int sc_index = locSCHit->sector - 1;
3554  double sc_pos_soss = sc_pos[sc_index][0].z(); // Start of straight section
3555  double sc_pos_eoss = sc_pos[sc_index][1].z(); // End of straight section
3556  double sc_pos_eobs = sc_pos[sc_index][sc_pos[sc_index].size() - 2].z(); // End of bend section
3557 
3558  // Grab the pulse integral
3559  double locCorrectedHitEnergy = locSCHit->dE;
3560 
3561  // Check to see if hit occured in the straight section
3562  if (locProjPos.Z() <= sc_pos_eoss)
3563  {
3564  // Calculate hit distance along scintillator relative to upstream end
3565  double L = locProjPos.Z() - sc_pos_soss;
3566 
3567  // Apply attenuation correction
3568  locCorrectedHitEnergy *= 1.0/(exp(sc_attn_B[SC_STRAIGHT_ATTN][sc_index]*L));
3569  }
3570  else if(locProjPos.Z() > sc_pos_eoss && locProjPos.Z() <= sc_pos_eobs) //check if in bend section: if so, apply corrections
3571  {
3572  // Calculate the hit position relative to the upstream end
3573  double L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
3574 
3575  // Apply attenuation correction
3576  locCorrectedHitEnergy *= (sc_attn_A[SC_STRAIGHT_ATTN][sc_index] /
3577  ((sc_attn_A[SC_BENDNOSE_ATTN][sc_index]*
3578  exp(sc_attn_B[SC_BENDNOSE_ATTN][sc_index]*L))
3579  + sc_attn_C[SC_BENDNOSE_ATTN][sc_index]));
3580  }
3581  else // nose section: apply corrections
3582  {
3583  // Calculate the hit position relative to the upstream end
3584  double L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
3585 
3586  // Apply attenuation correction
3587  locCorrectedHitEnergy *= (sc_attn_A[SC_STRAIGHT_ATTN][sc_index] /
3588  ((sc_attn_A[SC_BENDNOSE_ATTN][sc_index]*
3589  exp(sc_attn_B[SC_BENDNOSE_ATTN][sc_index]*L))
3590  + sc_attn_C[SC_BENDNOSE_ATTN][sc_index]));
3591  }
3592  return locCorrectedHitEnergy;
3593 }
3594 
3595 // Apply propagation time correction to the start counter hit using the
3596 // projected track position
3598  const DVector3 &locProjPos) const {
3599  // Start Counter geometry in hall coordinates, obtained from xml file
3600  unsigned int sc_index = locSCHit->sector - 1;
3601  double sc_pos_soss = sc_pos[sc_index][0].z(); // Start of straight section
3602  double sc_pos_eoss = sc_pos[sc_index][1].z(); // End of straight section
3603  double sc_pos_eobs = sc_pos[sc_index][sc_pos[sc_index].size() - 2].z(); // End of bend section
3604 
3605  // Grab the time-walk corrected start counter hit time
3606  double locCorrectedHitTime = locSCHit->t;
3607 
3608  // Check to see if hit occured in the straight section
3609  if (locProjPos.Z() <= sc_pos_eoss)
3610  {
3611  // Calculate hit distance along scintillator relative to upstream end
3612  double L = locProjPos.Z() - sc_pos_soss;
3613  // Apply propagation time correction
3614  locCorrectedHitTime -= L*sc_pt_slope[SC_STRAIGHT][sc_index] + sc_pt_yint[SC_STRAIGHT][sc_index];
3615  }
3616  else if(locProjPos.Z() > sc_pos_eoss && locProjPos.Z() <= sc_pos_eobs) //check if in bend section: if so, apply corrections
3617  {
3618  // Calculate the hit position relative to the upstream end
3619  double L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
3620  // Apply propagation time correction
3621  locCorrectedHitTime -= L*sc_pt_slope[SC_BEND][sc_index] + sc_pt_yint[SC_BEND][sc_index];
3622  }
3623  else // nose section: apply corrections
3624  {
3625  // Calculate the hit position relative to the upstream end
3626  double L = (locProjPos.Z() - sc_pos_eoss)*sc_angle_cor + (sc_pos_eoss - sc_pos_soss);
3627  // Apply propagation time correction
3628  locCorrectedHitTime -= L*sc_pt_slope[SC_NOSE][sc_index] + sc_pt_yint[SC_NOSE][sc_index];
3629  }
3630  return locCorrectedHitTime;
3631 }
3632 
3634  return dDIRCLut;
3635 }
virtual jerror_t CalcDCdEdxChiSq(DChargedTrackHypothesis *locChargedTrackHypothesis) const =0
double BCAL_PHI_CUT_PAR1
Definition: DParticleID.h:243
DetectorSystem_t t1_detector(void) const
#define F(x, y, z)
static bool DParticleID_dedx_amp_cmp(DParticleID::dedx_t a, DParticleID::dedx_t b)
Definition: DParticleID.cc:19
Definition: track.h:16
unsigned int PredictSCSector(const DReferenceTrajectory *rt, DVector3 *locOutputProjPos=nullptr, bool *locProjBarrelRegion=nullptr, double *locMinDPhi=nullptr) const
vector< double > sc_pt_slope[3]
Definition: DParticleID.h:287
struct VolMat FindMat(double *x)
Definition: DRootGeom.cc:518
DApplication * dapp
void Set_ChiSq_Overall(double locChiSq, unsigned int locNDF, double locFOM)
unsigned int Get_FDCPlaneBitPattern(vector< const DFDCPseudo * > &locFDCPseudos) const
void Get_FDCPlanes(unsigned int locBitPattern, set< int > &locFDCPlanes) const
bool ExtrapolateToRadius(double R, const vector< Extrapolation_t > &extraps, DVector3 &pos, DVector3 &mom, double &t, double &s) const
float Get_CenterVertPlane() const
Definition: DTOFGeometry.h:46
void Get_CDCRings(unsigned int locBitPattern, set< int > &locCDCRings) const
int dHorizontalBar
Definition: DTOFPoint.h:38
vector< double > sc_attn_A[2]
Definition: DParticleID.h:293
const DTOFPaddleHit * Get_ClosestTOFPaddleHit_Horizontal(const DReferenceTrajectory *locReferenceTrajectory, const vector< const DTOFPaddleHit * > &locTOFPaddleHits, double locInputStartTime, double &locBestDeltaY, double &locBestDistance) const
#define SPEED_OF_LIGHT
double BCAL_PHI_CUT_PAR2
Definition: DParticleID.h:243
bool Get_TOFMatchParams(const DTrackingData *locTrack, vector< shared_ptr< const DTOFHitMatchParams > > &locMatchParams) const
vector< double > SC_BOUNDARY2
Definition: DParticleID.h:255
vector< double > SC_SECTION2_P0
Definition: DParticleID.h:257
#define X0
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
float dE
Definition: DTOFPoint.h:35
double z(void) const
double TOF_CUT_PAR4
Definition: DParticleID.h:245
bool Get_SCMatchParams(const DTrackingData *locTrack, vector< shared_ptr< const DSCHitMatchParams > > &locMatchParams) const
TVector3 DVector3
Definition: DVector3.h:14
Definition: GlueX.h:16
#define M_TWO_PI
Definition: DParticleID.cc:12
double energy(void) const
vector< double > dSCCutPars_TimeBased
Definition: DParticleID.h:246
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
double OUT_OF_TIME_CUT
Definition: DParticleID.h:250
double dTargetZCenter
Definition: DParticleID.h:313
virtual double GetProtondEdxSigma_SC(double locBeta) const =0
double sc_angle_cor
Definition: DParticleID.h:272
int dHorizontalBarStatus
Definition: DTOFPoint.h:43
double dFCALz
Definition: DParticleID.h:298
#define c
double getTime() const
Definition: DFCALShower.h:161
vector< double > SC_BOUNDARY1
Definition: DParticleID.h:255
#define y
bool Get_FCALMatchParams(const DTrackingData *locTrack, vector< shared_ptr< const DFCALShowerMatchParams > > &locMatchParams) const
DVector3 GetLastDOCAPoint(void) const
static bool DParticleID_hypothesis_cmp(const DTrackTimeBased *a, const DTrackTimeBased *b)
Definition: DParticleID.cc:24
vector< double > CDC_GAIN_DOCA_PARS
Definition: DParticleID.h:252
bool ProjectTo_SC(const DReferenceTrajectory *rt, unsigned int locSCSector, double &locDeltaPhi, DVector3 &locProjPos, DVector3 &locProjMom, DVector3 &locPaddleNorm, double &locPathLength, double &locFlightTime, double &locFlightTimeVariance, int &locSCPlane) const
const DTrackTimeBased * Get_TrackTimeBased(void) const
bool Cut_MatchDIRC(const vector< DTrackFitter::Extrapolation_t > &extrapolations, const vector< const DDIRCPmtHit * > locDIRCHits, double locInputStartTime, Particle_t locPID, shared_ptr< DDIRCMatchParams > &locDIRCMatchParams, const vector< const DDIRCTruthBarHit * > locDIRCBarHits, map< shared_ptr< const DDIRCMatchParams >, vector< const DDIRCPmtHit * > > &locDIRCTrackMatchParams, DVector3 *locOutputProjPos=nullptr, DVector3 *locOutputProjMom=nullptr) const
bool Is_XPositionWellDefined(void) const
Definition: DTOFPoint.h:46
double Calc_SCFlightTimePCorrelation(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches) const
bool Get_DIRCMatchParams(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches, shared_ptr< const DDIRCMatchParams > &locBestMatchParams) const
double CalcdXHit(const DVector3 &mom, const DVector3 &pos, const DCoordinateSystem *wire) const
Definition: DParticleID.cc:568
vector< double > SC_SECTION4_P0
Definition: DParticleID.h:259
double Calc_PropagatedRFTime(const DKinematicData *locKinematicData, const DEventRFBunch *locEventRFBunch) const
bool GetFCALZ(double &z_fcal) const
z-location of front face of CCAL in cm
Definition: DGeometry.cc:1718
static char index(char c)
Definition: base64.cpp:115
oid_t candidateid
id of DTrackCandidate corresponding to this track
float Get_ShortBarLength() const
Definition: DTOFGeometry.h:42
vector< double > SC_SECTION3_P0
Definition: DParticleID.h:258
const DNeutralShower * Get_NeutralShower(void) const
#define X(str)
Definition: hddm-c.cpp:83
Definition: GlueX.h:17
double dRhoZoverA_CDC
Definition: DParticleID.h:237
Definition: GlueX.h:19
shared_ptr< const DTOFHitMatchParams > Get_TOFHitMatchParams(void) const
bool Get_StartTime(const vector< DTrackFitter::Extrapolation_t > &extrapolations, const vector< const DFCALShower * > &FCALShowers, double &StartTime) const
int sector
Definition: DSCHit.h:18
double CDC_TIME_CUT_FOR_DEDX
Definition: DParticleID.h:311
bool PredictFCALHit(const DReferenceTrajectory *rt, unsigned int &row, unsigned int &col, DVector3 *intersection=nullptr) const
int Get_FirstShortBar() const
Definition: DTOFGeometry.h:37
tof_spacetimehit_t * Build_TOFSpacetimeHit_Horizontal(const DTOFPaddleHit *locTOFHit)
unsigned int Get_NDF_DCdEdx(void) const
double dKRhoZoverA_FDC
Definition: DParticleID.h:235
double dLnI_CDC
Definition: DParticleID.h:237
void Get_FDCNumHitPlanesPerPackage(int locBitPattern, map< int, int > &locNumHitPlanesPerPackage) const
double Get_CorrectedHitEnergy(const DTOFPoint *locTOFPoint, const DVector3 &locProjPos) const
double time(void) const
bool Get_BestTOFMatchParams(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches, shared_ptr< const DTOFHitMatchParams > &locBestMatchParams) const
void Calc_ChargedPIDFOM(DChargedTrackHypothesis *locChargedTrackHypothesis) const
DTOFPoint_factory * dTOFPointFactory
Definition: DParticleID.h:317
bool Get_BestSCMatchParams(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches, shared_ptr< const DSCHitMatchParams > &locBestMatchParams) const
Definition: DSCHit.h:14
double dKRhoZoverA_Scint
Definition: DParticleID.h:236
bool PredictTOFPaddles(const DReferenceTrajectory *rt, unsigned int &hbar, unsigned int &vbar, DVector3 *intersection=nullptr) const
double Calc_TOFFlightTimePCorrelation(const DTrackingData *locTrack, DDetectorMatches *locDetectorMatches) const
double dKRhoZoverA_CDC
Definition: DParticleID.h:237
void Get_CDCNumHitRingsPerSuperlayer(int locBitPattern, map< int, int > &locNumHitRingsPerSuperlayer) const
DRootGeom * GetRootGeom(unsigned int run_number)
TEllipse * e
int Get_LastShortBar() const
Definition: DTOFGeometry.h:38
double dRhoZoverA_FDC
Definition: DParticleID.h:235
double FCAL_CUT_PAR2
Definition: DParticleID.h:244
unsigned int Get_CDCRingBitPattern(vector< const DCDCTrackHit * > &locCDCTrackHits) const
double Calc_FCALFlightTimePCorrelation(const DTrackingData *locTrack, DDetectorMatches *locDetectorMatches) const
DVector3 pos
Definition: DTOFPoint.h:33
vector< double > SC_SECTION2_P1
Definition: DParticleID.h:257
double Calc_BCALFlightTimePCorrelation(const DTrackingData *locTrack, DDetectorMatches *locDetectorMatches) const
TLatex tx
const DDIRCLut * dDIRCLut
Definition: DParticleID.h:320
Definition: GlueX.h:20
vector< double > SC_SECTION1_P0
Definition: DParticleID.h:256
vector< double > sc_attn_C[2]
Definition: DParticleID.h:295
Definition: GlueX.h:18
vector< double > sc_pt_yint[3]
Definition: DParticleID.h:286
bool Get_BestFCALMatchParams(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches, shared_ptr< const DFCALShowerMatchParams > &locBestMatchParams) const
double DistToRTwithTime(DVector3 hit, double *s=NULL, double *t=NULL, double *var_t=NULL, DetectorSystem_t detector=SYS_NULL) const
bool Get_BestBCALMatchParams(const DTrackingData *locTrack, const DDetectorMatches *locDetectorMatches, shared_ptr< const DBCALShowerMatchParams > &locBestMatchParams) const
double GetMostProbabledEdx_DC(double p, double mass, double dx, bool locIsCDCFlag) const
Definition: DParticleID.cc:657
float bar2y(int bar, int end=0) const
convert bar number to the position of the center of the bar in local coordinations ...
Definition: DTOFGeometry.cc:53
DGeometry * GetDGeometry(unsigned int run_number)
Definition: GlueX.h:22
float Get_CenterMidPlane() const
Definition: DTOFGeometry.h:48
vector< double > dSCCutPars_WireBased
Definition: DParticleID.h:246
double dSCdphi
Definition: DParticleID.h:276
shared_ptr< TMatrixFSym > dCovarianceMatrix
const DTOFPaddleHit * Get_ClosestTOFPaddleHit_Vertical(const DReferenceTrajectory *locReferenceTrajectory, const vector< const DTOFPaddleHit * > &locTOFPaddleHits, double locInputStartTime, double &locBestDeltaX, double &locBestDistance) const
#define _DBG_
Definition: HDEVIO.h:12
double BCAL_PHI_CUT_PAR3
Definition: DParticleID.h:243
float Get_LongBarLength() const
Definition: DTOFGeometry.h:40
double dRhoZoverA_Scint
Definition: DParticleID.h:236
float Get_CenterHorizPlane() const
Definition: DTOFGeometry.h:47
Double_t sigma[NCHANNELS]
Definition: st_tw_resols.C:37
double GetMass(void) const
virtual double GetProtondEdxMean_SC(double locBeta) const =0
vector< double > SC_BOUNDARY3
Definition: DParticleID.h:255
double TOF_ATTEN_LENGTH
Definition: DParticleID.h:307
jerror_t GroupTracks(vector< const DTrackTimeBased * > &tracks, vector< vector< const DTrackTimeBased * > > &grouped_tracks) const
Definition: DParticleID.cc:310
bool Get_ClosestToTrack(const DReferenceTrajectory *rt, const vector< const DBCALShower * > &locBCALShowers, bool locCutFlag, double &locStartTime, shared_ptr< const DBCALShowerMatchParams > &locBestMatchParams, double *locStartTimeVariance=nullptr, DVector3 *locBestProjPos=nullptr, DVector3 *locBestProjMom=nullptr) const
Double_t T0(Double_t x)
Definition: chebyshev_fit.C:3
vector< double > SC_SECTION1_P1
Definition: DParticleID.h:256
bool Get_DIRCMatchParams(const DTrackingData *locTrack, shared_ptr< const DDIRCMatchParams > &locMatchParams) const
double GetdEdxSigma_DC(double num_hits, double p, double mass, double mean_path_length, bool locIsCDCFlag) const
Definition: DParticleID.cc:679
shared_ptr< const DSCHitMatchParams > Get_SCHitMatchParams(void) const
TH1D * py[NCHANNELS]
jerror_t CalcdEdxHit(const DVector3 &mom, const DVector3 &pos, const DCDCTrackHit *hit, dedx_t &dedx) const
Definition: DParticleID.cc:495
tof_spacetimehit_t * Build_TOFSpacetimeHit_Vertical(const DTOFPaddleHit *locTOFHit)
double FCAL_CUT_PAR1
Definition: DParticleID.h:244
bool Cut_MatchDistance(const DReferenceTrajectory *rt, const DBCALShower *locBCALShower, double locInputStartTime, shared_ptr< DBCALShowerMatchParams > &locShowerMatchParams, DVector3 *locOutputProjPos=nullptr, DVector3 *locOutputProjMom=nullptr) const
const DTOFGeometry * dTOFGeometry
Definition: DParticleID.h:303
int column(int channel) const
Definition: DFCALGeometry.h:65
jerror_t GetIntersectionWithRadius(double R, DVector3 &mypos, double *s=NULL, double *t=NULL, DVector3 *dir=NULL) const
double sqrt(double)
double Calc_TimingChiSq(const DChargedTrackHypothesis *locChargedHypo, unsigned int &locNDF, double &locTimingPull) const
shared_ptr< const DFCALShowerMatchParams > Get_FCALShowerMatchParams(void) const
const DDIRCLut * Get_DIRCLut() const
double Get_ChiSq_DCdEdx(void) const
double sin(double)
int dVerticalBar
Definition: DTOFPoint.h:39
jerror_t CalcDCdEdx(const DTrackTimeBased *locTrackTimeBased, double &locdEdx_FDC, double &locdx_FDC, double &locdEdx_CDC, double &locdEdx_CDC_amp, double &locdx_CDC, double &locdx_CDC_amp, unsigned int &locNumHitsUsedFordEdx_FDC, unsigned int &locNumHitsUsedFordEdx_CDC) const
Definition: DParticleID.cc:425
bool Get_BCALMatchParams(const DTrackingData *locTrack, vector< shared_ptr< const DBCALShowerMatchParams > > &locMatchParams) const
jerror_t GetDCdEdxHits(const DTrackTimeBased *track, vector< dedx_t > &dEdxHits_CDC, vector< dedx_t > &dEdxHits_FDC) const
Definition: DParticleID.cc:343
virtual double GetTimeVariance(DetectorSystem_t detector, Particle_t particle, double p) const =0
double TOF_CUT_PAR3
Definition: DParticleID.h:245
double TOF_E_THRESHOLD
Definition: DParticleID.h:308
const DVector3 & momentum(void) const
bool CalcLUT(TVector3 locProjPos, TVector3 locProjMom, const vector< const DDIRCPmtHit * > locDIRCHits, double locFlightTime, Particle_t locPID, shared_ptr< DDIRCMatchParams > &locDIRCMatchParams, const vector< const DDIRCTruthBarHit * > locDIRCBarHits, map< shared_ptr< const DDIRCMatchParams >, vector< const DDIRCPmtHit * > > &locDIRCTrackMatchParams) const
Definition: DDIRCLut.cc:122
const DTrackFitter * fitter
Definition: DParticleID.h:316
double TOF_CUT_PAR2
Definition: DParticleID.h:245
double C_EFFECTIVE
Definition: DParticleID.h:248
double FCAL_CUT_PAR3
Definition: DParticleID.h:244
double dSCphi0
Definition: DParticleID.h:277
vector< vector< DVector3 > > sc_pos
Definition: DParticleID.h:274
float dE
Definition: DSCHit.h:19
vector< double > sc_attn_B[2]
Definition: DParticleID.h:294
double BCAL_Z_CUT
Definition: DParticleID.h:243
vector< vector< DVector3 > > sc_norm
Definition: DParticleID.h:275
vector< double > SC_SECTION3_P1
Definition: DParticleID.h:258
virtual double GetEOverPSigma(DetectorSystem_t detector, double p) const =0
double Get_CorrectedHitTime(const DTOFPoint *locTOFPoint, const DVector3 &locProjPos) const
float t
Definition: DSCHit.h:20
shared_ptr< const DBCALShowerMatchParams > Get_BCALShowerMatchParams(void) const
DetectorSystem_t t0_detector(void) const
double dHalfPaddle_OneSided
Definition: DParticleID.h:306
int row(int channel) const
Definition: DFCALGeometry.h:64
shared_ptr< const TMatrixFSym > errorMatrix(void) const
map< DetectorSystem_t, vector< DTrackFitter::Extrapolation_t > > extrapolations
float t
Definition: DTOFPoint.h:34
void GetScintMPdEandSigma(double p, double M, double x, double &most_prob_dE, double &sigma_dE) const
Definition: DParticleID.cc:622
const DFCALGeometry * dFCALGeometry
Definition: DParticleID.h:299
double ATTEN_LENGTH
Definition: DParticleID.h:249
int y2bar(double y) const
&gt; convert local position y to bar number (where y is the position pe...
Definition: DTOFGeometry.cc:68
const DTrackFinder * finder
Definition: DParticleID.h:315
double dLnI_Scint
Definition: DParticleID.h:236
bool Distance_ToTrack(const DReferenceTrajectory *rt, const DFCALShower *locFCALShower, double locInputStartTime, shared_ptr< DFCALShowerMatchParams > &locShowerMatchParams, DVector3 *locOutputProjPos=nullptr, DVector3 *locOutputProjMom=nullptr) const
Definition: DParticleID.cc:737
double dLnI_FDC
Definition: DParticleID.h:235
bool isBlockActive(int row, int column) const
vector< double > SC_SECTION4_P1
Definition: DParticleID.h:259
bool PredictBCALWedge(const DReferenceTrajectory *rt, unsigned int &module, unsigned int &sector, DVector3 *intersection=nullptr) const
DVector3 getPosition() const
Definition: DFCALShower.h:151
static bool DParticleID_dedx_cmp(DParticleID::dedx_t a, DParticleID::dedx_t b)
Definition: DParticleID.cc:16
TH2F * temp
float tErr
Definition: DTOFPoint.h:36
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
double ONESIDED_PADDLE_MIDPOINT_MAG
Definition: DParticleID.h:309
vector< double > propagation_speed
Definition: DParticleID.h:304
virtual double GetEOverPMean(DetectorSystem_t detector, double p) const =0
jerror_t GetIntersectionWithPlane(const DVector3 &origin, const DVector3 &norm, DVector3 &pos, double *s=NULL, double *t=NULL, double *var_t=NULL, DetectorSystem_t detector=SYS_NULL) const
vector< vector< DVector3 > > sc_dir
Definition: DParticleID.h:273
bool Is_YPositionWellDefined(void) const
Definition: DTOFPoint.h:50
Particle_t PID(void) const
double TOF_CUT_PAR1
Definition: DParticleID.h:245
bool GetStartCounterGeom(vector< vector< DVector3 > > &pos, vector< vector< DVector3 > > &norm) const
Definition: DGeometry.cc:1983
Particle_t
Definition: particleType.h:12
bool START_EXIST
Definition: DParticleID.h:268
int dVerticalBarStatus
Definition: DTOFPoint.h:44
void Set_ChiSq_Timing(double locChiSq, unsigned int locNDF)