LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
FeatureVertexFinder_module.cc
Go to the documentation of this file.
1 //
3 // FeatureVertexFinder class
4 //
5 // jasaadi@fnal.gov
6 //
7 // This algorithm is designed to reconstruct the vertices using the
8 // 2D cluster information and CornerFinderAlg to find 2-d and 3-d verticies
9 //
10 // 06/05/14
11 // This is a major rewrite of the original code and will be factored to take
12 // advantage of improvements in LArSoft. The code now goes something like this:
13 //
14 // 1)Take up EndPoint2d's from Cluster Crawler and keep ones that make sense in 3d
15 // (this algorithm wants ClusterCrawler to have been run, but should totally work
16 // even if it hasn't)
17 //
18 // 2)Take up all EndPoint2d's from the image finding CornerFinder algorithm
19 // (this algortithm wants CornerFinder to have been run, but should totally work
20 // even if it hasn't)
21 //
22 // 3)Take up an additional clustering algorithm (dBcluster by default but can work
23 // with any clustering algorithm) and use slopes and endpoints to find intersections
24 //
25 // 4)Now merge together any duplicates and sort them by their weight (which needs its units still
26 // decided somehow)
27 //
28 // 5)Return a list of verticies based on what mode you run this algorithm in
29 // a) Primary mode: This mode will return only a single 3d vertex and an appropriate
30 // number of EndPoint2d's corresponding to the most likely neutrino vertex
31 // b) All mode: This mode returns all 3d/2d verticies that this algorithm has found but
32 // sorts the list by the most likely candidate
33 //
34 //
35 //
36 // This is Preliminary Work and needs modifications
37 //
38 // ////////////////////////////////////////////////////////////////////////
39 
40 // Basic C++ Includes
41 #include <cmath>
42 #include <iomanip>
43 #include <iostream>
44 #include <string>
45 
46 // Framework Includes
55 #include "fhiclcpp/ParameterSet.h"
57 
58 // LArSoft Includes
71 
72 // ROOT Includes
73 #include "TF1.h"
74 #include "TGraph.h"
75 
76 namespace vertex {
77 
79  public:
80  explicit FeatureVertexFinder(fhicl::ParameterSet const& pset);
81 
82  private:
83  void produce(art::Event& evt) override;
84 
85  // This function will take in and EndPoint2d from either cluster crawler or corner
86  // finder and only save points that make a 3d-candidate
88  std::vector<art::Ptr<recob::EndPoint2D>> const& EndPoints,
89  bool PlaneDet);
90 
91  // This function will take in 2d Clusters (by default dBCluster) and return 2d vertex
92  // candidates for sorting later
96 
97  // This function takes in 2d Vertex candidates (found by
98  // Find2dClusterVertexCandidates), does some basic merging and then finds
99  // 3d-candidates for use later
101  std::vector<double> const& Wire_2dvtx,
102  std::vector<double> const& Time_2dvtx,
103  std::vector<double> const& Plane_2dvtx);
104 
105  // This function merges and sorts all the 3d vertex candidates, it merges them if they
106  // are within 2.0 cm in X, Y, and Z simultaneously and then sorts the list by vertex
107  // strength and Z location (lowest Z is first on the list
108  void MergeAndSort3dVtxCandidate(std::vector<double> const& merge_vtxX,
109  std::vector<double> const& merge_vtxY,
110  std::vector<double> const& merge_vtxZ,
111  std::vector<double> const& merge_vtxStgth);
112 
113  std::string fClusterModuleLabel;
114  std::string fHitModuleLabel;
117  Double_t fRunningMode;
118 
119  bool GT2PlaneDetector = false;
120 
121  // Unsorted Raw list of 3d-Vertex candidates filled
122  std::vector<double> candidate_x = {0.};
123  std::vector<double> candidate_y = {0.};
124  std::vector<double> candidate_z = {0.};
125  std::vector<double> candidate_strength = {0.};
126 
127  // Merged and sorted list of 3d-Vertex candidates filled
128  std::vector<double> MergeSort3dVtx_xpos = {0.};
129  std::vector<double> MergeSort3dVtx_ypos = {0.};
130  std::vector<double> MergeSort3dVtx_zpos = {0.};
131  std::vector<double> MergeSort3dVtx_strength = {0.};
132 
133  // 2d Cluster based Variables
134  std::vector<std::vector<int>> Cls; //<---- Index to clusters in each view
135  std::vector<double> dtdwstart = {0.}; //<----Slope (delta Time Tick vs delta Wire)
136  std::vector<double> dtdwstartError = {0.}; //<---Error on the slope
137  std::vector<double> Clu_Plane = {0.}; //<---Plane of the current cluster
138  std::vector<double> Clu_StartPos_Wire = {0.}; //<---Starting wire number of cluster
139  std::vector<double> Clu_StartPos_TimeTick = {0.}; //<---Starting TDC value of the cluster
140 
141  std::vector<double> Clu_EndPos_Wire = {0.}; //<---Ending wire number of cluster
142  std::vector<double> Clu_EndPos_TimeTick = {0.}; //<---Ending TDC value of the cluster
143 
144  std::vector<double> Clu_Slope = {0.}; //<---Calculated Slope of the cluster (TDC/Wire)
145  std::vector<double> Clu_Yintercept = {0.}; //<---Clusters Y Intercept using start positions
146  std::vector<double> Clu_Yintercept2 = {0.}; //<---Clusters Y Intercept using end positions
147  std::vector<double> Clu_Length = {0.}; //<---Calculated Length of the cluster
148 
149  // 2d Cluster based verticies
150  std::vector<double> TwoDvtx_wire = {0.};
151  std::vector<double> TwoDvtx_time = {0.};
152  std::vector<double> TwoDvtx_plane = {0.};
153  };
154 
155 } //<---End namespace vertex
156 
157 namespace vertex {
158 
160  {
161  fCornerFinderModuleLabel = pset.get<std::string>("CornerFinderModuleLabel");
162  fClusterModuleLabel = pset.get<std::string>("ClusterModuleLabel");
163  fHitModuleLabel = pset.get<std::string>("HitModuleLabel");
164  fCCrawlerEndPoint2dModuleLabel = pset.get<std::string>("CCrawlerEndPoint2dModuleLabel");
165  fRunningMode = pset.get<double>("RunningMode");
166 
167  produces<std::vector<recob::Vertex>>();
168  produces<std::vector<recob::EndPoint2D>>();
169  produces<art::Assns<recob::EndPoint2D, recob::Hit>>();
170 
171  // === Don't think I'll actually have any of these associations ===
172  // === should consider removing in the future
173  produces<art::Assns<recob::Vertex, recob::Hit>>();
174  produces<art::Assns<recob::Vertex, recob::Shower>>();
175  produces<art::Assns<recob::Vertex, recob::Track>>();
176 
177  Cls.resize(art::ServiceHandle<geo::WireReadout const>()->Get().Nplanes(), std::vector<int>());
178  }
179 
180  // -----------------------------------------------------------------------------
182  {
184  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
185  auto const detProp =
187 
188  // Figuring out if I have a 2 or 3 plane detector
189  GT2PlaneDetector = false;
190 
191  for (auto const& tpcid : geom->Iterate<geo::TPCID>()) {
192  if (wireReadoutGeom.Nplanes(tpcid) > 2) {
193  GT2PlaneDetector = true;
194  std::cout << "yeah" << std::endl;
195  break;
196  }
197  }
198 
199  // These are the things I want to put on the event
200  auto vcol = std::make_unique<std::vector<recob::Vertex>>(); // 3D vertex
201  auto epcol = std::make_unique<std::vector<recob::EndPoint2D>>(); // 2D vertex
202  auto assnep = std::make_unique<art::Assns<recob::EndPoint2D, recob::Hit>>();
203  auto assnsh = std::make_unique<art::Assns<recob::Vertex, recob::Shower>>();
204  auto assntr = std::make_unique<art::Assns<recob::Vertex, recob::Track>>();
205  auto assnh = std::make_unique<art::Assns<recob::Vertex, recob::Hit>>();
206 
207  // ClusterCrawler
208 
209  // Getting the EndPoint2d's for cluster crawler
210 
211  try {
212  art::Handle<std::vector<recob::EndPoint2D>> ccrawlerFinderHandle;
213  evt.getByLabel(fCCrawlerEndPoint2dModuleLabel, ccrawlerFinderHandle);
214  std::vector<art::Ptr<recob::EndPoint2D>> ccrawlerEndPoints;
215  art::fill_ptr_vector(ccrawlerEndPoints, ccrawlerFinderHandle);
216 
217  // Passing in the EndPoint2d's from Cluster Crawler
218  Get3dVertexCandidates(detProp, ccrawlerEndPoints, GT2PlaneDetector);
219  }
220  catch (...) {
221  mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Cluster Crawler";
222  }
223 
224  // CornerFinder EndPoint2d's
225 
226  // Getting the EndPoint2d's for Corner Finder
227  try {
228  art::Handle<std::vector<recob::EndPoint2D>> CornerFinderHandle;
229  evt.getByLabel(fCornerFinderModuleLabel, CornerFinderHandle);
230  std::vector<art::Ptr<recob::EndPoint2D>> cornerEndPoints;
231  art::fill_ptr_vector(cornerEndPoints, CornerFinderHandle);
232 
233  // Passing in the EndPoint2d's from Corner Finder
234  Get3dVertexCandidates(detProp, cornerEndPoints, GT2PlaneDetector);
235  }
236  catch (...) {
237  mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Corner Finder";
238  }
239 
240  // Making Cluster Slope EndPoint2d's
241 
242  // Retrieving the Cluster Module for the event
243  try {
244  art::Handle<std::vector<recob::Cluster>> clusterListHandle;
245  evt.getByLabel(fClusterModuleLabel, clusterListHandle);
246 
247  // Finding hits associated with the clusters
248  art::FindManyP<recob::Hit> fmh(clusterListHandle, evt, fClusterModuleLabel);
249 
250  // Filling the Cluster Vector
252  for (unsigned int ii = 0; ii < clusterListHandle->size(); ++ii) {
253  art::Ptr<recob::Cluster> clusterHolder(clusterListHandle, ii);
254  clusters.push_back(clusterHolder);
255  }
256 
257  // Passing in the clusters to find 2d Vertices
258  Find2dClusterVertexCandidates(detProp, clusters, fmh);
259 
260  // Finding 3d Candidates from 2d cluster vertex candidates
262  }
263  catch (...) {
264  mf::LogWarning("FeatureVertexFinder") << "Failed to get Cluster from default cluster module";
265  }
266 
267  // Merging and sorting 3d vertex candidates
269 
270  // Putting Vertices on the event
271  // -----------------------------------------------------------------------------------
272  // Now that I have a list of 3d vertex candidates I will return 3d/2d vertices based
273  // on which option the user has chosen fRunningMode == 0 (this returns a full list of
274  // all 3d/2d vertex candidates) fRunningMode == 1 (this returns only one vertex which
275  // is established as the most likely primary)
276 
277  // Returning all vertex candidates
278  if (fRunningMode == 0) {
279 
280  // Looping over Primary Verticies
281  for (size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++) {
282 
283  // Push each primary vertex onto the event
284 
285  double tempxyz[3] = {
287 
288  // Skipping a vertex that is zero
289 
290  if (tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0) { continue; }
291  recob::Vertex the3Dvertex(tempxyz, vcol->size());
292  vcol->push_back(the3Dvertex);
293 
294  // ---------------------------------------------------------------------
295  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
296  // ---------------------------------------------------------------------
297 
298  for (auto const& plane : wireReadoutGeom.Iterate<geo::PlaneGeo>()) {
299  auto const& planeID = plane.ID();
300  geo::Point_t const temp2dXYZ{
301  MergeSort3dVtx_xpos[pri], MergeSort3dVtx_ypos[pri], MergeSort3dVtx_zpos[pri]};
302  double temp2dStrength = MergeSort3dVtx_strength[pri];
303 
304  // Skipping a vertex that is zero
305  if (temp2dXYZ.X() == 0 && temp2dXYZ.Y() == 0 && temp2dXYZ.Z() == 0) { continue; }
306 
307  // Converting the 3d vertex into 2d time ticks, wire, and channel
308  double EndPoint2d_TimeTick = detProp.ConvertXToTicks(temp2dXYZ.X(), planeID);
309  int EndPoint2d_Wire = 0;
310  int EndPoint2d_Channel = 0;
311 
312  // Putting in protection in case NearestWire Fails
313  try {
314  EndPoint2d_Wire = plane.NearestWireID(temp2dXYZ).Wire;
315  }
316  catch (...) {
317  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
318  continue;
319  }
320  // Putting in protection in case NearestChannel Fails
321  try {
322  EndPoint2d_Channel = wireReadoutGeom.NearestChannel(temp2dXYZ, planeID);
323  }
324  catch (...) {
325  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
326  continue;
327  }
328 
329  // Making geo::WireID and getting the current View number
330  geo::View_t View = wireReadoutGeom.View(EndPoint2d_Channel);
331  geo::WireID wireID(planeID, EndPoint2d_Wire);
332 
333  // Putting the 2d Vertex found on the event
334  epcol->emplace_back(EndPoint2d_TimeTick, //<---TimeTick
335  wireID, //<---geo::WireID
336  temp2dStrength, //<---Vtx strength (JA: ?)
337  epcol->size(), //<---Vtx ID (JA: ?)
338  View, //<---Vtx View
339  1); //<---Total Charge (JA: Need to figure this one?)
340 
341  } //<---End Plane loop
342  } //<---End pri loop
343  } //<---End fRunningMode == 0
344 
345  // ================================================
346  // === Returning only primary vertex candidates ===
347  // ================================================
348  if (fRunningMode != 0) {
349  int position = 0;
350  int bail = 0;
351 
352  // Looping over Primary Verticies
353  for (size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++) {
354 
355  // Push each primary vertex onto the event
356  double tempxyz[3] = {
358 
359  // Skipping a vertex that is zero
360  if (bail > 0) { continue; }
361  if (tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0) { continue; }
362  position = pri;
363  bail++;
364  vcol->emplace_back(tempxyz, vcol->size());
365  }
366 
367  // ---------------------------------------------------------------------
368  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
369  // ---------------------------------------------------------------------
370 
371  // Looping over cryostats
372  for (auto const& plane : wireReadoutGeom.Iterate<geo::PlaneGeo>()) {
373  auto const& planeID = plane.ID();
374  geo::Point_t const temp2dXYZ{MergeSort3dVtx_xpos[position],
375  MergeSort3dVtx_ypos[position],
376  MergeSort3dVtx_zpos[position]};
377  double temp2dStrength = MergeSort3dVtx_strength[position];
378 
379  // Converting the 3d vertex into 2d time ticks, wire, and channel
380  double EndPoint2d_TimeTick = detProp.ConvertXToTicks(temp2dXYZ.X(), planeID);
381  int EndPoint2d_Wire = 0;
382  int EndPoint2d_Channel = 0;
383  // Putting in protection in case NearestWire Fails
384  try {
385  EndPoint2d_Wire = plane.NearestWireID(temp2dXYZ).Wire;
386  }
387  catch (...) {
388  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
389  continue;
390  }
391  // Putting in protection in case NearestChannel Fails
392  try {
393  EndPoint2d_Channel = wireReadoutGeom.NearestChannel(temp2dXYZ, planeID);
394  }
395  catch (...) {
396  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
397  continue;
398  }
399 
400  // Making geo::WireID and getting the current View number
401  geo::View_t View = wireReadoutGeom.View(EndPoint2d_Channel);
402  geo::WireID wireID(planeID, EndPoint2d_Wire);
403 
404  // Putting the 2d Vertex found on the event
405  epcol->emplace_back(EndPoint2d_TimeTick, //<---TimeTick
406  wireID, //<---geo::WireID
407  temp2dStrength, //<---Vtx strength (JA: ?)
408  epcol->size(), //<---Vtx ID (JA: ?)
409  View, //<---Vtx View
410  1); //<---Total Charge (JA: Need to figure this one?)
411 
412  } //<---End Plane loop
413  } //<---End fRunningMode == 1
414 
415  mf::LogVerbatim("Summary") << std::setfill('-') << std::setw(175) << "-" << std::setfill(' ');
416  mf::LogVerbatim("Summary") << "FeatureVertexFinder Summary:";
417  for (size_t i = 0; i < epcol->size(); ++i)
418  mf::LogVerbatim("Summary") << epcol->at(i);
419  for (size_t i = 0; i < vcol->size(); ++i)
420  mf::LogVerbatim("Summary") << vcol->at(i);
421 
422  evt.put(std::move(epcol));
423  evt.put(std::move(vcol));
424  evt.put(std::move(assnep));
425  evt.put(std::move(assntr));
426  evt.put(std::move(assnsh));
427  evt.put(std::move(assnh));
428 
429  // Clearing vectors at the end of the event
430  vcol.reset();
431  epcol.reset();
432  candidate_x.clear();
433  candidate_y.clear();
434  candidate_z.clear();
435  candidate_strength.clear();
436  MergeSort3dVtx_xpos.clear();
437  MergeSort3dVtx_ypos.clear();
438  MergeSort3dVtx_zpos.clear();
439  MergeSort3dVtx_strength.clear();
440  dtdwstart.clear();
441  dtdwstartError.clear();
442  Clu_Plane.clear();
443  Clu_StartPos_Wire.clear();
444  Clu_StartPos_TimeTick.clear();
445  Clu_EndPos_Wire.clear();
446  Clu_EndPos_TimeTick.clear();
447  Clu_Slope.clear();
448  Clu_Yintercept.clear();
449  Clu_Yintercept2.clear();
450  Clu_Length.clear();
451  TwoDvtx_wire.clear();
452  TwoDvtx_time.clear();
453  TwoDvtx_plane.clear();
454 
455  } //<--End FeatureVertexFinder::produce
456 
457  // -----------------------------------------------------------------------------
458  // Get 3d Vertex Candidates
459  // -----------------------------------------------------------------------------
461  detinfo::DetectorPropertiesData const& detProp,
462  std::vector<art::Ptr<recob::EndPoint2D>> const& EndPoints,
463  bool PlaneDet)
464  {
466  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
467 
468  auto const numEndPoints = size(EndPoints);
469  for (auto const& tpcid : geom->Iterate<geo::TPCID>()) {
470  for (size_t iendpt1 = 0; iendpt1 < numEndPoints; ++iendpt1) {
471  for (size_t iendpt2 = iendpt1 + 1; iendpt2 < numEndPoints; ++iendpt2) {
472 
473  auto const& endpt1 = *EndPoints[iendpt1];
474  auto const& endpt2 = *EndPoints[iendpt2];
475 
476  geo::PlaneID const endpt1_planeid{tpcid, endpt1.WireID().Plane};
477  geo::PlaneID const endpt2_planeid{tpcid, endpt2.WireID().Plane};
478 
479  // Check to make sure we are comparing features from different planes
480  if (endpt1_planeid.Plane == endpt2_planeid.Plane) continue;
481 
482  // Get the appropriate time offset for the two planes we are considering
483  float tempXFeature1 = detProp.ConvertTicksToX(endpt1.DriftTime(), endpt1_planeid);
484  float tempXFeature2 = detProp.ConvertTicksToX(endpt2.DriftTime(), endpt2_planeid);
485 
486  // Skip features that are not within 0.5 cm in projected X
487  if (std::abs(tempXFeature1 - tempXFeature2) >= 0.5) continue;
488 
489  // Checking to see if these features have intersecting channels
490  geo::WireID const endpt1_wireid{endpt1_planeid, endpt1.WireID().Wire};
491  geo::WireID const endpt2_wireid{endpt2_planeid, endpt2.WireID().Wire};
492 
493  auto intersection =
494  wireReadoutGeom.ChannelsIntersect(wireReadoutGeom.PlaneWireToChannel(endpt1_wireid),
495  wireReadoutGeom.PlaneWireToChannel(endpt2_wireid));
496  if (!intersection) continue;
497 
498  // Use this fill if we are in a detector with fewer than 3 plane (e.g. ArgoNeuT)
499  if (!PlaneDet) {
500  candidate_x.push_back(tempXFeature1);
501  candidate_y.push_back(intersection->y);
502  candidate_z.push_back(intersection->z);
503  candidate_strength.push_back(endpt1.Strength() + endpt2.Strength());
504  continue;
505  } //<---End fill for 2 plane detector
506 
507  // Now need to check for a match across more than 2 planes
508 
509  // Looping over the rest of the list
510 
511  for (size_t iendpt3 = iendpt2 + 1; iendpt3 < numEndPoints; ++iendpt3) {
512  auto const& endpt3 = *EndPoints[iendpt3];
513 
514  geo::PlaneID const endpt3_planeid{tpcid, endpt3.WireID().Plane};
515 
516  // Check to make sure we are comparing features from different planes
517  // N.B. We do not need to check between endpt1 and endpt2 as that has been done above.
518 
519  if (endpt3_planeid.Plane == endpt2_planeid.Plane ||
520  endpt3_planeid.Plane == endpt1_planeid.Plane)
521  continue;
522 
523  // Check to see that the third feature is within 1.0 cm projected in X
524  geo::WireID const endpt3_wireid{endpt3_planeid, endpt3.WireID().Wire};
525  float const tempXFeature3 = detProp.ConvertTicksToX(endpt3.DriftTime(), endpt3_wireid);
526 
527  if (std::abs(tempXFeature3 - tempXFeature2) >= 1.0 ||
528  std::abs(tempXFeature3 - tempXFeature1) >= 1.0) {
529  continue;
530  }
531 
532  // Make sure our third feature has an intersecting channel with our other two channels.
533  if (!wireReadoutGeom.ChannelsIntersect(
534  wireReadoutGeom.PlaneWireToChannel(endpt3_wireid),
535  wireReadoutGeom.PlaneWireToChannel(endpt1_wireid)) ||
536  !wireReadoutGeom.ChannelsIntersect(
537  wireReadoutGeom.PlaneWireToChannel(endpt3_wireid),
538  wireReadoutGeom.PlaneWireToChannel(endpt2_wireid))) {
539  continue;
540  }
541  candidate_x.push_back(
542  detProp.ConvertTicksToX(endpt1.DriftTime(), endpt1_wireid.asPlaneID()));
543 
544  // Finding intersection points
545  auto intersection =
546  wireReadoutGeom.WireIDsIntersect(endpt1_wireid, endpt2_wireid).value();
547  candidate_y.push_back(intersection.y);
548  candidate_z.push_back(intersection.z);
549  candidate_strength.push_back(endpt1.Strength() + endpt2.Strength() + endpt3.Strength());
550 
551  // Note: If I've made it here I have a matched triplet...since I don't want to use any
552  // of these features again I am going to iterate each of the counters so we move to the
553  // next one.
554  if (iendpt1 < numEndPoints) { ++iendpt1; }
555  if (iendpt2 < numEndPoints) { ++iendpt2; }
556  if (iendpt3 < numEndPoints) { ++iendpt3; }
557  } //<---End iendpt3
558  } //<---End iendpt2 loop
559  } //<---End iendpt1 loop
560  } //<---End TPC loop
561  } //<---End Get3dVertexCandidates
562 
563  // -----------------------------------------------------------------------------
564  // Get 2d Vertex Candidates from clusters
565  // -----------------------------------------------------------------------------
567  detinfo::DetectorPropertiesData const& detProp,
568  art::PtrVector<recob::Cluster> RawClusters,
570  {
572  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
573 
574  int nClustersFound = 0;
575 
576  // Initialize Cls
577  for (auto& c : Cls)
578  c.clear();
579 
580  for (size_t iclu = 0; iclu < RawClusters.size(); ++iclu) {
581  // Gathering the hits associated with the current cluster
582  std::vector<art::Ptr<recob::Hit>> hit = fmhit.at(iclu);
583 
584  // I only want to consider this cluster if it has a sufficient number
585  // of hits
586  if (hit.size() < 15) { continue; }
587 
588  // Determine which view the current cluster is in
589 
590  const geo::View_t view = RawClusters.at(iclu)->View();
591  if (view >= Cls.size()) {
592  std::cerr << __PRETTY_FUNCTION__ << "\033[93m Logic error in my code ... view " << view
593  << " not supported ! \033[00m" << std::endl;
594  throw std::exception();
595  }
596 
597  Cls.at(RawClusters.at(iclu)->View()).push_back(iclu);
598 
599  // Filling wires and times into a TGraph for the cluster
600 
601  std::vector<double> wires;
602  std::vector<double> times;
603 
604  // Counting the number of hits in the current cluster (n)
605  int n = 0;
606 
607  // Looping over the hits in the cluster
608 
609  for (size_t i = 0; i < hit.size(); ++i) {
610  wires.push_back(hit[i]->WireID().Wire);
611  times.push_back(hit[i]->PeakTime());
612  ++n;
613  }
614 
615  // If there are 2 or more hits in the cluster fill a TGraph and
616  // fit a from a polynomial or order 1
617 
618  if (n >= 15) {
619 
620  // Push the hits into a TGraph
621 
622  TGraph* the2Dtrack = new TGraph(n, &wires[0], &times[0]);
623  // === Try to fit the TGraph with a 1st order polynomial ===
624  try {
625  the2Dtrack->Fit("pol1", "Q");
626  TF1* pol1 = (TF1*)the2Dtrack->GetFunction("pol1");
627  double par[2];
628  double parerror[2];
629  pol1->GetParameters(par);
630  parerror[1] = pol1->GetParError(1);
631  double FitChi2 = pol1->GetChisquare();
632  double FitNDF = pol1->GetNDF();
633 
634  double fitGoodness = FitChi2 / FitNDF;
635 
636  // Skipping the fitted slope if the Chi2/NDF < 5
637  if (fitGoodness > 10) {
638  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
639  continue;
640  }
641 
642  // Take change in time tick vs change in wire (dT/dW) from the fit
643 
644  dtdwstart.push_back(par[1]);
645  dtdwstartError.push_back(parerror[1]);
646  } //<---End try to fit with a polynomial order 1
647 
648  // If the fitter fails just take dT/dW from the cluster
649  catch (...) {
650  mf::LogWarning("FeatureVertexFinder")
651  << "Fitter failed, using the clusters default dTdW()";
652  delete the2Dtrack;
653  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
654  continue;
655  }
656 
657  delete the2Dtrack;
658  } //<---End if the cluster has 2 or more hits
659 
660  // If the cluster has fewer than 2 hits just take the dT/dW from
661  // the cluster
662 
663  else {
664  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
665  }
666  } //<---End loop over clusters iclu
667 
668  // Now that I have slopes for all the clusters move on to finding
669  // intersection points
670 
671  // Looping over cryostats
672 
673  for (auto const& tpcid : geom->Iterate<geo::TPCID>()) {
674  for (unsigned int i = 0; i < wireReadoutGeom.Nplanes(tpcid); ++i) {
675 
676  // If there is at least one cluster found
677 
678  if (Cls[i].size() >= 1) {
679 
680  // Loop over each cluster
681 
682  for (unsigned int j = 0; j < Cls[i].size(); ++j) {
683  // === Current Clusters Plane ===
684  Clu_Plane.push_back(RawClusters.at(Cls.at(i).at(j))->View());
685  // === Current Clusters StartPos ===
686  Clu_StartPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->StartWire());
687  Clu_StartPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->StartTick());
688  // === Current Clusters EndPos ===
689  Clu_EndPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->EndWire());
690  Clu_EndPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->EndTick());
691  // Current Clusters Slope (In Wire and Time Tick)
692  Clu_Slope.push_back(dtdwstart[Cls[i][j]]);
693  Clu_Length.push_back(std::sqrt(pow((RawClusters.at(Cls.at(i).at(j))->StartWire() -
694  RawClusters.at(Cls.at(i).at(j))->EndWire()) *
695  13.5,
696  2) +
697  pow(RawClusters.at(Cls.at(i).at(j))->StartTick() -
698  RawClusters.at(Cls.at(i).at(j))->EndTick(),
699  2)));
700 
701  // Given a slope and a point find the y-intercept
702  // c = y-mx
703 
704  Clu_Yintercept.push_back(
705  RawClusters.at(Cls.at(i).at(j))->StartTick() -
706  (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->StartWire()));
707 
708  // Also calculating the y-intercept but using the end
709  // time of the cluster correct for the possibility that
710  // the clustering didn't get start and end points right
711 
712  Clu_Yintercept2.push_back(
713  RawClusters.at(Cls.at(i).at(j))->EndTick() -
714  (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->EndWire()));
715 
716  // Iterating on the total number of clusters found
717 
718  nClustersFound++;
719  } //<---End loop over all clusters
720 
721  } //<---End check if we have at least one cluster
722 
723  // If no clusters were found then put in dummy vertex values
724  else {
725  TwoDvtx_wire.push_back(-1);
726  TwoDvtx_time.push_back(-1);
727  TwoDvtx_plane.push_back(-1);
728  }
729 
730  } //<---End loop over planes (i)
731  } //<---End loop over tpc's
732 
733  // Now loop over all the clusters found and establish a
734  // preliminary set of 2d-verticies based on the slope/intercept of
735  // those clusters
736 
737  for (unsigned int n = nClustersFound; n > 0; n--) {
738 
739  // Looping over the clusters starting from the first cluster and
740  // checking against the nCluster
741 
742  for (unsigned int m = 0; m < n; m++) {
743 
744  // Checking to make sure clusters are in the same view
745 
746  if (Clu_Plane[n] == Clu_Plane[m]) {
747  // --- Skip the vertex if the lines slope don't intercept ---
748  if (Clu_Slope[m] - Clu_Slope[n] == 0) { break; }
749 
750  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
751  float intersection_X =
752  (Clu_Yintercept[n] - Clu_Yintercept[m]) / (Clu_Slope[m] - Clu_Slope[n]);
753 
754  // === Y intersection = (slope1 * XInt) + yInt1 ===
755  float intersection_Y = (Clu_Slope[m] * intersection_X) + Clu_Yintercept[m];
756 
757  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
758  float intersection_X2 =
760 
761  // === Y intersection = (slope1 * XInt) + yInt1 ===
762  float intersection_Y2 = (Clu_Slope[m] * intersection_X2) + Clu_Yintercept2[m];
763 
764  // Skipping crap intersection points
765  geo::PlaneID const planeid(0, 0, Clu_Plane[m]);
766  if (intersection_X2 < 1) { intersection_X2 = -999; }
767  if (intersection_X2 > wireReadoutGeom.Nwires(planeid)) { intersection_X2 = -999; }
768  if (intersection_Y2 < 0) { intersection_Y2 = -999; }
769  if (intersection_Y2 > detProp.NumberTimeSamples()) { intersection_Y2 = -999; }
770  if (intersection_X < 1) { intersection_X = -999; }
771  if (intersection_X > wireReadoutGeom.Nwires(planeid)) { intersection_X = -999; }
772  if (intersection_Y < 0) { intersection_Y = -999; }
773  if (intersection_Y > detProp.NumberTimeSamples()) { intersection_Y = -999; }
774 
775  // Putting in a protection for the findManyHit function
776 
777  try {
778  // Gathering the hits associated with the current cluster
779  std::vector<art::Ptr<recob::Hit>> hitClu1 = fmhit.at(m);
780  std::vector<art::Ptr<recob::Hit>> hitClu2 = fmhit.at(n);
781 
782  // If the intersection point is 80 or more wires away from
783  // either cluster and one of the clusters has fewer than 8 hits the
784  // intersection is likely a crap one and we won't save this point
785  if ((abs(Clu_EndPos_Wire[m] - intersection_X2) > 80 && hitClu1.size() < 8) ||
786  (abs(Clu_EndPos_Wire[n] - intersection_X2) > 80 && hitClu2.size() < 8)) {
787  intersection_X2 = -999;
788  intersection_Y2 = -999;
789  }
790 
791  if ((abs(Clu_StartPos_Wire[m] - intersection_X) > 80 && hitClu1.size() < 8) ||
792  (abs(Clu_StartPos_Wire[n] - intersection_X) > 80 && hitClu2.size() < 8)) {
793  intersection_X = -999;
794  intersection_Y = -999;
795  }
796 
797  // If the intersection point is 50 or more wires away from
798  // either cluster and the one of the clusters has fewer than 3 hits
799  // the intersection is likely a crap one and we won't save this
800  // point
801  if ((abs(Clu_EndPos_Wire[m] - intersection_X2) > 50 && hitClu1.size() < 4) ||
802  (abs(Clu_EndPos_Wire[n] - intersection_X2) > 50 && hitClu2.size() < 4)) {
803  intersection_X2 = -999;
804  intersection_Y2 = -999;
805  }
806 
807  if ((abs(Clu_StartPos_Wire[m] - intersection_X) > 50 && hitClu1.size() < 4) ||
808  (abs(Clu_StartPos_Wire[n] - intersection_X) > 50 && hitClu2.size() < 4)) {
809  intersection_X = -999;
810  intersection_Y = -999;
811  }
812  }
813  catch (...) {
814  mf::LogWarning("FeatureVertexFinder") << "FindManyHit Function faild";
815  intersection_X = -999;
816  intersection_Y = -999;
817  intersection_X2 = -999;
818  intersection_Y2 = -999;
819  continue;
820  }
821 
822  // Push back a candidate 2dClusterVertex if it is inside the
823  // detector
824 
825  if (intersection_X2 > 1 && intersection_Y2 > 0 &&
826  (intersection_X2 < wireReadoutGeom.Nwires(planeid)) &&
827  (intersection_Y2 < detProp.NumberTimeSamples())) {
828 
829  TwoDvtx_wire.push_back(intersection_X2);
830  TwoDvtx_time.push_back(intersection_Y2);
831  TwoDvtx_plane.push_back(Clu_Plane[m]);
832  } //<---End saving a "good 2d vertex" candidate
833 
834  // Push back a candidate 2dClusterVertex if it is inside the
835  // detector
836 
837  if (intersection_X > 1 && intersection_Y > 0 &&
838  (intersection_X < wireReadoutGeom.Nwires(planeid)) &&
839  (intersection_Y < detProp.NumberTimeSamples())) {
840  TwoDvtx_wire.push_back(intersection_X);
841  TwoDvtx_time.push_back(intersection_Y);
842  TwoDvtx_plane.push_back(Clu_Plane[m]);
843  } //<---End saving a "good 2d vertex" candidate
844 
845  } //<---End check that they are in differnt planes
846  } //<---End m loop
847  } //<---End n loop
848 
849  } //<---End 2dClusterVertexCandidates
850 
851  // -----------------------------------------------------------------------------
852  // Get 3d Vertex Candidates from clusters 2d Vertex candidates
853  // -----------------------------------------------------------------------------
855  detinfo::DetectorPropertiesData const& detProp,
856  std::vector<double> const& Wire_2dvtx,
857  std::vector<double> const& Time_2dvtx,
858  std::vector<double> const& Plane_2dvtx)
859  {
860  std::vector<double> vtx_wire_merged;
861  std::vector<double> vtx_time_merged;
862  std::vector<double> vtx_plane_merged;
863 
864  bool merged = false;
865 
867 
868  // MERGING THE LONG LIST OF 2D CANDIDATES
869 
870  // Looping over 2d-verticies (loop1)
871 
872  for (size_t vtxloop1 = 0; vtxloop1 < Wire_2dvtx.size(); vtxloop1++) {
873  if (Wire_2dvtx[vtxloop1] < 0) { continue; }
874 
875  merged = false;
876 
877  // Looping over 2d-verticies (loop2)
878 
879  for (size_t vtxloop2 = vtxloop1 + 1; vtxloop2 < Wire_2dvtx.size(); vtxloop2++) {
880  if (Wire_2dvtx[vtxloop2] < 0) { continue; }
881 
882  // Make sure the 2d-Verticies are in the same plane
883  if (Plane_2dvtx[vtxloop1] == Plane_2dvtx[vtxloop2]) {
884 
885  // Considering merging 2d vertices if they are within 3 wires of each other
886  if (fabs(Wire_2dvtx[vtxloop1] - Wire_2dvtx[vtxloop2]) < 4) {
887 
888  // Merge the verticies if they are within 10 time ticks
889  if (fabs(Time_2dvtx[vtxloop1] - Time_2dvtx[vtxloop2]) < 10) {
890  vtx_wire_merged.push_back(((Wire_2dvtx[vtxloop2] + Wire_2dvtx[vtxloop1]) / 2));
891  vtx_time_merged.push_back(((Time_2dvtx[vtxloop2] + Time_2dvtx[vtxloop1]) / 2));
892  vtx_plane_merged.push_back(Plane_2dvtx[vtxloop1]);
893 
894  merged = true;
895  if (vtxloop2 < Wire_2dvtx.size()) { vtxloop2++; }
896  if (vtxloop1 < Wire_2dvtx.size()) { vtxloop1++; }
897  } //<---End the check within 10 time ticks for merging
898  } //<---Looking at vertices that are within 3 wires of each other
899  } //<---Only looking at vertices that are in the same plane
900  } //<---End vtxloop2
901  if (!merged) {
902  vtx_wire_merged.push_back(Wire_2dvtx[vtxloop1]);
903  vtx_time_merged.push_back(Time_2dvtx[vtxloop1]);
904  vtx_plane_merged.push_back(Plane_2dvtx[vtxloop1]);
905  } //<---end saving unmerged verticies
906  } //<---End vtxloop1
907 
908  // Variables for channel numbers
909 
910  uint32_t vtx1_channel = 0;
911  uint32_t vtx2_channel = 0;
912 
913  // Having now found a very long list of potential 2-d end points we need to check if
914  // any of them match between planes and only keep those that have matches
915  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
916  for (auto const& tpcid : geom->Iterate<geo::TPCID>()) {
917  for (unsigned int vtx = vtx_wire_merged.size(); vtx > 0; --vtx) {
918  for (unsigned int vtx1 = 0; vtx1 < vtx; ++vtx1) {
919 
920  // Make sure we are comparing verticies from different planes
921  if (vtx_plane_merged[vtx1] == vtx_plane_merged[vtx]) continue;
922 
923  // To figure out if these two verticies are from a common point we need to check
924  // if the channels intersect and if they are close in time ticks as well...to do
925  // this we have to do some converting to use geom->PlaneWireToChannel(...)
926  geo::PlaneID const vtx1_planeid(tpcid, vtx_plane_merged[vtx1]);
927  geo::WireID const vtx1_wireid(vtx1_planeid, vtx_wire_merged[vtx1]);
928  try {
929  vtx1_channel = wireReadoutGeom.PlaneWireToChannel(vtx1_wireid);
930  }
931  catch (...) {
932  mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
933  continue;
934  }
935 
936  geo::PlaneID const vtx2_planeid(tpcid, vtx_plane_merged[vtx]);
937  geo::WireID const vtx2_wireid(vtx2_planeid, vtx_wire_merged[vtx]);
938  try {
939  vtx2_channel = wireReadoutGeom.PlaneWireToChannel(vtx2_wireid);
940  }
941  catch (...) {
942  mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
943  continue;
944  }
945 
946  // Check to see if the channels intersect and save the y and z coordinate
947  auto intersection = wireReadoutGeom.ChannelsIntersect(vtx1_channel, vtx2_channel);
948  if (!intersection) {
949  mf::LogWarning("FeatureVertexFinder") << "match failed for some reason";
950  continue;
951  }
952 
953  // If the channels intersect establish if they are close in "X"
954  float tempXCluster1 = detProp.ConvertTicksToX(vtx_time_merged[vtx1], vtx1_planeid);
955  float tempXCluster2 = detProp.ConvertTicksToX(vtx_time_merged[vtx], vtx2_planeid);
956 
957  // Now check if the matched channels are within 0.5 cm when projected in X and
958  // that we have less than 100 of these candidates...because more than that seems
959  // silly
960 
961  if (std::abs(tempXCluster1 - tempXCluster2) < 0.5 && candidate_x.size() < 101) {
962  candidate_x.push_back(detProp.ConvertTicksToX(vtx_time_merged[vtx1], vtx1_planeid));
963  candidate_y.push_back(intersection->y);
964  candidate_z.push_back(intersection->z);
965  candidate_strength.push_back(
966  10); //<--For cluster verticies I give it a strength of "10"
967  // arbitrarily for now
968 
969  } //<---End Checking if the vertices agree "well enough" in time tick
970  } //<---end vtx1 for loop
971  } //<---End vtx for loop
972  } //<---End loop over TPC's
973 
974  } //<---End Find3dVtxFrom2dClusterVtxCand
975 
976  // -----------------------------------------------------------------------------
977  // Get 3d Vertex Candidates from clusters 2d Vertex candidates
978  // -----------------------------------------------------------------------------
980  std::vector<double> const& merge_vtxX,
981  std::vector<double> const& merge_vtxY,
982  std::vector<double> const& merge_vtxZ,
983  std::vector<double> const& merge_vtxStgth)
984  {
985  std::vector<double> x_3dVertex_dupRemoved = {0.};
986  std::vector<double> y_3dVertex_dupRemoved = {0.};
987  std::vector<double> z_3dVertex_dupRemoved = {0.};
988  std::vector<double> strength_dupRemoved = {0.};
989 
990  // Looping over the 3d candidates found thus far
991  for (size_t dup = 0; dup < merge_vtxX.size(); dup++) {
992  // Temporary storing the current vertex
993  float tempX_dup = merge_vtxX[dup];
994  float tempY_dup = merge_vtxY[dup];
995  float tempZ_dup = merge_vtxZ[dup];
996  float tempStgth = merge_vtxStgth[dup];
997 
998  bool duplicate_found = false;
999 
1000  // Looping over the rest of the list for duplicate check
1001  for (size_t check = dup + 1; check < merge_vtxX.size(); check++) {
1002 
1003  // I am going to call a duplicate vertex one that matches in x, y, and z within
1004  // 0.1 cm for all 3 coordinates simultaneously
1005  if (std::abs(merge_vtxX[check] - tempX_dup) < 0.1 &&
1006  std::abs(merge_vtxY[check] - tempY_dup) < 0.1 &&
1007  std::abs(merge_vtxZ[check] - tempZ_dup) < 0.1) {
1008  duplicate_found = true;
1009  } //<---End checking to see if this is a duplicate vertex
1010 
1011  } //<---End check for loop
1012 
1013  // If we didn't find a duplicate then lets save this 3d vertex as a real candidate
1014  // for consideration
1015  if (!duplicate_found && tempX_dup > 0) {
1016  x_3dVertex_dupRemoved.push_back(tempX_dup);
1017  y_3dVertex_dupRemoved.push_back(tempY_dup);
1018  z_3dVertex_dupRemoved.push_back(tempZ_dup);
1019  strength_dupRemoved.push_back(tempStgth);
1020  } //<---End storing only non-duplicates
1021 
1022  } //<---End dup for loop
1023 
1024  // Sorting the verticies I have found such that the first in the list is the vertex
1025  // with the highest vertex strength and the lowest z location
1026 
1027  int flag = 1;
1028  double tempX, tempY, tempZ, tempS;
1029 
1030  // Looping over all duplicate removed candidates
1031  for (size_t npri = 0; (npri < x_3dVertex_dupRemoved.size()) && flag; npri++) {
1032  flag = 0;
1033  for (size_t mpri = 0; mpri < x_3dVertex_dupRemoved.size() - 1; mpri++) {
1034  // Swap the order of the two elements
1035  if (strength_dupRemoved[mpri + 1] > strength_dupRemoved[mpri] ||
1036  (strength_dupRemoved[mpri + 1] == strength_dupRemoved[mpri] &&
1037  z_3dVertex_dupRemoved[mpri] > z_3dVertex_dupRemoved[mpri + 1])) {
1038  tempX = x_3dVertex_dupRemoved[mpri];
1039  x_3dVertex_dupRemoved[mpri] = x_3dVertex_dupRemoved[mpri + 1];
1040  x_3dVertex_dupRemoved[mpri + 1] = tempX;
1041 
1042  tempY = y_3dVertex_dupRemoved[mpri];
1043  y_3dVertex_dupRemoved[mpri] = y_3dVertex_dupRemoved[mpri + 1];
1044  y_3dVertex_dupRemoved[mpri + 1] = tempY;
1045 
1046  tempZ = z_3dVertex_dupRemoved[mpri];
1047  z_3dVertex_dupRemoved[mpri] = z_3dVertex_dupRemoved[mpri + 1];
1048  z_3dVertex_dupRemoved[mpri + 1] = tempZ;
1049 
1050  tempS = strength_dupRemoved[mpri];
1051  strength_dupRemoved[mpri] = strength_dupRemoved[mpri + 1];
1052  strength_dupRemoved[mpri + 1] = tempS;
1053 
1054  flag = 1;
1055 
1056  } //<---Inside swap loop
1057  } //<---End mpri
1058  } //<---End npri loop
1059 
1060  // Pushing into a vector of merged and sorted vertices
1061  for (size_t count = 0; count < x_3dVertex_dupRemoved.size(); count++) {
1062  MergeSort3dVtx_xpos.push_back(x_3dVertex_dupRemoved[count]);
1063  MergeSort3dVtx_ypos.push_back(y_3dVertex_dupRemoved[count]);
1064  MergeSort3dVtx_zpos.push_back(z_3dVertex_dupRemoved[count]);
1065  MergeSort3dVtx_strength.push_back(strength_dupRemoved[count]);
1066  }
1067 
1068  } // End MergeAndSort3dVtxCandidate
1069 
1071 
1072  // -----------------------------------------------------------------------------
1073 
1074 } //<---End namespace vertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Encapsulate the construction of a single cyostat .
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Declaration of signal hit object.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
void produce(art::Event &evt) override
constexpr auto abs(T v)
Returns the absolute value of the argument.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
void MergeAndSort3dVtxCandidate(std::vector< double > const &merge_vtxX, std::vector< double > const &merge_vtxY, std::vector< double > const &merge_vtxZ, std::vector< double > const &merge_vtxStgth)
std::vector< double > MergeSort3dVtx_strength
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
std::vector< std::vector< int > > Cls
void Find3dVtxFrom2dClusterVtxCand(detinfo::DetectorPropertiesData const &detProp, std::vector< double > const &Wire_2dvtx, std::vector< double > const &Time_2dvtx, std::vector< double > const &Plane_2dvtx)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:67
void Find2dClusterVertexCandidates(detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Cluster > RawClusters, art::FindManyP< recob::Hit > fmhit)
reference at(size_type n)
Definition: PtrVector.h:359
FeatureVertexFinder(fhicl::ParameterSet const &pset)
The data type to uniquely identify a TPC.
Definition: geo_types.h:306
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Declaration of cluster object.
size_type size() const
Definition: PtrVector.h:302
Detector simulation of raw signals on wires.
double ConvertTicksToX(double ticks, int p, int t, int c) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Provides recob::Track data product.
int ID() const
Return vertex id.
Definition: Vertex.h:101
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
constexpr WireID()=default
Default constructor: an invalid TPC ID.
Char_t n[5]
TCEvent evt
Definition: DataStructs.cxx:8
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
Definition: fwd.h:26
void Get3dVertexCandidates(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::EndPoint2D >> const &EndPoints, bool PlaneDet)
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Encapsulate the construction of a single detector plane .
vertex reconstruction