tpctrackfit2_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: tpctrackfit2
3 // Plugin Type: producer (art v3_00_00)
4 // File: tpctrackfit2_module.cc
5 //
6 // Generated at Tue Feb 5 11:34:54 2019 by Thomas Junk using cetskelgen
7 // from cetlib version v3_04_00.
8 ////////////////////////////////////////////////////////////////////////
9 
17 #include "fhiclcpp/ParameterSet.h"
20 #include "canvas/Persistency/Common/FindManyP.h"
21 
22 #include <memory>
23 #include <set>
24 
25 // ROOT includes
26 
27 #include "TVectorF.h"
28 #include "TMatrix.h"
29 #include "TMath.h"
30 #include "TVector3.h"
31 
32 // GArSoft Includes
39 #include "Reco/TrackPar.h"
40 #include "Reco/tracker2algs.h"
41 #include "Geometry/GeometryGAr.h"
42 #include "CoreUtils/ServiceUtil.h"
43 
44 #include "nug4/MagneticFieldServices/MagneticFieldService.h"
45 #include "Geant4/G4ThreeVector.hh"
46 
47 namespace gar {
48  namespace rec {
49 
50  class tpctrackfit2 : public art::EDProducer {
51  public:
52  explicit tpctrackfit2(fhicl::ParameterSet const& p);
53  // The compiler-generated destructor is fine for non-base
54  // classes without bare pointers or other resource use.
55 
56  // Plugins should not be copied or assigned.
57  tpctrackfit2(tpctrackfit2 const&) = delete;
58  tpctrackfit2(tpctrackfit2&&) = delete;
59  tpctrackfit2& operator=(tpctrackfit2 const&) = delete;
60  tpctrackfit2& operator=(tpctrackfit2&&) = delete;
61 
62  // Required functions.
63  void produce(art::Event& e) override;
64 
65  private:
66 
67  // Declare member data here.
68 
69  std::string fPatRecLabel; ///< input patrec tracks and associations
70  int fPrintLevel; ///< debug printout: 0: none, 1: just track parameters and residuals, 2: all
71  float fKalCurvStepUncSq; ///< constant uncertainty term on each step of the Kalman fit -- squared, for curvature
72  float fKalPhiStepUncSq; ///< constant uncertainty term on each step of the Kalman fit -- squared, for phi
73  float fKalLambdaStepUncSq; ///< constant uncertainty term on each step of the Kalman fit -- squared, for lambda
74  float fKalCovZYMeasure; ///< constant uncertainty term on measurement in Kalman (the R matrix)
75  float fTPCClusterResolYZ; ///< pad size in cm in YZ to determine step size
76  float fTPCClusterResolX; ///< drift direction contribution to determine step size (resolution of a TPCCluster)
77  unsigned int fInitialTPNTPCClusters; ///< number of TPCClusters to use for initial trackpar estimate, if present
78  unsigned int fMinNumTPCClusters; ///< minimum number of TPCClusters to define a track
79  int fDumpTracks; ///< 0: do not print out tracks, 1: print out tracks
80  float fRoadYZinFit; ///< cut in cm for dropping TPCClusters from tracks in fit
81  int fSortAlg; ///< which hit sorting alg to use. 1: old, 2: greedy distance sort
82  float fSortDistCut; ///< distance cut to pass to hit sorter #2
83  float fSortTransWeight; ///< for use in hit sorting algorithm #1 -- transverse distance weight factor
84  float fSortDistBack; ///< for use in hit sorting algorithm #1 -- how far to go back before raising the distance figure of merit
85  float fMinIonizGapCut; ///< Don't compute dEdx for this dx or larger
86 
87  float fTPCClusterResid__CROC_b; ///< parameters to estimate residuals in YZ plane
95 
96 
97 
98  int KalmanFit( std::vector<TPCCluster> &TPCClusters,
99  std::vector<int> &TPCClusterlist,
100  std::vector<float> &trackparatend,
101  float &chisquared,
102  float &length,
103  float *covmat, // 5x5 covariance matrix
104  std::set<int> &unused_TPCClusters,
105  std::vector<std::pair<float,float>>& dSigdX,
106  std::vector<TVector3>& trajpts);
107 
108  int KalmanFitBothWays(std::vector<gar::rec::TPCCluster> &TPCClusters,
109  TrackPar &trackpar, TrackIoniz &trackions, TrackTrajectory &tracktraj);
110 
112 
113  };
114 
115 
117  {
118  // Call appropriate produces<>() functions here.
119  // Call appropriate consumes<>() for any products to be retrieved by this module.
120 
121  fPatRecLabel = p.get<std::string>("PatRecLabel","patrec");
122  fPrintLevel = p.get<int>("PrintLevel",0);
123  fMinNumTPCClusters = p.get<unsigned int>("MinNumTPCClusters",20);
124  fKalCurvStepUncSq = p.get<float>("KalCurvStepUncSq",1.0E-9);
125  fKalPhiStepUncSq = p.get<float>("KalPhiStepUncSq",1.0E-9);
126  fKalLambdaStepUncSq = p.get<float>("KalLambdaStepUncSq",1.0E-9);
127  fKalCovZYMeasure = p.get<float>("KalCovZYMeasure", 4.0);
128  fInitialTPNTPCClusters = p.get<unsigned int>("InitialTPNTPCClusters",100);
129  fDumpTracks = p.get<int>("DumpTracks",0);
130  fTPCClusterResolYZ = p.get<float>("TPCClusterResolYZ",1.0); // TODO -- think about what this value is
131  fTPCClusterResolX = p.get<float>("TPCClusterResolX",0.5); // this is probably much better
132  fRoadYZinFit = p.get<float>("RoadYZinFit",1.0);
133  fSortTransWeight = p.get<float>("SortTransWeight",0.1);
134  fSortDistBack = p.get<float>("SortDistBack",2.0);
135  fMinIonizGapCut = p.get<float>("MinIonizGapCut",5.0);
136  fSortDistCut = p.get<float>("SortDistCut",10.0);
137  fSortAlg = p.get<int>("SortAlg",2);
138 
139  fTPCClusterResid__CROC_b = p.get<float>("TPCClusterResid__CROC_b", 0.2);
140  fTPCClusterResid__CROC_m = p.get<float>("TPCClusterResid__CROC_m", 0.1);
141  fTPCClusterResid__IROC_b = p.get<float>("TPCClusterResid__IROC_b", 0.1);
142  fTPCClusterResid__IROC_m = p.get<float>("TPCClusterResid__IROC_m", 0.2);
143  fTPCClusterResid_IOROC_b = p.get<float>("TPCClusterResid__CROC_b", 0.1);
144  fTPCClusterResid_IOROC_m = p.get<float>("TPCClusterResid__CROC_m", 0.3);
145  fTPCClusterResid_OOROC_b = p.get<float>("TPCClusterResid__CROC_b", 0.1);
146  fTPCClusterResid_OOROC_m = p.get<float>("TPCClusterResid__CROC_m", 0.9);
147 
148  art::InputTag patrecTag(fPatRecLabel);
149  consumes<std::vector<gar::rec::Track>>(patrecTag);
150  consumes<art::Assns<gar::rec::TPCCluster, gar::rec::Track>>(patrecTag);
151 
152  // probably don't need the vector hits at this point if we have the TPCClusters
153  //consumes< std::vector<gar::rec::VecHit> >(patrecTag);
154  //consumes< art::Assns<gar::rec::VecHit, gar::rec::Track> >(patrecTag);
155 
156  produces<std::vector<gar::rec::Track>>();
157  produces<art::Assns<gar::rec::TPCCluster, gar::rec::Track>>();
158  produces<std::vector<gar::rec::TrackIoniz>>();
159  produces<art::Assns<rec::TrackIoniz, rec::Track>>();
160  produces<std::vector<gar::rec::TrackTrajectory>>();
161  produces<art::Assns<rec::TrackTrajectory, rec::Track>>();
162  }
163 
164 
165 
167  {
168  // output collections
169 
170  std::unique_ptr< std::vector<gar::rec::Track> > trkCol(new std::vector<gar::rec::Track>);
171  std::unique_ptr< art::Assns<gar::rec::TPCCluster,gar::rec::Track> > TPCClusterTrkAssns(new ::art::Assns<gar::rec::TPCCluster,gar::rec::Track>);
172  std::unique_ptr< std::vector<rec::TrackIoniz> > ionCol(new std::vector<rec::TrackIoniz>);
173  std::unique_ptr< art::Assns<rec::TrackIoniz,rec::Track> > ionTrkAssns(new ::art::Assns<rec::TrackIoniz,rec::Track>);
174  std::unique_ptr< std::vector<rec::TrackTrajectory> > trajCol(new std::vector<rec::TrackTrajectory>);
175  std::unique_ptr< art::Assns<rec::TrackTrajectory,rec::Track> > trajTrkAssns(new ::art::Assns<rec::TrackTrajectory,rec::Track>);
176 
177  // inputs
178 
179  auto patrecTrackHandle = e.getValidHandle< std::vector<gar::rec::Track> >(fPatRecLabel);
180  auto const& patrecTracks = *patrecTrackHandle;
181 
182  auto const trackPtrMaker = art::PtrMaker<gar::rec::Track>(e);
183  auto const ionizPtrMaker = art::PtrMaker<rec::TrackIoniz>(e);
184  auto const trajPtrMaker = art::PtrMaker<rec::TrackTrajectory>(e);
185  //auto const TPCClusterPtrMaker = art::PtrMaker<gar::rec::TPCCluster>(e, TPCClusterHandle.id());
186 
187  auto const *magFieldService = gar::providerFrom<mag::MagneticFieldService>();
188  G4ThreeVector zerovec(0,0,0);
189  G4ThreeVector magfield = magFieldService->FieldAtPoint(zerovec);
190 
191  double xtpccent = euclid->TPCXCent();
192  double ytpccent = euclid->TPCYCent();
193  double ztpccent = euclid->TPCZCent();
194  TVector3 tpccent(xtpccent,ytpccent,ztpccent);
195  TVector3 xhat(1,0,0);
196 
197  const art::FindManyP<gar::rec::TPCCluster> TPCClustersFromPatRecTracks(patrecTrackHandle,e,fPatRecLabel);
198 
199  for (size_t itrack = 0; itrack < patrecTracks.size(); ++itrack)
200  {
201  std::vector<gar::rec::TPCCluster> TPCClusters;
202  for (size_t iTPCCluster=0; iTPCCluster < TPCClustersFromPatRecTracks.at(itrack).size(); ++iTPCCluster)
203  {
204  TPCClusters.push_back(*TPCClustersFromPatRecTracks.at(itrack).at(iTPCCluster)); // make our own local copy of TPCClusters. Maybe we can skip this?
205  }
206  TrackPar trackparams;
207  TrackIoniz trackions;
208  TrackTrajectory tracktraj;
209  if (KalmanFitBothWays(TPCClusters,trackparams,trackions,tracktraj) == 0) // to think about -- unused TPCClusters? Or just ignore them in the fit?
210  {
211  trkCol->push_back(trackparams.CreateTrack());
212  ionCol->push_back(trackions);
213  trajCol->push_back(tracktraj);
214  auto const trackpointer = trackPtrMaker(trkCol->size()-1);
215  auto const ionizpointer = ionizPtrMaker(ionCol->size()-1);
216  auto const trajpointer = trajPtrMaker(trajCol->size()-1);
217  for (size_t iTPCCluster=0; iTPCCluster<TPCClusters.size(); ++iTPCCluster)
218  {
219  TPCClusterTrkAssns->addSingle(TPCClustersFromPatRecTracks.at(itrack).at(iTPCCluster),trackpointer);
220  }
221  ionTrkAssns->addSingle(ionizpointer, trackpointer);
222  trajTrkAssns->addSingle(trajpointer, trackpointer);
223  }
224  }
225 
226  e.put(std::move(trkCol));
227  e.put(std::move(TPCClusterTrkAssns));
228  e.put(std::move(ionCol));
229  e.put(std::move(ionTrkAssns));
230  e.put(std::move(trajCol));
231  e.put(std::move(trajTrkAssns));
232  }
233 
234  int tpctrackfit2::KalmanFitBothWays(std::vector<gar::rec::TPCCluster> &TPCClusters,
235  TrackPar &trackpar, TrackIoniz &trackions, TrackTrajectory &tracktraj)
236 
237  {
238  // variables: x is the independent variable
239  // 0: y
240  // 1: z
241  // 2: curvature
242  // 3: phi
243  // 4: lambda = angle from the cathode plane
244  // 5: x /// added on to the end
245 
246 
247  std::vector<int> hlf;
248  std::vector<int> hlb;
249  float lftmp=0; // need these dummy arguments so we can share code with the patrec sorter
250  float lbtmp=0;
251  if (fSortAlg == 1)
252  {
254  }
255  else if (fSortAlg == 2)
256  {
257  gar::rec::sort_TPCClusters_along_track2(TPCClusters,hlf,hlb,fPrintLevel,lftmp,lbtmp,fSortDistCut);
258  }
259  else
260  {
261  throw cet::exception("tpctrackfit2_module") << "Sort Algorithm swithc not understood: " << fSortAlg;
262  }
263  if (hlf.size() == 0) return 1;
264  std::vector<float> tparend(6);
265  float covmatend[25];
266  float chisqforwards = 0;
267  float lengthforwards = 0;
268  std::set<int> unused_TPCClusters;
269  std::vector<std::pair<float,float>> dSigdXs_FWD;
270  std::vector<TVector3> trajpts_FWD;
271 
272  int retcode = KalmanFit(TPCClusters,hlf,tparend,chisqforwards,lengthforwards,covmatend,unused_TPCClusters,dSigdXs_FWD,trajpts_FWD);
273  if (retcode != 0) return 1;
274 
275  // the "backwards" fit is in decreasing x. Track parameters are at the end of the fit, the other end of the track
276 
277  std::vector<float> tparbeg(6);
278  float covmatbeg[25];
279  float chisqbackwards = 0;
280  float lengthbackwards = 0;
281  std::vector<std::pair<float,float>> dSigdXs_BAK;
282  std::vector<TVector3> trajpts_BAK;
283 
284  retcode = KalmanFit(TPCClusters,hlb,tparbeg,chisqbackwards,lengthbackwards,covmatbeg,unused_TPCClusters,dSigdXs_BAK,trajpts_BAK);
285  if (retcode != 0) return 1;
286 
287  size_t nTPCClusters=0;
288  if (TPCClusters.size()>unused_TPCClusters.size())
289  { nTPCClusters = TPCClusters.size()-unused_TPCClusters.size(); }
290  trackpar.setNTPCClusters(nTPCClusters);
291  trackpar.setTime(0);
292  trackpar.setChisqForwards(chisqforwards);
293  trackpar.setChisqBackwards(chisqbackwards);
294  trackpar.setLengthForwards(lengthforwards);
295  trackpar.setLengthBackwards(lengthbackwards);
296  trackpar.setCovMatBeg(covmatbeg);
297  trackpar.setCovMatEnd(covmatend);
298  trackpar.setTrackParametersBegin(tparbeg.data());
299  trackpar.setXBeg(tparbeg[5]);
300  trackpar.setTrackParametersEnd(tparend.data());
301  trackpar.setXEnd(tparend[5]);
302 
303  trackions.setData(dSigdXs_FWD,dSigdXs_BAK);
304  tracktraj.setData(trajpts_FWD,trajpts_BAK);
305 
306  return 0;
307  }
308 
309  //--------------------------------------------------------------------------------------------------------------
310  //--------------------------------------------------------------------------------------------------------------
311 
312  // KalmanFit does a forwards or backwards Kalman fit using the sorted TPCCluster list
313  // variables: x is the independent variable
314  // 0: y
315  // 1: z
316  // 2: curvature
317  // 3: phi
318  // 4: lambda
319 
320  int tpctrackfit2::KalmanFit( std::vector<TPCCluster> &TPCClusters,
321  std::vector<int> &TPCClusterlist, // sort ordered list
322  std::vector<float> &trackparatend,
323  float &chisquared,
324  float &length,
325  float *covmat, // 5x5 covariance matrix
326  std::set<int> &unused_TPCClusters,
327  std::vector<std::pair<float,float>>& dSigdXs,
328  std::vector<TVector3>& trajpts)
329  {
330 
331  // set some default values in case we return early
332 
333  size_t nTPCClusters = TPCClusterlist.size();
334  chisquared = 0;
335  length = 0;
336  for (size_t i=0; i<5; ++i) trackparatend[i] = 0;
337  for (size_t i=0; i<25; ++i) covmat[i] = 0;
338 
339  float roadsq = fRoadYZinFit*fRoadYZinFit;
340 
341  // estimate curvature, lambda, phi, xpos from the initial track parameters
342  float curvature_init=0.1;
343  float phi_init = 0;
344  float lambda_init = 0;
345  float xpos_init=0;
346  float ypos_init=0;
347  float zpos_init=0;
348  float x_other_end = 0;
349  if ( gar::rec::initial_trackpar_estimate(TPCClusters,
350  TPCClusterlist,
351  curvature_init,
352  lambda_init,
353  phi_init,
354  xpos_init,
355  ypos_init,
356  zpos_init,
357  x_other_end,
359  fPrintLevel) != 0)
360  {
361  //std::cout << "kalman fit failed on initial trackpar estimate" << std::endl;
362  return 1;
363  }
364 
365  // Kalman fitter variables
366 
367  float xpos = xpos_init;
368 
369  TMatrixF P(5,5); // covariance matrix of parameters
370  // fill in initial guesses -- generous uncertainties on first value.
371  P.Zero();
372  P[0][0] = TMath::Sq(1); // initial position uncertainties -- y
373  P[1][1] = TMath::Sq(1); // and z
374  P[2][2] = TMath::Sq(.5); // curvature of zero gets us to infinite momentum, and curvature of 2 is curled up tighter than the pads
375  P[3][3] = TMath::Sq(.5); // phi uncertainty
376  P[4][4] = TMath::Sq(.5); // lambda uncertainty
377 
378  TMatrixF PPred(5,5);
379 
380  // per-step additions to the covariance matrix
381  TMatrixF Q(5,5);
382  Q.Zero();
383  Q[2][2] = fKalCurvStepUncSq; // allow for some curvature uncertainty between points
384  Q[3][3] = fKalPhiStepUncSq; // phi
385  Q[4][4] = fKalLambdaStepUncSq; // lambda
386 
387  // Noise covariance on the measured points.
388  // 16 cm2 initially, might reasonably be lowered to typicalResidual near line 552-67
389  TMatrixF R(2,2);
390  R.Zero();
391  R[0][0] = TMath::Sq(fKalCovZYMeasure); // in cm^2
392  R[1][1] = TMath::Sq(fKalCovZYMeasure); // in cm^2
393 
394  // add the TPCClusters and update the track parameters and uncertainties. Put in additional terms to keep uncertainties from shrinking when
395  // scattering and energy loss can change the track parameters along the way.
396 
397  // F = partial(updatefunc)/partial(parvec). Update functions are in the comments below.
398  TMatrixF F(5,5);
399  TMatrixF FT(5,5);
400  TVectorF parvec(5);
401  parvec[0] = ypos_init;
402  parvec[1] = zpos_init;
403  parvec[2] = curvature_init;
404  parvec[3] = phi_init;
405  parvec[4] = lambda_init;
406  TVectorF predstep(5);
407 
408  TMatrixF H(2,5); // partial(obs)/partial(params)
409  H.Zero();
410  H[0][0] = 1; // y
411  H[1][1] = 1; // z
412  TMatrixF HT(5,2);
413 
414  TVectorF z(2);
415  TVectorF ytilde(2);
416  TVectorF hx(2);
417  TMatrixF S(2,2);
418  TMatrixF K(5,2);
419 
420  TMatrixF I(5,5);
421  I.Zero();
422  for (int i=0;i<5;++i) I[i][i] = 1;
423 
424  for (size_t iTPCCluster=1; iTPCCluster<nTPCClusters; ++iTPCCluster)
425  {
426 
427  float xh = TPCClusters[TPCClusterlist[iTPCCluster]].Position()[0];
428  float yh = TPCClusters[TPCClusterlist[iTPCCluster]].Position()[1];
429  float zh = TPCClusters[TPCClusterlist[iTPCCluster]].Position()[2];
430 
431  if (fPrintLevel > 0)
432  {
433  std::cout << std::endl;
434  std::cout << "Adding a new TPCCluster: " << xh << " " << yh << " " << zh << std::endl;
435  }
436 
437  // for readability
438  float curvature = parvec[2];
439  float phi = parvec[3];
440  float lambda = parvec[4];
441 
442  // update prediction to the plane containing x. Maybe we need to find
443  // the closest point on the helix to the TPCCluster we are adding,
444  // and not necessarily force it to be at this x
445 
446  F.Zero();
447 
448  // y = yold + slope*dx*Sin(phi). F[0][i] = dy/dtrackpar[i], where f is the update function slope*dx*Sin(phi)
449 
450  float slope = TMath::Tan(lambda);
451  if (slope != 0)
452  {
453  slope = 1.0/slope;
454  }
455  else
456  {
457  slope = 1E9;
458  }
459 
460  // relocate dx to be the location along the helix which minimizes
461  // [ (Xhit -Xhelix)/sigmaX ]^2 + [ (Yhit -Yhelix)/sigmaY ]^2 + [ (Zhit -Zhelix)/sigmaZ ]^2
462  // Linearize for now near xpos:
463  // x = xpos + dx
464  // y = parvec[0] + slope * dx * sin(phi)
465  // z = parvec[1] + slope * dx * cos(phi)
466  // parvec is updated as the fit progresses so the 'zero point' where y_0, z_0, phi_0
467  // are defined is at the end of the fit, not at the place where the fit begins.
468  //
469  // old calc was just based on TPCCluster position in x:
470  // float dx = xh - xpos;
471 
472 
473  float dxnum = (slope/(fTPCClusterResolYZ*fTPCClusterResolYZ))*( (yh - parvec[0])*TMath::Sin(phi) + (zh - parvec[1])*TMath::Cos(phi) )
474  + (xh - xpos)/(fTPCClusterResolX*fTPCClusterResolX);
475  float dxdenom = slope*slope/(fTPCClusterResolYZ*fTPCClusterResolYZ) + 1.0/(fTPCClusterResolX*fTPCClusterResolX);
476  float dx = dxnum/dxdenom;
477  if (dx == 0) dx = 1E-3;
478  //std::cout << "dxdenom, dxnum: " << dxdenom << " " << dxnum << std::endl;
479  //std::cout << "Track pos: " << xpos << " " << parvec[0] << " " << parvec[1] << " " << " TPCCluster pos: " << xh << " " << yh << " " << zh << std::endl;
480  //std::cout << "dx old and new: " << xh - xpos << " " << dx << std::endl;
481 
482 
483  //TODO check this -- are these the derivatives?
484  // y = yold + dx*slope*TMath::Sin(phi)
485  // slope = cot(lambda), so dslope/dlambda = -csc^2(lambda) = -1 - slope^2
486  F[0][0] = 1.;
487  F[0][3] = dx*slope*TMath::Cos(phi);
488  F[0][4] = dx*TMath::Sin(phi)*(-1.0-slope*slope);
489 
490  // z = zold + slope*dx*Cos(phi)
491  F[1][1] = 1.;
492  F[1][3] = -dx*slope*TMath::Sin(phi);
493  F[1][4] = dx*TMath::Cos(phi)*(-1.0-slope*slope);
494 
495  // curvature = old curvature -- doesn't change but put in an uncertainty
496  F[2][2] = 1.;
497 
498  // phi = old phi + curvature*slope*dx
499  // need to take the derivative of a product here
500  F[3][2] = dx*slope;
501  F[3][3] = 1.;
502  F[3][4] = dx*curvature*(-1.0-slope*slope);
503 
504  // lambda -- same -- but put in an uncertainty in case it changes
505  F[4][4] = 1.;
506 
507  // predicted step
508  if (fPrintLevel > 1)
509  {
510  std::cout << "F Matrix: " << std::endl;
511  F.Print();
512  std::cout << "P Matrix: " << std::endl;
513  P.Print();
514  }
515  if (fPrintLevel > 0)
516  {
517  std::cout << "x: " << xpos << " dx: " << dx << std::endl;
518  std::cout << " Parvec: y " << parvec[0] << " z " << parvec[1] << " c " << parvec[2] << " phi " << parvec[3] << " lambda " << parvec[4] << std::endl;
519  }
520 
521  predstep = parvec;
522  predstep[0] += slope*dx*TMath::Sin(phi); // update y
523  predstep[1] += slope*dx*TMath::Cos(phi); // update z
524  predstep[3] += slope*dx*curvature; // update phi
525 
526  if (fPrintLevel > 1)
527  {
528  std::cout << " Predstep: y " << predstep[0] << " z " << predstep[1] << " c " << predstep[2] << " phi " << predstep[3] << " lambda " << predstep[4] << std::endl;
529  }
530  // equations from the extended Kalman filter
531  FT.Transpose(F);
532  PPred = F*P*FT + Q;
533  if (fPrintLevel > 1)
534  {
535  std::cout << "PPred Matrix: " << std::endl;
536  PPred.Print();
537  }
538 
539  ytilde[0] = yh - predstep[0];
540  ytilde[1] = zh - predstep[1];
541  float ydistsq = ytilde.Norm2Sqr();
542  if (ydistsq > roadsq)
543  {
544  unused_TPCClusters.insert(iTPCCluster);
545  continue;
546  }
547 
548  // Now the chisquared calculation. Need the angle of track re line from axis of
549  // TPC, that is alpha; and to determine which part of the detector we are
550  // in. The residual is determined based on a simple linear parameterization
551  float impactAngle;
552  TVector3 trajPerp(0.0, predstep[0],predstep[1]);
553  float rTrj = trajPerp.Mag();
554  TVector3 trajStepPerp(0.0, sin(predstep[3]),cos(predstep[3]));
555  impactAngle = trajPerp.Dot(trajStepPerp) / rTrj;
556  impactAngle = acos(abs(impactAngle));
557  float IROC_OROC_boundary = (euclid->GetIROCOuterRadius() +euclid->GetOROCInnerRadius())/2.0;
558  bool In_CROC = rTrj <= euclid->GetIROCInnerRadius();
559  bool In_IROC = euclid->GetIROCInnerRadius() < rTrj && rTrj <= IROC_OROC_boundary;
560  bool InIOROC = IROC_OROC_boundary < rTrj && rTrj <= euclid->GetOROCPadHeightChangeRadius();
561  bool InOOROC = euclid->GetOROCPadHeightChangeRadius() < rTrj;
562  float typicalResidual = 1.0; // Shaddup, compiler
563  if (In_CROC) {
564  typicalResidual = fTPCClusterResid__CROC_m*impactAngle +fTPCClusterResid__CROC_b;
565  } else if (In_IROC) {
566  typicalResidual = fTPCClusterResid__IROC_m*impactAngle +fTPCClusterResid__IROC_b;
567  } else if (InIOROC) {
568  typicalResidual = fTPCClusterResid_IOROC_m*impactAngle +fTPCClusterResid_IOROC_b;
569  } else if (InOOROC) {
570  typicalResidual = fTPCClusterResid_OOROC_m*impactAngle +fTPCClusterResid_OOROC_b;
571  }
572 
573  chisquared += ytilde.Norm2Sqr()/TMath::Sq(typicalResidual);
574  if (fPrintLevel > 0)
575  {
576  std::cout << "ytilde (residuals): " << std::endl;
577  ytilde.Print();
578  }
579  if (fPrintLevel > 1)
580  {
581  std::cout << "H Matrix: " << std::endl;
582  H.Print();
583  }
584 
585  HT.Transpose(H);
586  S = H*PPred*HT + R;
587  if (fPrintLevel > 1)
588  {
589  std::cout << "S Matrix: " << std::endl;
590  S.Print();
591  }
592 
593  S.Invert();
594  if (fPrintLevel > 1)
595  {
596  std::cout << "Inverted S Matrix: " << std::endl;
597  S.Print();
598  }
599 
600  K = PPred*HT*S;
601  if (fPrintLevel > 1)
602  {
603  std::cout << "K Matrix: " << std::endl;
604  K.Print();
605  }
606 
607  float yprev = parvec[0];
608  float zprev = parvec[1];
609  parvec = predstep + K*ytilde;
610  P = (I-K*H)*PPred;
611  xpos = xpos + dx;
612  //std::cout << " Updated xpos: " << xpos << " " << dx << std::endl;
613  trajpts.emplace_back(xpos,parvec[0],parvec[1]);
614 
615  float d_length = TMath::Sqrt( dx*dx + TMath::Sq(parvec[0]-yprev) + TMath::Sq(parvec[1]-zprev) );
616  length += d_length;
617 
618  // Save the ionization data - skip large gaps from sector boundaries
619  float valSig = TPCClusters[TPCClusterlist[iTPCCluster]].Signal();
620  if (d_length < fMinIonizGapCut)
621  {
622  std::pair pushme = std::make_pair(valSig,d_length);
623  dSigdXs.push_back( pushme );
624  }
625  else
626  // Have to remove the fellow before the large gap, too
627  {
628  if (dSigdXs.size()>0) dSigdXs.pop_back();
629  }
630  }
631 
632  for (size_t i=0; i<5; ++i)
633  {
634  trackparatend[i] = parvec[i];
635  }
636  trackparatend[5] = xpos; // tack this on so we can specify where the track endpoint is
637  if (fPrintLevel > 1)
638  {
639  std::cout << "Track params at end (y, z, curv, phi, lambda) " << trackparatend[0] << " " << trackparatend[1] << " " <<
640  trackparatend[2] << " " << trackparatend[3] <<" " << trackparatend[4] << std::endl;
641  S.Print();
642  }
643 
644  // just for visualization of the initial track parameter guesses.
645  // Comment out when fitting tracks.
646  //trackparatend[0] = ypos_init;
647  //trackparatend[1] = zpos_init;
648  //trackparatend[2] = curvature_init;
649  //trackparatend[3] = phi_init;
650  //trackparatend[4] = lambda_init;
651  //trackparatend[5] = xpos_init;
652 
653 
654  size_t icov=0;
655  for (size_t i=0; i<5; ++i)
656  {
657  for (size_t j=0; j<5; ++j)
658  {
659  covmat[icov] = P[i][j];
660  }
661  }
662 
663  return 0;
664  }
665 
666  //--------------------------------------------------------------------------------------------------------------
667 
668 
670 
671  } // namespace rec
672 } // namespace gar
void setNTPCClusters(const size_t nTPCClusters)
Definition: TrackPar.cxx:214
void setLengthForwards(const float lengthforwards)
Definition: TrackPar.cxx:251
float fSortTransWeight
for use in hit sorting algorithm #1 – transverse distance weight factor
rec
Definition: tracks.py:88
std::string fPatRecLabel
input patrec tracks and associations
TH3F * xpos
Definition: doAna.cpp:29
float fKalCurvStepUncSq
constant uncertainty term on each step of the Kalman fit – squared, for curvature ...
void setCovMatBeg(const float *covmatbeg)
Definition: TrackPar.cxx:235
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
int KalmanFitBothWays(std::vector< gar::rec::TPCCluster > &TPCClusters, TrackPar &trackpar, TrackIoniz &trackions, TrackTrajectory &tracktraj)
float fKalPhiStepUncSq
constant uncertainty term on each step of the Kalman fit – squared, for phi
float fRoadYZinFit
cut in cm for dropping TPCClusters from tracks in fit
struct vector vector
std::pair< float, std::string > P
void setLengthBackwards(const float lengthbackwards)
Definition: TrackPar.cxx:256
float fSortDistBack
for use in hit sorting algorithm #1 – how far to go back before raising the distance figure of merit...
int KalmanFit(std::vector< TPCCluster > &TPCClusters, std::vector< int > &TPCClusterlist, std::vector< float > &trackparatend, float &chisquared, float &length, float *covmat, std::set< int > &unused_TPCClusters, std::vector< std::pair< float, float >> &dSigdX, std::vector< TVector3 > &trajpts)
art::ServiceHandle< geo::GeometryGAr > euclid
int fDumpTracks
0: do not print out tracks, 1: print out tracks
float fTPCClusterResid__CROC_b
parameters to estimate residuals in YZ plane
void setTrackParametersBegin(const float *tparbeg)
Definition: TrackPar.cxx:219
T abs(T value)
int fSortAlg
which hit sorting alg to use. 1: old, 2: greedy distance sort
tpctrackfit2 & operator=(tpctrackfit2 const &)=delete
float fMinIonizGapCut
Don&#39;t compute dEdx for this dx or larger.
const double e
unsigned int fMinNumTPCClusters
minimum number of TPCClusters to define a track
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
def move(depos, offset)
Definition: depos.py:107
void setXEnd(const float xend)
Definition: TrackPar.cxx:276
void setTrackParametersEnd(const float *tparend)
Definition: TrackPar.cxx:227
float fSortDistCut
distance cut to pass to hit sorter #2
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
int fPrintLevel
debug printout: 0: none, 1: just track parameters and residuals, 2: all
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
void setChisqBackwards(const float chisqbackwards)
Definition: TrackPar.cxx:266
void setData(std::vector< TVector3 > ForwardTrajectory, std::vector< TVector3 > BackwardTrajectory)
float fKalCovZYMeasure
constant uncertainty term on measurement in Kalman (the R matrix)
float fTPCClusterResolYZ
pad size in cm in YZ to determine step size
gar::rec::Track CreateTrack()
Definition: TrackPar.cxx:292
void produce(art::Event &e) override
General GArSoft Utilities.
void setCovMatEnd(const float *covmatend)
Definition: TrackPar.cxx:243
void sort_TPCClusters_along_track(const std::vector< gar::rec::TPCCluster > &TPCClusters, std::vector< int > &hlf, std::vector< int > &hlb, int printlevel, float &lengthforwards, float &lengthbackwards, float sorttransweight, float sortdistback)
void sort_TPCClusters_along_track2(const std::vector< gar::rec::TPCCluster > &TPCClusters, std::vector< int > &hlf, std::vector< int > &hlb, int printlevel, float &lengthforwards, float &lengthbackwards, float dcut)
void setXBeg(const float xbeg)
Definition: TrackPar.cxx:271
void setData(std::vector< std::pair< float, float >> dSigdX_FWD, std::vector< std::pair< float, float >> dSigdX_BAK)
Definition: TrackIoniz.cxx:20
float fTPCClusterResolX
drift direction contribution to determine step size (resolution of a TPCCluster)
void setChisqForwards(const float chisqforwards)
Definition: TrackPar.cxx:261
unsigned int fInitialTPNTPCClusters
number of TPCClusters to use for initial trackpar estimate, if present
art framework interface to geometry description
void setTime(const double time)
Definition: TrackPar.cxx:281
float fKalLambdaStepUncSq
constant uncertainty term on each step of the Kalman fit – squared, for lambda
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
tpctrackfit2(fhicl::ParameterSet const &p)
QTextStream & endl(QTextStream &s)
int initial_trackpar_estimate(const std::vector< gar::rec::TPCCluster > &TPCClusters, std::vector< int > &TPCClusterlist, float &curvature_init, float &lambda_init, float &phi_init, float &xpos, float &ypos, float &zpos, float &x_other_end, unsigned int initialtpnTPCClusters, int printlevel)
Definition: tracker2algs.cxx:8