tpcpatrec2_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: tpcpatrec2
3 // Plugin Type: producer (art v3_00_00)
4 // File: tpcpatrec2_module.cc
5 //
6 // Generated at Tue Feb 5 08:57:00 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 #include "TMath.h"
26 #include "TVector3.h"
27 
28 #include "nug4/MagneticFieldServices/MagneticFieldService.h"
29 #include "Geant4/G4ThreeVector.hh"
30 
31 // GArSoft Includes
36 #include "Reco/TrackPar.h"
37 #include "Reco/tracker2algs.h"
38 #include "CoreUtils/ServiceUtil.h"
39 
40 namespace gar {
41  namespace rec {
42 
43  class tpcpatrec2 : public art::EDProducer {
44  public:
45  explicit tpcpatrec2(fhicl::ParameterSet const& p);
46  // The compiler-generated destructor is fine for non-base
47  // classes without bare pointers or other resource use.
48 
49  // Plugins should not be copied or assigned.
50  tpcpatrec2(tpcpatrec2 const&) = delete;
51  tpcpatrec2(tpcpatrec2&&) = delete;
52  tpcpatrec2& operator=(tpcpatrec2 const&) = delete;
53  tpcpatrec2& operator=(tpcpatrec2&&) = delete;
54 
55  // Required functions.
56  void produce(art::Event& e) override;
57 
58  private:
59 
60  // Declare member data here.
61 
62  std::string fVecHitLabel; ///< label of module to get the vector hits and associations with hits
63  int fPrintLevel; ///< debug printout: 0: none, 1: selected, 2: all
64  float fVecHitMatchCos; ///< matching condition for pairs of vector hits cos angle between directions
65  float fVecHitMatchPos; ///< matching condition for pairs of vector hits -- 3D distance (cm)
66  float fVecHitMatchPEX; ///< matching condition for pairs of vector hits -- miss distance (cm)
67  float fVecHitMatchEta; ///< matching condition for pairs of vector hits -- eta match (cm)
68  float fVecHitMatchLambda; ///< matching condition for pairs of vector hits -- dLambda (radians)
69  unsigned int fInitialTPNTPCClusters; ///< number of hits to use for initial trackpar estimate, if present
70  size_t fMinNumTPCClusters; ///< minimum number of hits for a patrec track
71 
72  int fSortAlg; ///< which hit sorting alg to use. 1: old, 2: greedy distance sort
73  float fSortDistCut; ///< distance cut to pass to hit sorting algorithm #2
74  float fSortTransWeight; ///< for use in hit sorting algorithm #1 -- transverse distance weight factor
75  float fSortDistBack; ///< for use in hit sorting algorithm #1 -- how far to go back before raising the distance figure of merit
76  float fCloseEtaUnmatch; ///< distance to look for vector hits that don't match in eta.
77 
78  float fConvAngleCut; ///< cut on angle diff for the conversion finder to split a cluster of VH's into two tracks
79 
80  // criteria for associating vector hits together to form clusters
81  bool vhclusmatch(const std::vector<gar::rec::VecHit> &vechits, std::vector<size_t> &cluster, size_t vh);
82 
83  // rough estimate of track parameters
84  int makepatrectrack(std::vector<gar::rec::TPCCluster> &hits, gar::rec::TrackPar &trackpar);
85 
86  float calceta2d(gar::rec::VecHit &vhtest, gar::rec::VecHit &vh);
87 
88  // test to see if a cluster looks like a conversion and split it in two if it does. Returns true
89  // if the cluster is identified as a conversion.
90 
91  bool conversion_test_split(const std::vector<gar::rec::VecHit> &vechits,
92  std::vector<size_t> &cluster,
93  std::vector<size_t> &splitclus1,
94  std::vector<size_t> &splitclus2);
95 
96  };
97 
98 
100  {
101  fVecHitLabel = p.get<std::string>("VecHitLabel","vechit");
102  fPrintLevel = p.get<int>("PrintLevel",0);
103  fVecHitMatchCos = p.get<float>("VecHitMatchCos",0.9);
104  fVecHitMatchPos = p.get<float>("VecHitMatchPos",20.0);
105  fVecHitMatchPEX = p.get<float>("VecHitMatchPEX",5.0);
106  fVecHitMatchEta = p.get<float>("VecHitMatchEta",1.0);
107  fVecHitMatchLambda = p.get<float>("VecHitMatchLambda",0.1);
108  fInitialTPNTPCClusters = p.get<unsigned int>("InitialTPNTPCClusters",100);
109  fMinNumTPCClusters = p.get<size_t>("MinNumTPCClusters",20);
110  fSortDistCut = p.get<float>("SortDistCut",10.0);
111  fSortAlg = p.get<int>("SortAlg",2);
112  fSortTransWeight = p.get<float>("SortTransWeight",0.1);
113  fSortDistBack = p.get<float>("SortDistBack",2.0);
114  fCloseEtaUnmatch = p.get<float>("CloseEtaUnmatch",20.0);
115  fConvAngleCut = p.get<float>("ConvAngleCut",1.0);
116 
117  art::InputTag vechitTag(fVecHitLabel);
118  consumes< std::vector<gar::rec::VecHit> >(vechitTag);
119  consumes< art::Assns<gar::rec::TPCCluster, gar::rec::VecHit> >(vechitTag);
120  produces< std::vector<gar::rec::Track> >();
121  produces< art::Assns<gar::rec::TPCCluster, gar::rec::Track> >();
122  produces< art::Assns<gar::rec::VecHit, gar::rec::Track> >();
123  }
124 
126  {
127  std::unique_ptr< std::vector<gar::rec::Track> > trkCol(new std::vector<gar::rec::Track>);
128  std::unique_ptr< art::Assns<gar::rec::VecHit,gar::rec::Track> > vhTrkAssns(new ::art::Assns<gar::rec::VecHit,gar::rec::Track>);
129  std::unique_ptr< art::Assns<gar::rec::TPCCluster,gar::rec::Track> > TPCClusterTrkAssns(new ::art::Assns<gar::rec::TPCCluster,gar::rec::Track>);
130 
131  auto vechitHandle = e.getValidHandle< std::vector<gar::rec::VecHit> >(fVecHitLabel);
132  auto const& vechits = *vechitHandle;
133 
134  auto const trackPtrMaker = art::PtrMaker<gar::rec::Track>(e);
135  auto const vhPtrMaker = art::PtrMaker<gar::rec::VecHit>(e, vechitHandle.id());
136 
137  const art::FindManyP<gar::rec::TPCCluster> TPCClustersFromVecHits(vechitHandle,e,fVecHitLabel);
138 
139  auto const *magFieldService = gar::providerFrom<mag::MagneticFieldService>();
140  G4ThreeVector zerovec(0,0,0);
141  G4ThreeVector magfield = magFieldService->FieldAtPoint(zerovec);
142 
143 
144  // stitch together vector hits into tracks
145  // question -- do we need to iterate this, first looking for small-angle matches, and then
146  // loosening up? Also need to address tracks that get stitched across the primary vertex -- may need to split
147  // these after other tracks have been found.
148 
149  std::vector< std::vector< size_t > > vhclusters; // change this to use just indices of vh's
150 
151  for (size_t ivh = 0; ivh< vechits.size(); ++ ivh)
152  {
153  if (fPrintLevel>1)
154  {
155  std::cout << " vhprint " << vechits[ivh].Position()[0] << " " << vechits[ivh].Position()[1] << " " << vechits[ivh].Position()[2] << " " <<
156  vechits[ivh].Direction()[0] << " " << vechits[ivh].Direction()[1] << " " << vechits[ivh].Direction()[2] << " " << std::endl;
157  }
158 
159  std::vector<size_t> clusmatchlist;
160  for (size_t iclus=0; iclus<vhclusters.size(); ++iclus)
161  {
162  if (vhclusmatch(vechits,vhclusters[iclus],ivh))
163  {
164  clusmatchlist.push_back(iclus);
165  }
166  }
167  if (clusmatchlist.size() == 0)
168  {
169  std::vector<size_t> newclus;
170  newclus.push_back(ivh);
171  vhclusters.push_back(newclus);
172  }
173  else if (clusmatchlist.size() == 1)
174  {
175  vhclusters[clusmatchlist[0]].push_back(ivh);
176  }
177  else // multiple matches -- merge clusters togetehr
178  {
179  for (size_t icm=1; icm<clusmatchlist.size(); ++icm)
180  {
181  for (size_t ivh2=0; ivh2<vhclusters[clusmatchlist[icm]].size(); ++ivh2)
182  {
183  vhclusters[clusmatchlist[0]].push_back(vhclusters[clusmatchlist[icm]][ivh2]);
184  }
185  }
186  // remove the merged vh clusters, using the new indexes after removing earlier ones
187  for (size_t icm=1; icm<clusmatchlist.size(); ++icm)
188  {
189  vhclusters.erase(vhclusters.begin() + (clusmatchlist[icm]-icm+1));
190  }
191  }
192  }
193 
194  //std::cout << "Before conversion check, clusters: " << std::endl;
195  //for (size_t iclus=0; iclus<vhclusters.size(); ++iclus)
196  // {
197  // std::cout << "Cluster " << iclus << std::endl;
198  // for (size_t ivh = 0; ivh< vhclusters.at(iclus).size(); ++ ivh)
199  // {
200  // size_t i=vhclusters.at(iclus).at(ivh);
201  // std::cout << " " << ivh << " " <<
202  // vechits[i].Position()[0] << " " << vechits[i].Position()[1] << " " << vechits[i].Position()[2] << " " <<
203  // vechits[i].Direction()[0] << " " << vechits[i].Direction()[1] << " " << vechits[i].Direction()[2] << " " << std::endl;
204  // }
205  // }
206 
207  // look for conversions with two tracks that have been joined together and split them in two.
208 
209  std::vector<size_t> identified_conversions; // index into vhclusters of identified conversions
210  std::vector< std::vector< size_t > > splitclus1; // vhcluster for one leg after split
211  std::vector< std::vector< size_t > > splitclus2; // vhcluster for the other leg after split
212 
213  for (size_t iclus=0; iclus<vhclusters.size(); ++iclus)
214  {
215  //std::cout << "testing for a conversion: " << iclus << " " << vhclusters.size() << std::endl;
216  std::vector<size_t> scc1;
217  std::vector<size_t> scc2;
218  if (conversion_test_split(vechits, vhclusters.at(iclus), scc1, scc2))
219  {
220  identified_conversions.push_back(iclus);
221  splitclus1.push_back(scc1);
222  splitclus2.push_back(scc2);
223  }
224  }
225 
226  // rearrange the cluster list -- put the two legs separately in the list, replacing the incorrectly-merged one
227 
228  for (size_t icc=0; icc<identified_conversions.size(); ++icc)
229  {
230  //std::cout << "convrep: " << icc << " " << identified_conversions.at(icc) << " " << vhclusters.size() << std::endl;
231  //std::cout
232  // << "tpcpatrec2: replacing a cluster of size: "
233  // << vhclusters.at(identified_conversions.at(icc)).size()
234  // << " with one of size: " << splitclus1.at(icc).size()
235  // << " and one of size: " << splitclus2.at(icc).size()
236  // << std::endl;
237  vhclusters.at(identified_conversions.at(icc)) = splitclus1.at(icc);
238  vhclusters.push_back(splitclus2.at(icc));
239  }
240 
241 
242  // make a local list of TPCClusters for each track and find initial track parameters
243  for (size_t iclus=0; iclus < vhclusters.size(); ++iclus)
244  {
245  std::vector<gar::rec::TPCCluster> TPCClusters;
246  std::vector<art::Ptr<gar::rec::TPCCluster> > TPCClusterptrs;
247  for (size_t ivh=0; ivh<vhclusters[iclus].size(); ++ivh)
248  {
249  for (size_t iTPCCluster=0; iTPCCluster<TPCClustersFromVecHits.at(vhclusters[iclus][ivh]).size(); ++iTPCCluster)
250  {
251  TPCClusterptrs.push_back(TPCClustersFromVecHits.at(vhclusters[iclus][ivh]).at(iTPCCluster));
252  TPCClusters.push_back(*TPCClusterptrs.back());
253  }
254  }
255 
256  if (TPCClusters.size() >= fMinNumTPCClusters)
257  {
258  gar::rec::TrackPar trackpar;
259  if ( makepatrectrack(TPCClusters,trackpar) == 0 )
260  {
261  trkCol->push_back(trackpar.CreateTrack());
262  auto const trackpointer = trackPtrMaker(trkCol->size()-1);
263  for (size_t iTPCCluster=0; iTPCCluster<TPCClusters.size(); ++iTPCCluster)
264  {
265  TPCClusterTrkAssns->addSingle(TPCClusterptrs.at(iTPCCluster),trackpointer);
266  }
267  for (size_t ivh=0; ivh<vhclusters[iclus].size(); ++ivh)
268  {
269  auto const vhpointer = vhPtrMaker(ivh);
270  vhTrkAssns->addSingle(vhpointer,trackpointer);
271  }
272  }
273  }
274  }
275 
276  e.put(std::move(trkCol));
277  e.put(std::move(vhTrkAssns));
278  e.put(std::move(TPCClusterTrkAssns));
279 
280  }
281 
282 
283  bool tpcpatrec2::vhclusmatch(const std::vector<gar::rec::VecHit> &vechits, std::vector<size_t> &cluster, size_t vhindex)
284  {
285  gar::rec::VecHit vh = vechits[vhindex];
286  TVector3 vhdir(vh.Direction());
287  TVector3 vhpos(vh.Position());
288 
289  bool foundmatch = false;
290  for (size_t ivh=0; ivh<cluster.size(); ++ivh)
291  {
292  gar::rec::VecHit vhtest = vechits[cluster[ivh]];
293  TVector3 vhtestdir(vhtest.Direction());
294  TVector3 vhtestpos(vhtest.Position());
295 
296  if (fPrintLevel > 1)
297  {
298  std::cout << "Testing vh " << ivh << " in a cluster of size: " << cluster.size() << std::endl;
299  }
300 
301  // require the two VH's directions to point along each other -- use dot product
302 
303  if (TMath::Abs((vhdir).Dot(vhtestdir)) < fVecHitMatchCos)
304  {
305  if (fPrintLevel > 1)
306  {
307  std::cout << " Dot failure: " << TMath::Abs((vhdir).Dot(vhtestdir)) << std::endl;
308  }
309  continue;
310  }
311 
312  // require the positions to be within fVecHitMatchPos of each other
313 
314  if ((vhpos-vhtestpos).Mag() > fVecHitMatchPos)
315  {
316  if (fPrintLevel > 1)
317  {
318  std::cout << " Pos failure: " << (vhpos-vhtestpos).Mag() << std::endl;
319  }
320  continue;
321  }
322 
323  // require the extrapolation of one VH's line to another VH's center to match up. Do for
324  // both VH's.
325 
326  if ( ((vhpos-vhtestpos).Cross(vhdir)).Mag() > fVecHitMatchPEX )
327  {
328  if (fPrintLevel > 1)
329  {
330  std::cout << "PEX failure: " << ((vhpos-vhtestpos).Cross(vhdir)).Mag() << std::endl;
331  }
332  continue;
333  }
334  if ( ((vhpos-vhtestpos).Cross(vhtestdir)).Mag() > fVecHitMatchPEX )
335  {
336  if (fPrintLevel > 1)
337  {
338  std::cout << "PEX failure: " << ((vhpos-vhtestpos).Cross(vhtestdir)).Mag() << std::endl;
339  }
340  continue;
341  }
342 
343  float eta = calceta2d(vhtest,vh);
344 
345  if ( eta > fVecHitMatchEta )
346  {
347  if (fPrintLevel > 1)
348  {
349  std::cout << "Eta failure: " << eta << std::endl;
350  }
351  continue;
352  }
353 
354 
355  //----------------
356  // lambda requirement
357 
358  float vhpd = TMath::Sqrt( TMath::Sq(vhdir.Y()) + TMath::Sq(vhdir.Z()) );
359  float vhxd = TMath::Abs( vhdir.X() );
360  float vhlambda = TMath::Pi()/2.0;
361  if (vhpd >0) vhlambda = TMath::ATan(vhxd/vhpd);
362 
363  float cvhpd = TMath::Sqrt( TMath::Sq(vhtestdir.Y()) + TMath::Sq(vhtestdir.Z()) );
364  float cvhxd = TMath::Abs( vhtestdir.X() );
365  float cvhlambda = TMath::Pi()/2.0;
366  if (cvhpd >0) cvhlambda = TMath::ATan(cvhxd/cvhpd);
367 
368  if ( TMath::Abs(vhlambda - cvhlambda) > fVecHitMatchLambda )
369  {
370  if (fPrintLevel > 1)
371  {
372  std::cout << "dlambda failure: " << vhlambda << " " << cvhlambda << std::endl;
373  }
374  continue;
375  }
376 
377  if ( vhdir.Dot(vhtestdir) * vhdir.X() * vhtestdir.X() < 0 &&
378  TMath::Abs(vhdir.X()) > 0.01 && TMath::Abs(vhtestdir.X()) > 0.01)
379  {
380  if (fPrintLevel > 1)
381  {
382  std::cout << "lambda sign failure" << std::endl;
383  }
384  continue;
385  }
386 
387  if (fPrintLevel > 1)
388  {
389  std::cout << " vh cluster match " << std::endl;
390  }
391  foundmatch = true;
392  }
393  if (!foundmatch)
394  {
395  return false;
396  }
397  else
398  {
399  // we have a match, but let's check it to see if we should discard it because there's a
400  // close-by mismatch, which happens when a photon converts
401  // the above loop stops when we find a match, but this time we want to go through
402  // all the VH's in the cluster and check them, so new loop.
403 
404  // for (size_t ivh=0; ivh<cluster.size(); ++ivh)
405  // {
406  // gar::rec::VecHit vhtest = vechits[cluster[ivh]];
407  // TVector3 vhtestpos(vhtest.Position());
408 
409  // // look for close-by VH's with an eta mismatch
410  // if ((vhpos-vhtestpos).Mag() < fCloseEtaUnmatch)
411  // {
412  // float eta = calceta2d(vhtest,vh);
413  // if ( eta > fVecHitMatchEta )
414  // {
415  // return false;
416  // }
417  // }
418  // }
419 
420  }
421  return true;
422  }
423 
424  // rough estimate of track parameters -- both ends
425 
426  int tpcpatrec2::makepatrectrack(std::vector<gar::rec::TPCCluster> &trackTPCClusters, gar::rec::TrackPar &trackpar)
427  {
428  // track parameters: x is the independent variable
429  // 0: y
430  // 1: z
431  // 2: curvature
432  // 3: phi
433  // 4: lambda = angle from the cathode plane
434  // 5: x /// added on to the end
435 
436 
437  float lengthforwards = 0;
438  std::vector<int> hlf;
439  float lengthbackwards = 0;
440  std::vector<int> hlb;
441 
442  if (fSortAlg == 1)
443  {
444  gar::rec::sort_TPCClusters_along_track(trackTPCClusters,hlf,hlb,fPrintLevel,lengthforwards,lengthbackwards,fSortTransWeight,fSortDistBack);
445  }
446  else if (fSortAlg == 2)
447  {
448  gar::rec::sort_TPCClusters_along_track2(trackTPCClusters,hlf,hlb,fPrintLevel,lengthforwards,lengthbackwards,fSortDistCut);
449  }
450  else
451  {
452  throw cet::exception("tpcpatrec2_module") << "Sort Algorithm switch not understood: " << fSortAlg;
453  }
454 
455 
456 
457  std::vector<float> tparbeg(6,0);
458  float xother = 0;
459  if ( gar::rec::initial_trackpar_estimate(trackTPCClusters, hlf, tparbeg[2], tparbeg[4],
460  tparbeg[3], tparbeg[5], tparbeg[0], tparbeg[1], xother, fInitialTPNTPCClusters, fPrintLevel) != 0)
461  {
462  return 1;
463  }
464 
465  std::vector<float> tparend(6,0);
466  if ( gar::rec::initial_trackpar_estimate(trackTPCClusters, hlb, tparend[2], tparend[4],
467  tparend[3], tparend[5], tparend[0], tparend[1], xother, fInitialTPNTPCClusters, fPrintLevel) != 0)
468  {
469  return 1;
470  }
471 
472  // no chisquare or covariance in patrec tracks
473  float covmatbeg[25];
474  float covmatend[25];
475  for (size_t i=0; i<25; ++i) // no covmat in patrec tracks
476  {
477  covmatend[i] = 0;
478  covmatbeg[i] = 0;
479  }
480 
481  trackpar.setNTPCClusters(trackTPCClusters.size());
482  trackpar.setTime(0);
483  trackpar.setChisqForwards(0);
484  trackpar.setChisqBackwards(0);
485  trackpar.setLengthForwards(lengthforwards);
486  trackpar.setLengthBackwards(lengthbackwards);
487  trackpar.setCovMatBeg(covmatbeg);
488  trackpar.setCovMatEnd(covmatend);
489  trackpar.setTrackParametersBegin(tparbeg.data());
490  trackpar.setXBeg(tparbeg[5]);
491  trackpar.setTrackParametersEnd(tparend.data());
492  trackpar.setXEnd(tparend[5]);
493 
494  return 0;
495  }
496 
497 
498  // compute a 2D eta
499 
501  {
502  // normalized direction vector for the VH under test, just the components
503  // perpendicular to X
504 
505  TVector3 vhtestdir(vhtest.Direction());
506  TVector3 vhtestpos(vhtest.Position());
507  TVector3 vhdir(vh.Direction());
508  TVector3 vhpos(vh.Position());
509 
510  TVector3 vhdp(vhdir);
511  vhdp.SetX(0);
512  float norm = vhdp.Mag();
513  if (norm > 0) vhdp *= (1.0/norm);
514 
515  // same for the VH in the cluster under test
516 
517  TVector3 vhcp(vhtestdir);
518  vhcp.SetX(0);
519  norm = vhcp.Mag();
520  if (norm > 0) vhcp *= (1.0/norm);
521 
522  float relsign = 1.0;
523  if (vhdp.Dot(vhcp) < 0) relsign = -1;
524 
525  TVector3 dcent = vhpos-vhtestpos;
526  dcent.SetX(0);
527 
528  TVector3 avgdir1 = 0.5*(vhdp + relsign*vhcp);
529  float amag = avgdir1.Mag();
530  if (amag != 0) avgdir1 *= 1.0/amag;
531  float eta = (dcent.Cross(avgdir1)).Mag();
532  return eta;
533 
534  }
535 
536  // test to see if a cluster looks like a conversion and split it in two if it does. Returns true
537  // if the cluster is identified as a conversion.
538 
539  bool tpcpatrec2::conversion_test_split(const std::vector<gar::rec::VecHit> &vechits,
540  std::vector<size_t> &cluster,
541  std::vector<size_t> &splitclus1,
542  std::vector<size_t> &splitclus2)
543  {
544 
545  //std::cout << "in conversion_test_split " << vechits.size() << " " << cluster.size() << std::endl;
546  splitclus1.clear();
547  splitclus2.clear();
548 
549  // find the VH the farthest away from all the others as an approximation of the end of one of the legs of the
550  // conversion candidate.
551 
552  double dsummax=0;
553  size_t ivhend=0;
554  for (size_t ivh=0; ivh<cluster.size(); ++ivh)
555  {
556  TVector3 vhpos(vechits.at(cluster.at(ivh)).Position());
557  double dsum = 0;
558  for (size_t jvh=0; jvh<cluster.size(); ++jvh)
559  {
560  if (ivh == jvh) continue;
561  TVector3 vhpos2(vechits.at(cluster.at(jvh)).Position());
562  gar::rec::VecHit vh1 = vechits.at(cluster.at(jvh));
563  gar::rec::VecHit vh2 = vechits.at(cluster.at(ivh));
564  dsum += calceta2d(vh1,vh2);
565  dsum += (vhpos-vhpos2).Mag();
566  }
567  //std::cout << "Looking for end: " << cluster.at(ivh) << " " << vhpos.X() << " " << vhpos.Y() << " " << vhpos.Z() << " " << dsum << std::endl;
568  if (dsum > dsummax)
569  {
570  ivhend = ivh; // this is an index into cluster
571  dsummax = dsum;
572  //std::cout << "This is the new max" << std::endl;
573  }
574  }
575  if (dsummax == 0) return(false);
576 
577  // step along the cluster, looking for the closest vh not on the list yet, and identify places where we turn around
578  // and backtrack.
579 
580  std::vector<size_t> already; // already looked at vh list
581  std::set<size_t> yet; // set of vector hits yet to look at.
582 
583  size_t ivhlast = 0; // the last one looked at -- index into vechits
584 
585  for(size_t ivh=0; ivh<cluster.size(); ++ivh)
586  {
587  if (ivh == ivhend)
588  {
589  ivhlast = cluster.at(ivh);
590  already.push_back(ivhlast);
591  //std::cout << " pushed " << ivhlast << " to already" << std::endl;
592  }
593  else
594  {
595  yet.insert(cluster.at(ivh));
596  }
597  }
598 
599  TVector3 lastpdir(0,0,0); // direction in which we're going. Don't know yet, and the VH's
600  //have a two-fold ambiguity as to what that means
601 
602  TVector3 lastpos(vechits.at(ivhlast).Position()); // position of ivhlast
603  gar::rec::VecHit lastvhdp = vechits.at(ivhlast); // save for calculating eta
604 
605  while(yet.size() > 0)
606  {
607 
608  // find which VH in the yet-to-be-looked-at pile that is most likely the "next" one.
609  // choose the closest vechit that satisfies all the matching criteria.
610 
611  float dmin = 0;
612  bool foundmin = false;
613  size_t inext=0;
614  for (auto iyet : yet)
615  {
616  TVector3 testpos(vechits.at(iyet).Position());
617  TVector3 testdir(vechits.at(iyet).Direction());
618  gar::rec::VecHit testvhdp = vechits.at(iyet);
619  float dtest = (lastpos - testpos).Mag() + calceta2d(lastvhdp,testvhdp);
620  if (dtest < dmin || !foundmin)
621  {
622  foundmin = true;
623  dmin = dtest;
624  inext = iyet;
625  }
626  }
627  if (!foundmin) return(false);
628  TVector3 nextpos(vechits.at(inext).Position());
629  TVector3 nextdir(vechits.at(inext).Direction());
630  if (lastpdir.Mag() > 1E-3)
631  {
632  TVector3 testpdir = nextpos - lastpos;
633  //std::cout << "Angle check for a conversion: " << testpdir.Angle(lastpdir) << std::endl;
634  if (testpdir.Angle(lastpdir) > fConvAngleCut)
635  {
636  // we turned around -- found a conversion.
637  splitclus1 = already;
638  for (auto iyet : yet)
639  {
640  splitclus2.push_back(iyet);
641  }
642  //std::cout << "Found a conversion" << std::endl;
643  return(true);
644  }
645  }
646  lastpdir = nextpos - lastpos;
647  already.push_back(inext);
648  //std::cout << " pushed " << inext << " to already" << std::endl;
649  yet.erase(inext);
650  lastpos = nextpos;
651  lastvhdp = vechits.at(inext);
652  //std::cout << "conv hunting: " << lastpos.X() << " " << lastpos.Y() << " " << lastpos.Z() << std::endl;
653  }
654  return(false);
655  }
656 
658 
659 
660  } // namespace rec
661 } // namespace gar
void setNTPCClusters(const size_t nTPCClusters)
Definition: TrackPar.cxx:214
size_t fMinNumTPCClusters
minimum number of hits for a patrec track
void setLengthForwards(const float lengthforwards)
Definition: TrackPar.cxx:251
rec
Definition: tracks.py:88
int fPrintLevel
debug printout: 0: none, 1: selected, 2: all
const float * Position() const
Definition: VecHit.h:47
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
tpcpatrec2(fhicl::ParameterSet const &p)
void setLengthBackwards(const float lengthbackwards)
Definition: TrackPar.cxx:256
Cluster finding and building.
float fSortDistCut
distance cut to pass to hit sorting algorithm #2
const float * Direction() const
Definition: VecHit.h:48
std::string fVecHitLabel
label of module to get the vector hits and associations with hits
void setTrackParametersBegin(const float *tparbeg)
Definition: TrackPar.cxx:219
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
def move(depos, offset)
Definition: depos.py:107
bool vhclusmatch(const std::vector< gar::rec::VecHit > &vechits, std::vector< size_t > &cluster, size_t vh)
void setXEnd(const float xend)
Definition: TrackPar.cxx:276
void setTrackParametersEnd(const float *tparend)
Definition: TrackPar.cxx:227
float calceta2d(gar::rec::VecHit &vhtest, gar::rec::VecHit &vh)
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
float fVecHitMatchEta
matching condition for pairs of vector hits – eta match (cm)
unsigned int fInitialTPNTPCClusters
number of hits to use for initial trackpar estimate, if present
void setChisqBackwards(const float chisqbackwards)
Definition: TrackPar.cxx:266
gar::rec::Track CreateTrack()
Definition: TrackPar.cxx:292
auto norm(Vector const &v)
Return norm of the specified vector.
bool conversion_test_split(const std::vector< gar::rec::VecHit > &vechits, std::vector< size_t > &cluster, std::vector< size_t > &splitclus1, std::vector< size_t > &splitclus2)
float fConvAngleCut
cut on angle diff for the conversion finder to split a cluster of VH&#39;s into two tracks ...
float fCloseEtaUnmatch
distance to look for vector hits that don&#39;t match in eta.
General GArSoft Utilities.
int makepatrectrack(std::vector< gar::rec::TPCCluster > &tpcclusters, gar::rec::TrackPar &trackpar)
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
float fVecHitMatchLambda
matching condition for pairs of vector hits – dLambda (radians)
int fSortAlg
which hit sorting alg to use. 1: old, 2: greedy distance sort
float fSortTransWeight
for use in the hit sorting algorithm – transverse distance weight factor
tpcpatrec2 & operator=(tpcpatrec2 const &)=delete
void setChisqForwards(const float chisqforwards)
Definition: TrackPar.cxx:261
float fVecHitMatchPEX
matching condition for pairs of vector hits – miss distance (cm)
float fVecHitMatchCos
matching condition for pairs of vector hits cos angle between directions
float fSortDistBack
for use in the hit sorting algorithm – how far to go back before raising the distance figure of meri...
float fVecHitMatchPos
matching condition for pairs of vector hits – 3D distance (cm)
void setTime(const double time)
Definition: TrackPar.cxx:281
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
void produce(art::Event &e) override
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