All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FeatureVertexFinder_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
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
47 #include "art/Framework/Core/EDProducer.h"
48 #include "art/Framework/Core/ModuleMacros.h"
49 #include "art/Framework/Principal/Event.h"
50 #include "art/Framework/Principal/Handle.h"
51 #include "art/Framework/Services/Registry/ServiceHandle.h"
52 #include "canvas/Persistency/Common/FindManyP.h"
53 #include "canvas/Persistency/Common/Ptr.h"
54 #include "canvas/Persistency/Common/PtrVector.h"
55 #include "fhiclcpp/ParameterSet.h"
56 #include "messagefacility/MessageLogger/MessageLogger.h"
57 
58 // LArSoft Includes
70 
71 // ROOT Includes
72 #include "TF1.h"
73 #include "TGraph.h"
74 
75 namespace vertex {
76 
77  class FeatureVertexFinder : public art::EDProducer {
78  public:
79  explicit FeatureVertexFinder(fhicl::ParameterSet const& pset);
80 
81  private:
82  void produce(art::Event& evt) override;
83 
84  // This function will take in and EndPoint2d from either cluster crawler
85  // or corner finder and only save points that make a 3d-candidate
87  std::vector<art::Ptr<recob::EndPoint2D>> EndPoints,
88  bool PlaneDet);
89 
90  // This function will take in 2d Clusters (by default dBCluster)
91  // and return 2d vertex candidates for sorting later
93  art::PtrVector<recob::Cluster> RawClusters,
94  art::FindManyP<recob::Hit> fmhit);
95 
96  // This function takes in 2d Vertex candidates (found by
97  // Find2dClusterVertexCandidates), does some basic merging and
98  // then finds 3d-candidates for use later
100  std::vector<double> const& Wire_2dvtx,
101  std::vector<double> const& Time_2dvtx,
102  std::vector<double> const& Plane_2dvtx);
103 
104  // This function merges and sorts all the 3d vertex candidates, it
105  // merges them if they are within 2.0 cm in X, Y, and Z
106  // simultaneously and then sorts the list by vertex strength and Z
107  // location (lowest Z is first on the list
108  void MergeAndSort3dVtxCandidate(std::vector<double> merge_vtxX,
109  std::vector<double> merge_vtxY,
110  std::vector<double> merge_vtxZ,
111  std::vector<double> 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 
123  std::vector<double> candidate_x = {0.};
124  std::vector<double> candidate_y = {0.};
125  std::vector<double> candidate_z = {0.};
126  std::vector<double> candidate_strength = {0.};
127 
128  // Merged and sorted list of 3d-Vertex candidates filled
129 
130  std::vector<double> MergeSort3dVtx_xpos = {0.};
131  std::vector<double> MergeSort3dVtx_ypos = {0.};
132  std::vector<double> MergeSort3dVtx_zpos = {0.};
133  std::vector<double> MergeSort3dVtx_strength = {0.};
134 
135  // 2d Cluster based Variables
136 
137  std::vector<std::vector<int>> Cls; //<---- Index to clusters in each view
138  std::vector<double> dtdwstart = {0.}; //<----Slope (delta Time Tick vs delta Wire)
139  std::vector<double> dtdwstartError = {0.}; //<---Error on the slope
140  std::vector<double> Clu_Plane = {0.}; //<---Plane of the current cluster
141  std::vector<double> Clu_StartPos_Wire = {0.}; //<---Starting wire number of cluster
142  std::vector<double> Clu_StartPos_TimeTick = {0.}; //<---Starting TDC value of the cluster
143 
144  std::vector<double> Clu_EndPos_Wire = {0.}; //<---Ending wire number of cluster
145  std::vector<double> Clu_EndPos_TimeTick = {0.}; //<---Ending TDC value of the cluster
146 
147  std::vector<double> Clu_Slope = {0.}; //<---Calculated Slope of the cluster (TDC/Wire)
148  std::vector<double> Clu_Yintercept = {0.}; //<---Clusters Y Intercept using start positions
149  std::vector<double> Clu_Yintercept2 = {0.}; //<---Clusters Y Intercept using end positions
150  std::vector<double> Clu_Length = {0.}; //<---Calculated Length of the cluster
151 
152  // 2d Cluster based verticies
153 
154  std::vector<double> TwoDvtx_wire = {0.};
155  std::vector<double> TwoDvtx_time = {0.};
156  std::vector<double> TwoDvtx_plane = {0.};
157  };
158 
159 } //<---End namespace vertex
160 
161 namespace vertex {
162 
163  FeatureVertexFinder::FeatureVertexFinder(fhicl::ParameterSet const& pset) : EDProducer{pset}
164  {
165  fCornerFinderModuleLabel = pset.get<std::string>("CornerFinderModuleLabel");
166  fClusterModuleLabel = pset.get<std::string>("ClusterModuleLabel");
167  fHitModuleLabel = pset.get<std::string>("HitModuleLabel");
168  fCCrawlerEndPoint2dModuleLabel = pset.get<std::string>("CCrawlerEndPoint2dModuleLabel");
169  fRunningMode = pset.get<double>("RunningMode");
170 
171  produces<std::vector<recob::Vertex>>();
172  produces<std::vector<recob::EndPoint2D>>();
173  produces<art::Assns<recob::EndPoint2D, recob::Hit>>();
174 
175  // === Don't think I'll actually have any of these associations ===
176  // === should consider removing in the future
177  produces<art::Assns<recob::Vertex, recob::Hit>>();
178  produces<art::Assns<recob::Vertex, recob::Shower>>();
179  produces<art::Assns<recob::Vertex, recob::Track>>();
180 
181  art::ServiceHandle<geo::Geometry const> geom;
182  Cls.resize(geom->Nplanes(), std::vector<int>());
183  }
184 
185  // -----------------------------------------------------------------------------
186  // Produce
187  void
189  {
190  art::ServiceHandle<geo::Geometry const> geom;
191  auto const detProp =
192  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt);
193 
194  // Figuring out if I have a 2 or 3 plane detector
195 
196  GT2PlaneDetector = false;
197 
198  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
199  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
200  if (geom->Cryostat(cstat).TPC(tpc).Nplanes() > 2) { GT2PlaneDetector = true; }
201  } //<---End tpc loop
202  } //<---End cstat loop
203 
204  if (GT2PlaneDetector) { std::cout << "yeah" << std::endl; }
205 
206  // These are the things I want to put on the event
207 
208  auto vcol = std::make_unique<std::vector<recob::Vertex>>(); // 3D vertex
209  auto epcol = std::make_unique<std::vector<recob::EndPoint2D>>(); // 2D vertex
210  auto assnep = std::make_unique<art::Assns<recob::EndPoint2D, recob::Hit>>();
211  auto assnsh = std::make_unique<art::Assns<recob::Vertex, recob::Shower>>();
212  auto assntr = std::make_unique<art::Assns<recob::Vertex, recob::Track>>();
213  auto assnh = std::make_unique<art::Assns<recob::Vertex, recob::Hit>>();
214 
215  // ClusterCrawler
216 
217  // Getting the EndPoint2d's for cluster crawler
218 
219  try {
220  art::Handle<std::vector<recob::EndPoint2D>> ccrawlerFinderHandle;
221  evt.getByLabel(fCCrawlerEndPoint2dModuleLabel, ccrawlerFinderHandle);
222  std::vector<art::Ptr<recob::EndPoint2D>> ccrawlerEndPoints;
223  art::fill_ptr_vector(ccrawlerEndPoints, ccrawlerFinderHandle);
224 
225  // Passing in the EndPoint2d's from Cluster Crawler
226  Get3dVertexCandidates(detProp, ccrawlerEndPoints, GT2PlaneDetector);
227  }
228  catch (...) {
229  mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Cluster Crawler";
230  }
231 
232  // CornerFinder EndPoint2d's
233 
234  // Getting the EndPoint2d's for Corner Finder
235  try {
236  art::Handle<std::vector<recob::EndPoint2D>> CornerFinderHandle;
237  evt.getByLabel(fCornerFinderModuleLabel, CornerFinderHandle);
238  std::vector<art::Ptr<recob::EndPoint2D>> cornerEndPoints;
239  art::fill_ptr_vector(cornerEndPoints, CornerFinderHandle);
240 
241  // Passing in the EndPoint2d's from Corner Finder
243  }
244  catch (...) {
245  mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Corner Finder";
246  }
247 
248  // Making Cluster Slope EndPoint2d's
249 
250  // Retrieving the Cluster Module for the event
251  try {
252  art::Handle<std::vector<recob::Cluster>> clusterListHandle;
253  evt.getByLabel(fClusterModuleLabel, clusterListHandle);
254 
255  // Finding hits associated with the clusters
256  art::FindManyP<recob::Hit> fmh(clusterListHandle, evt, fClusterModuleLabel);
257 
258  // Filling the Cluster Vector
259  art::PtrVector<recob::Cluster> clusters;
260  for (unsigned int ii = 0; ii < clusterListHandle->size(); ++ii) {
261  art::Ptr<recob::Cluster> clusterHolder(clusterListHandle, ii);
262  clusters.push_back(clusterHolder);
263  }
264 
265  // Passing in the clusters to find 2d Vertices
266  Find2dClusterVertexCandidates(detProp, clusters, fmh);
267 
268  // Finding 3d Candidates from 2d cluster vertex candidates
270  }
271  catch (...) {
272  mf::LogWarning("FeatureVertexFinder") << "Failed to get Cluster from default cluster module";
273  }
274 
275  // Merging and sorting 3d vertex candidates
277 
278  // Putting Vertices on the event
279  // ------------------------------------------------------------
280  // Now that I have a list of 3d vertex candidates I will return
281  // 3d/2d vertices based on which option the user has chosen
282  // fRunningMode == 0 (this returns a full list of all 3d/2d vertex
283  // candidates) fRunningMode == 1 (this returns only one vertex
284  // which is established as the most likely primary)
285 
286  // Returning all vertex candidates
287  if (fRunningMode == 0) {
288 
289  // Looping over Primary Verticies
290  for (size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++) {
291 
292  // Push each primary vertex onto the event
293 
294  double tempxyz[3] = {
296 
297  // Skipping a vertex that is zero
298 
299  if (tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0) { continue; }
300  recob::Vertex the3Dvertex(tempxyz, vcol->size());
301  vcol->push_back(the3Dvertex);
302 
303  // ---------------------------------------------------------------------
304  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
305  // ---------------------------------------------------------------------
306 
307  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
308  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
309  for (size_t plane = 0; plane < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++plane) {
310  double temp2dXYZ[3] = {
312  double temp2dStrength = MergeSort3dVtx_strength[pri];
313 
314  // Skipping a vertex that is zero
315 
316  if (temp2dXYZ[0] == 0 && temp2dXYZ[1] == 0 && temp2dXYZ[2] == 0) { continue; }
317 
318  // Converting the 3d vertex into 2d time ticks, wire, and
319  // channel
320 
321  double EndPoint2d_TimeTick = detProp.ConvertXToTicks(temp2dXYZ[0], plane, tpc, cstat);
322  int EndPoint2d_Wire = 0;
323  int EndPoint2d_Channel = 0;
324  // Putting in protection in case NearestWire Fails
325  try {
326  EndPoint2d_Wire = geom->NearestWire(temp2dXYZ, plane, tpc, cstat);
327  }
328  catch (...) {
329  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
330  continue;
331  }
332  // Putting in protection in case NearestChannel Fails
333  try {
334  EndPoint2d_Channel = geom->NearestChannel(temp2dXYZ, plane, tpc, cstat);
335  }
336  catch (...) {
337  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
338  continue;
339  }
340 
341  // Making geo::WireID and getting the current View number
342  geo::View_t View = geom->View(EndPoint2d_Channel);
343  geo::WireID wireID(cstat, tpc, plane, EndPoint2d_Wire);
344 
345  // Putting the 2d Vertex found on the event
346 
347  recob::EndPoint2D vertex(EndPoint2d_TimeTick, //<---TimeTick
348  wireID, //<---geo::WireID
349  temp2dStrength, //<---Vtx strength (JA: ?)
350  epcol->size(), //<---Vtx ID (JA: ?)
351  View, //<---Vtx View
352  1); //<---Total Charge (JA: Need to figure this one?)
353  epcol->push_back(vertex);
354  } //<---End Plane loop
355  } //<---End TPC loop
356  } //<---End cstat loop
357  } //<---End pri loop
358  } //<---End fRunningMode == 0
359 
360  // ================================================
361  // === Returning only primary vertex candidates ===
362  // ================================================
363  if (fRunningMode != 0) {
364  int position = 0;
365  int bail = 0;
366 
367  // Looping over Primary Verticies
368 
369  for (size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++) {
370 
371  // Push each primary vertex onto the event
372 
373  double tempxyz[3] = {
375 
376  // Skipping a vertex that is zero
377 
378  if (bail > 0) { continue; }
379  if (tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0) { continue; }
380  position = pri;
381  bail++;
382  recob::Vertex the3Dvertex(tempxyz, vcol->size());
383  vcol->push_back(the3Dvertex);
384  }
385 
386  // ---------------------------------------------------------------------
387  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
388  // ---------------------------------------------------------------------
389 
390  // Looping over cryostats
391 
392  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
393  // Looping over TPC's
394  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
395  // Loop over the wire planes
396  for (size_t plane = 0; plane < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++plane) {
397  double temp2dXYZ[3] = {MergeSort3dVtx_xpos[position],
398  MergeSort3dVtx_ypos[position],
399  MergeSort3dVtx_zpos[position]};
400  double temp2dStrength = MergeSort3dVtx_strength[position];
401 
402  // Converting the 3d vertex into 2d time ticks, wire, and
403  // channel
404 
405  double EndPoint2d_TimeTick = detProp.ConvertXToTicks(temp2dXYZ[0], plane, tpc, cstat);
406  int EndPoint2d_Wire = 0;
407  int EndPoint2d_Channel = 0;
408  // Putting in protection in case NearestWire Fails
409  try {
410  EndPoint2d_Wire = geom->NearestWire(temp2dXYZ, plane, tpc, cstat);
411  }
412  catch (...) {
413  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
414  continue;
415  }
416  // Putting in protection in case NearestChannel Fails
417  try {
418  EndPoint2d_Channel = geom->NearestChannel(temp2dXYZ, plane, tpc, cstat);
419  }
420  catch (...) {
421  mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
422  continue;
423  }
424 
425  // Making geo::WireID and getting the current View number
426  geo::View_t View = geom->View(EndPoint2d_Channel);
427  geo::WireID wireID(cstat, tpc, plane, EndPoint2d_Wire);
428 
429  // Putting the 2d Vertex found on the event
430 
431  recob::EndPoint2D vertex(EndPoint2d_TimeTick, //<---TimeTick
432  wireID, //<---geo::WireID
433  temp2dStrength, //<---Vtx strength (JA: ?)
434  epcol->size(), //<---Vtx ID (JA: ?)
435  View, //<---Vtx View
436  1); //<---Total Charge (JA: Need to figure this one?)
437  epcol->push_back(vertex);
438  } //<---End Plane loop
439  } //<---End TPC loop
440  } //<---End cstat loop
441  } //<---End fRunningMode == 1
442 
443  mf::LogVerbatim("Summary") << std::setfill('-') << std::setw(175) << "-" << std::setfill(' ');
444  mf::LogVerbatim("Summary") << "FeatureVertexFinder Summary:";
445  for (size_t i = 0; i < epcol->size(); ++i)
446  mf::LogVerbatim("Summary") << epcol->at(i);
447  for (size_t i = 0; i < vcol->size(); ++i)
448  mf::LogVerbatim("Summary") << vcol->at(i);
449 
450  evt.put(std::move(epcol));
451  evt.put(std::move(vcol));
452  evt.put(std::move(assnep));
453  evt.put(std::move(assntr));
454  evt.put(std::move(assnsh));
455  evt.put(std::move(assnh));
456 
457  // Clearing vectors at the end of the event
458 
459  vcol.reset();
460  epcol.reset();
461  candidate_x.clear();
462  candidate_y.clear();
463  candidate_z.clear();
464  candidate_strength.clear();
465  MergeSort3dVtx_xpos.clear();
466  MergeSort3dVtx_ypos.clear();
467  MergeSort3dVtx_zpos.clear();
468  MergeSort3dVtx_strength.clear();
469  dtdwstart.clear();
470  dtdwstartError.clear();
471  Clu_Plane.clear();
472  Clu_StartPos_Wire.clear();
473  Clu_StartPos_TimeTick.clear();
474  Clu_EndPos_Wire.clear();
475  Clu_EndPos_TimeTick.clear();
476  Clu_Slope.clear();
477  Clu_Yintercept.clear();
478  Clu_Yintercept2.clear();
479  Clu_Length.clear();
480  TwoDvtx_wire.clear();
481  TwoDvtx_time.clear();
482  TwoDvtx_plane.clear();
483 
484  } //<--End FeatureVertexFinder::produce
485 
486  // -----------------------------------------------------------------------------
487  // Get 3d Vertex Candidates
488  // -----------------------------------------------------------------------------
489  void
492  std::vector<art::Ptr<recob::EndPoint2D>> EndPoints,
493  bool PlaneDet)
494  {
495  art::ServiceHandle<geo::Geometry const> geom;
496 
497  double y = 0., z = 0.;
498  double yy = 0., zz = 0.;
499  double yy2 = 0., zz2 = 0.;
500  double yy3 = 0., zz3 = 0.;
501 
502  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
503  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
504  for (size_t endpt1 = 0; endpt1 < EndPoints.size(); endpt1++) {
505  for (size_t endpt2 = endpt1 + 1; endpt2 < EndPoints.size(); endpt2++) {
506 
507  // Check to make sure we are comparing features from different
508  // planes
509 
510  if (EndPoints.at(endpt1)->WireID().Plane != EndPoints.at(endpt2)->WireID().Plane) {
511 
512  // Get the appropriate time offset for the two planes we are
513  // considering
514 
515  float tempXFeature1 = detProp.ConvertTicksToX(EndPoints.at(endpt1)->DriftTime(),
516  EndPoints.at(endpt1)->WireID().Plane,
517  tpc,
518  cstat);
519  float tempXFeature2 = detProp.ConvertTicksToX(EndPoints.at(endpt2)->DriftTime(),
520  EndPoints.at(endpt2)->WireID().Plane,
521  tpc,
522  cstat);
523 
524  // Checking to see if these features have intersecting
525  // channels and are within 0.5 cm in projected X
526 
527  if (geom->ChannelsIntersect(
528  geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane,
529  EndPoints.at(endpt2)->WireID().Wire,
530  tpc,
531  cstat),
532  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane,
533  EndPoints.at(endpt1)->WireID().Wire,
534  tpc,
535  cstat),
536  yy,
537  zz) &&
538  std::abs(tempXFeature1 - tempXFeature2) < 0.5) {
539 
540  // Use this fill if we are in a detector with fewer than 3
541  // plane (e.g. ArgoNeuT)
542 
543  if (!PlaneDet) {
544  candidate_x.push_back(tempXFeature1);
545  candidate_y.push_back(yy);
546  candidate_z.push_back(zz);
547  candidate_strength.push_back(EndPoints.at(endpt1)->Strength() +
548  EndPoints.at(endpt2)->Strength());
549  } //<---End fill for 2 plane detector
550 
551  // Adding a check to see if I am in a 3-plane detector and
552  // therefore need to check for a match across more than 2 planes
553 
554  if (PlaneDet) {
555 
556  // Looping over the rest of the list
557 
558  for (size_t endpt3 = endpt2 + 1; endpt3 < EndPoints.size(); endpt3++) {
559 
560  // Check to make sure we are comparing features from
561  // different planes
562 
563  if (EndPoints.at(endpt3)->WireID().Plane !=
564  EndPoints.at(endpt2)->WireID().Plane &&
565  EndPoints.at(endpt3)->WireID().Plane !=
566  EndPoints.at(endpt1)->WireID().Plane &&
567  EndPoints.at(endpt1)->WireID().Plane !=
568  EndPoints.at(endpt2)->WireID().Plane) {
569  float tempXFeature3 =
570  detProp.ConvertTicksToX(EndPoints.at(endpt3)->DriftTime(),
571  EndPoints.at(endpt3)->WireID().Plane,
572  tpc,
573  cstat);
574 
575  // Checking to make sure our third feature has an
576  // intersecting channel with our
577  // other two channels and is within 1.0 cm
578  // projected in X
579 
580  if (geom->ChannelsIntersect(
581  geom->PlaneWireToChannel(EndPoints.at(endpt3)->WireID().Plane,
582  EndPoints.at(endpt3)->WireID().Wire,
583  tpc,
584  cstat),
585  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane,
586  EndPoints.at(endpt1)->WireID().Wire,
587  tpc,
588  cstat),
589  yy3,
590  zz3) &&
591  geom->ChannelsIntersect(
592  geom->PlaneWireToChannel(EndPoints.at(endpt3)->WireID().Plane,
593  EndPoints.at(endpt3)->WireID().Wire,
594  tpc,
595  cstat),
596  geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane,
597  EndPoints.at(endpt2)->WireID().Wire,
598  tpc,
599  cstat),
600  yy2,
601  zz2) &&
602  geom->ChannelsIntersect(
603  geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane,
604  EndPoints.at(endpt2)->WireID().Wire,
605  tpc,
606  cstat),
607  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane,
608  EndPoints.at(endpt1)->WireID().Wire,
609  tpc,
610  cstat),
611  yy,
612  zz) &&
613  std::abs(tempXFeature3 - tempXFeature2) < 1.0 &&
614  std::abs(tempXFeature3 - tempXFeature1) < 1.0 &&
615  std::abs(tempXFeature1 - tempXFeature2) < 1.0) {
616  candidate_x.push_back(
617  detProp.ConvertTicksToX(EndPoints.at(endpt1)->DriftTime(),
618  EndPoints.at(endpt1)->WireID().Plane,
619  tpc,
620  cstat));
621 
622  // Finding intersection points
623 
624  geom->IntersectionPoint(EndPoints.at(endpt1)->WireID().Wire,
625  EndPoints.at(endpt2)->WireID().Wire,
626  EndPoints.at(endpt1)->WireID().Plane,
627  EndPoints.at(endpt2)->WireID().Plane,
628  cstat,
629  tpc,
630  y,
631  z);
632 
633  candidate_y.push_back(y);
634  candidate_z.push_back(z);
635  candidate_strength.push_back(EndPoints.at(endpt1)->Strength() +
636  EndPoints.at(endpt2)->Strength() +
637  EndPoints.at(endpt3)->Strength());
638 
639  // Note: If I've made it here I have a matched
640  // triplet...since I don't want to use any of
641  // these features again I am going to iterate
642  // each of the counters so we move to the next
643  // one
644  if (endpt1 < EndPoints.size()) { endpt1++; }
645  if (endpt2 < EndPoints.size()) { endpt2++; }
646  if (endpt3 < EndPoints.size()) { endpt3++; }
647  } //<---End finding 3d point across all three planes
648 
649  } //<---End checking for all different planes
650  } //<---End endpt3
651 
652  } //<---End fill for 3 plane detector
653 
654  } //<---End intersecting channels
655 
656  } //<---End making sure we are looking across planes
657  } //<---End endpt2 loop
658  } //<---End endpt1 loop
659  } //<---End TPC loop
660  } //<---End cstat
661 
662  } //<---End Get3dVertexCandidates
663 
664  // -----------------------------------------------------------------------------
665  // Get 2d Vertex Candidates from clusters
666  // -----------------------------------------------------------------------------
667  void
670  art::PtrVector<recob::Cluster> RawClusters,
671  art::FindManyP<recob::Hit> fmhit)
672  {
673  art::ServiceHandle<geo::Geometry const> geom;
674 
675  int nClustersFound = 0;
676 
677  // Initialize Cls
678  for (auto& c : Cls)
679  c.clear();
680 
681  for (size_t iclu = 0; iclu < RawClusters.size(); ++iclu) {
682  // Gathering the hits associated with the current cluster
683  std::vector<art::Ptr<recob::Hit>> hit = fmhit.at(iclu);
684 
685  // I only want to consider this cluster if it has a sufficient number
686  // of hits
687  if (hit.size() < 15) { continue; }
688 
689  // Determine which view the current cluster is in
690 
691  const geo::View_t view = RawClusters.at(iclu)->View();
692  if (view >= Cls.size()) {
693  std::cerr << __PRETTY_FUNCTION__ << "\033[93m Logic error in my code ... view " << view
694  << " not supported ! \033[00m" << std::endl;
695  throw std::exception();
696  }
697 
698  Cls.at(RawClusters.at(iclu)->View()).push_back(iclu);
699 
700  // Filling wires and times into a TGraph for the cluster
701 
702  std::vector<double> wires;
703  std::vector<double> times;
704 
705  // Counting the number of hits in the current cluster (n)
706  int n = 0;
707 
708  // Looping over the hits in the cluster
709 
710  for (size_t i = 0; i < hit.size(); ++i) {
711  wires.push_back(hit[i]->WireID().Wire);
712  times.push_back(hit[i]->PeakTime());
713  ++n;
714  }
715 
716  // If there are 2 or more hits in the cluster fill a TGraph and
717  // fit a from a polynomial or order 1
718 
719  if (n >= 15) {
720 
721  // Push the hits into a TGraph
722 
723  TGraph* the2Dtrack = new TGraph(n, &wires[0], &times[0]);
724  // === Try to fit the TGraph with a 1st order polynomial ===
725  try {
726  the2Dtrack->Fit("pol1", "Q");
727  TF1* pol1 = (TF1*)the2Dtrack->GetFunction("pol1");
728  double par[2];
729  double parerror[2];
730  pol1->GetParameters(par);
731  parerror[1] = pol1->GetParError(1);
732  double FitChi2 = pol1->GetChisquare();
733  double FitNDF = pol1->GetNDF();
734 
735  double fitGoodness = FitChi2 / FitNDF;
736 
737  // Skipping the fitted slope if the Chi2/NDF < 5
738  if (fitGoodness > 10) {
739  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
740  continue;
741  }
742 
743  // Take change in time tick vs change in wire (dT/dW) from the fit
744 
745  dtdwstart.push_back(par[1]);
746  dtdwstartError.push_back(parerror[1]);
747  } //<---End try to fit with a polynomial order 1
748 
749  // If the fitter fails just take dT/dW from the cluster
750  catch (...) {
751  mf::LogWarning("FeatureVertexFinder")
752  << "Fitter failed, using the clusters default dTdW()";
753  delete the2Dtrack;
754  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
755  continue;
756  }
757 
758  delete the2Dtrack;
759  } //<---End if the cluster has 2 or more hits
760 
761  // If the cluster has fewer than 2 hits just take the dT/dW from
762  // the cluster
763 
764  else {
765  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
766  }
767  } //<---End loop over clusters iclu
768 
769  // Now that I have slopes for all the clusters move on to finding
770  // intersection points
771 
772  // Looping over cryostats
773 
774  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
775  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
776  for (unsigned int i = 0; i < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++i) {
777 
778  // If there is at least one cluster found
779 
780  if (Cls[i].size() >= 1) {
781 
782  // Loop over each cluster
783 
784  for (unsigned int j = 0; j < Cls[i].size(); ++j) {
785  // === Current Clusters Plane ===
786  Clu_Plane.push_back(RawClusters.at(Cls.at(i).at(j))->View());
787  // === Current Clusters StartPos ===
788  Clu_StartPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->StartWire());
789  Clu_StartPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->StartTick());
790  // === Current Clusters EndPos ===
791  Clu_EndPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->EndWire());
792  Clu_EndPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->EndTick());
793  // Current Clusters Slope (In Wire and Time Tick)
794  Clu_Slope.push_back(dtdwstart[Cls[i][j]]);
795  Clu_Length.push_back(std::sqrt(pow((RawClusters.at(Cls.at(i).at(j))->StartWire() -
796  RawClusters.at(Cls.at(i).at(j))->EndWire()) *
797  13.5,
798  2) +
799  pow(RawClusters.at(Cls.at(i).at(j))->StartTick() -
800  RawClusters.at(Cls.at(i).at(j))->EndTick(),
801  2)));
802 
803  // Given a slope and a point find the y-intercept
804  // c = y-mx
805 
806  Clu_Yintercept.push_back(
807  RawClusters.at(Cls.at(i).at(j))->StartTick() -
808  (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->StartWire()));
809 
810  // Also calculating the y-intercept but using the end
811  // time of the cluster correct for the possibility that
812  // the clustering didn't get start and end points right
813 
814  Clu_Yintercept2.push_back(
815  RawClusters.at(Cls.at(i).at(j))->EndTick() -
816  (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->EndWire()));
817 
818  // Iterating on the total number of clusters found
819 
820  nClustersFound++;
821  } //<---End loop over all clusters
822 
823  } //<---End check if we have at least one cluster
824 
825  // If no clusters were found then put in dummy vertex values
826  else {
827  TwoDvtx_wire.push_back(-1);
828  TwoDvtx_time.push_back(-1);
829  TwoDvtx_plane.push_back(-1);
830  }
831 
832  } //<---End loop over planes (i)
833  } //<---End loop over tpc's
834  } //<---End loop over cryostats
835 
836  // Now loop over all the clusters found and establish a
837  // preliminary set of 2d-verticies based on the slope/intercept of
838  // those clusters
839 
840  for (unsigned int n = nClustersFound; n > 0; n--) {
841 
842  // Looping over the clusters starting from the first cluster and
843  // checking against the nCluster
844 
845  for (unsigned int m = 0; m < n; m++) {
846 
847  // Checking to make sure clusters are in the same view
848 
849  if (Clu_Plane[n] == Clu_Plane[m]) {
850  // --- Skip the vertex if the lines slope don't intercept ---
851  if (Clu_Slope[m] - Clu_Slope[n] == 0) { break; }
852 
853  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
854  float intersection_X =
855  (Clu_Yintercept[n] - Clu_Yintercept[m]) / (Clu_Slope[m] - Clu_Slope[n]);
856 
857  // === Y intersection = (slope1 * XInt) + yInt1 ===
858  float intersection_Y = (Clu_Slope[m] * intersection_X) + Clu_Yintercept[m];
859 
860  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
861  float intersection_X2 =
862  (Clu_Yintercept2[n] - Clu_Yintercept2[m]) / (Clu_Slope[m] - Clu_Slope[n]);
863 
864  // === Y intersection = (slope1 * XInt) + yInt1 ===
865  float intersection_Y2 = (Clu_Slope[m] * intersection_X2) + Clu_Yintercept2[m];
866 
867  // Skipping crap intersection points
868 
869  if (intersection_X2 < 1) { intersection_X2 = -999; }
870  if (intersection_X2 > geom->Nwires(Clu_Plane[m], 0, 0)) { intersection_X2 = -999; }
871  if (intersection_Y2 < 0) { intersection_Y2 = -999; }
872  if (intersection_Y2 > detProp.NumberTimeSamples()) { intersection_Y2 = -999; }
873  if (intersection_X < 1) { intersection_X = -999; }
874  if (intersection_X > geom->Nwires(Clu_Plane[m], 0, 0)) { intersection_X = -999; }
875  if (intersection_Y < 0) { intersection_Y = -999; }
876  if (intersection_Y > detProp.NumberTimeSamples()) { intersection_Y = -999; }
877 
878  // Putting in a protection for the findManyHit function
879 
880  try {
881  // Gathering the hits associated with the current cluster
882  std::vector<art::Ptr<recob::Hit>> hitClu1 = fmhit.at(m);
883  std::vector<art::Ptr<recob::Hit>> hitClu2 = fmhit.at(n);
884 
885  // If the intersection point is 80 or more wires away from
886  // either cluster and one of the clusters has fewer than 8 hits the
887  // intersection is likely a crap one and we won't save this point
888  if ((abs(Clu_EndPos_Wire[m] - intersection_X2) > 80 && hitClu1.size() < 8) ||
889  (abs(Clu_EndPos_Wire[n] - intersection_X2) > 80 && hitClu2.size() < 8)) {
890  intersection_X2 = -999;
891  intersection_Y2 = -999;
892  }
893 
894  if ((abs(Clu_StartPos_Wire[m] - intersection_X) > 80 && hitClu1.size() < 8) ||
895  (abs(Clu_StartPos_Wire[n] - intersection_X) > 80 && hitClu2.size() < 8)) {
896  intersection_X = -999;
897  intersection_Y = -999;
898  }
899 
900  // If the intersection point is 50 or more wires away from
901  // either cluster and the one of the clusters has fewer than 3 hits
902  // the intersection is likely a crap one and we won't save this
903  // point
904  if ((abs(Clu_EndPos_Wire[m] - intersection_X2) > 50 && hitClu1.size() < 4) ||
905  (abs(Clu_EndPos_Wire[n] - intersection_X2) > 50 && hitClu2.size() < 4)) {
906  intersection_X2 = -999;
907  intersection_Y2 = -999;
908  }
909 
910  if ((abs(Clu_StartPos_Wire[m] - intersection_X) > 50 && hitClu1.size() < 4) ||
911  (abs(Clu_StartPos_Wire[n] - intersection_X) > 50 && hitClu2.size() < 4)) {
912  intersection_X = -999;
913  intersection_Y = -999;
914  }
915  }
916  catch (...) {
917  mf::LogWarning("FeatureVertexFinder") << "FindManyHit Function faild";
918  intersection_X = -999;
919  intersection_Y = -999;
920  intersection_X2 = -999;
921  intersection_Y2 = -999;
922  continue;
923  }
924 
925  // Push back a candidate 2dClusterVertex if it is inside the
926  // detector
927 
928  if (intersection_X2 > 1 && intersection_Y2 > 0 &&
929  (intersection_X2 < geom->Nwires(Clu_Plane[m], 0, 0)) &&
930  (intersection_Y2 < detProp.NumberTimeSamples())) {
931 
932  TwoDvtx_wire.push_back(intersection_X2);
933  TwoDvtx_time.push_back(intersection_Y2);
934  TwoDvtx_plane.push_back(Clu_Plane[m]);
935  } //<---End saving a "good 2d vertex" candidate
936 
937  // Push back a candidate 2dClusterVertex if it is inside the
938  // detector
939 
940  if (intersection_X > 1 && intersection_Y > 0 &&
941  (intersection_X < geom->Nwires(Clu_Plane[m], 0, 0)) &&
942  (intersection_Y < detProp.NumberTimeSamples())) {
943  TwoDvtx_wire.push_back(intersection_X);
944  TwoDvtx_time.push_back(intersection_Y);
945  TwoDvtx_plane.push_back(Clu_Plane[m]);
946  } //<---End saving a "good 2d vertex" candidate
947 
948  } //<---End check that they are in differnt planes
949  } //<---End m loop
950  } //<---End n loop
951 
952  } //<---End 2dClusterVertexCandidates
953 
954  // -----------------------------------------------------------------------------
955  // Get 3d Vertex Candidates from clusters 2d Vertex candidates
956  // -----------------------------------------------------------------------------
957  void
960  std::vector<double> const& Wire_2dvtx,
961  std::vector<double> const& Time_2dvtx,
962  std::vector<double> const& Plane_2dvtx)
963  {
964 
965  std::vector<double> vtx_wire_merged;
966  std::vector<double> vtx_time_merged;
967  std::vector<double> vtx_plane_merged;
968 
969  double y_coord = 0, z_coord = 0;
970 
971  bool merged = false;
972 
973  art::ServiceHandle<geo::Geometry const> geom;
974 
975  // MERGING THE LONG LIST OF 2D CANDIDATES
976 
977  // Looping over 2d-verticies (loop1)
978 
979  for (size_t vtxloop1 = 0; vtxloop1 < Wire_2dvtx.size(); vtxloop1++) {
980  if (Wire_2dvtx[vtxloop1] < 0) { continue; }
981 
982  merged = false;
983 
984  // Looping over 2d-verticies (loop2)
985 
986  for (size_t vtxloop2 = vtxloop1 + 1; vtxloop2 < Wire_2dvtx.size(); vtxloop2++) {
987  if (Wire_2dvtx[vtxloop2] < 0) { continue; }
988 
989  // Make sure the 2d-Verticies are in the same plane
990 
991  if (Plane_2dvtx[vtxloop1] == Plane_2dvtx[vtxloop2]) {
992 
993  // Considering merging 2d vertices if they
994  // are within 3 wires of each other
995 
996  if (fabs(Wire_2dvtx[vtxloop1] - Wire_2dvtx[vtxloop2]) < 4) {
997 
998  // Merge the verticies if they are within 10 time ticks
999 
1000  if (fabs(Time_2dvtx[vtxloop1] - Time_2dvtx[vtxloop2]) < 10) {
1001  vtx_wire_merged.push_back(((Wire_2dvtx[vtxloop2] + Wire_2dvtx[vtxloop1]) / 2));
1002  vtx_time_merged.push_back(((Time_2dvtx[vtxloop2] + Time_2dvtx[vtxloop1]) / 2));
1003  vtx_plane_merged.push_back(Plane_2dvtx[vtxloop1]);
1004 
1005  merged = true;
1006  if (vtxloop2 < Wire_2dvtx.size()) { vtxloop2++; }
1007  if (vtxloop1 < Wire_2dvtx.size()) { vtxloop1++; }
1008  } //<---End the check within 10 time ticks for merging
1009  } //<---Looking at vertices that are within 3 wires of each other
1010  } //<---Only looking at vertices that are in the same plane
1011  } //<---End vtxloop2
1012  if (!merged) {
1013  vtx_wire_merged.push_back(Wire_2dvtx[vtxloop1]);
1014  vtx_time_merged.push_back(Time_2dvtx[vtxloop1]);
1015  vtx_plane_merged.push_back(Plane_2dvtx[vtxloop1]);
1016  } //<---end saving unmerged verticies
1017  } //<---End vtxloop1
1018 
1019  // Variables for channel numbers
1020 
1021  uint32_t vtx1_channel = 0;
1022  uint32_t vtx2_channel = 0;
1023 
1024  // Having now found a very long list of potential 2-d end points
1025  // we need to check if any of them match between planes and only
1026  // keep those that have matches
1027 
1028  // Looping over cryostats
1029 
1030  for (size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat) {
1031 
1032  // Looping over TPC's
1033 
1034  for (size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc) {
1035  for (unsigned int vtx = vtx_wire_merged.size(); vtx > 0; vtx--) {
1036  for (unsigned int vtx1 = 0; vtx1 < vtx; vtx1++) {
1037 
1038  // Check to make sure we are comparing verticies from different
1039  // planes
1040 
1041  if (vtx_plane_merged[vtx1] != vtx_plane_merged[vtx]) {
1042  // To figure out if these two verticies are from a
1043  // common point we need to check if the channels
1044  // intersect and if they are close in time ticks as
1045  // well...to do this we have to do some converting to
1046  // use geom->PlaneWireToChannel(PlaneNo, Wire, tpc,
1047  // cstat)
1048  bool match = false;
1049 
1050  unsigned int vtx1_plane = vtx_plane_merged[vtx1];
1051  unsigned int vtx1_wire = vtx_wire_merged[vtx1];
1052  try {
1053  vtx1_channel = geom->PlaneWireToChannel(vtx1_plane, vtx1_wire, tpc, cstat);
1054  }
1055  catch (...) {
1056  mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
1057  match = false;
1058  continue;
1059  }
1060 
1061  unsigned int vtx2_plane = vtx_plane_merged[vtx];
1062  unsigned int vtx2_wire = vtx_wire_merged[vtx];
1063  try {
1064  vtx2_channel = geom->PlaneWireToChannel(vtx2_plane, vtx2_wire, tpc, cstat);
1065  }
1066  catch (...) {
1067  mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
1068  match = false;
1069  continue;
1070  }
1071 
1072  // Check to see if the channels intersect and save the y and z
1073  // coordinate
1074 
1075  try {
1076  match = geom->ChannelsIntersect(vtx1_channel, vtx2_channel, y_coord, z_coord);
1077  }
1078  catch (...) {
1079  mf::LogWarning("FeatureVertexFinder") << "match failed for some reason";
1080  match = false;
1081  continue;
1082  }
1083 
1084  // If the channels intersect establish if they are close in
1085  // "X"
1086 
1087  if (match) {
1088  float tempXCluster1 =
1089  detProp.ConvertTicksToX(vtx_time_merged[vtx1], vtx1_plane, tpc, cstat);
1090  float tempXCluster2 =
1091  detProp.ConvertTicksToX(vtx_time_merged[vtx], vtx2_plane, tpc, cstat);
1092 
1093  // Now check if the matched channels are within 0.5 cm when
1094  // projected in X and that we have less than 100 of these
1095  // candidates...because more than that seems silly
1096 
1097  if (std::abs(tempXCluster1 - tempXCluster2) < 0.5 && candidate_x.size() < 101) {
1098  candidate_x.push_back(detProp.ConvertTicksToX(
1099  vtx_time_merged[vtx1], vtx_plane_merged[vtx1], tpc, cstat));
1100  candidate_y.push_back(y_coord);
1101  candidate_z.push_back(z_coord);
1102  candidate_strength.push_back(
1103  10); //<--For cluster verticies I give it a strength of "10"
1104  // arbitrarily for now
1105 
1106  } //<---End Checking if the vertices agree "well enough" in time
1107  // tick
1108  } //<---End Checking if verticies intersect
1109 
1110  } //<--- End checking we are in different planes
1111  } //<---end vtx1 for loop
1112  } //<---End vtx for loop
1113  } //<---End loop over TPC's
1114  } //<---End loop over cryostats
1115 
1116  } //<---End Find3dVtxFrom2dClusterVtxCand
1117 
1118  // -----------------------------------------------------------------------------
1119  // Get 3d Vertex Candidates from clusters 2d Vertex candidates
1120  // -----------------------------------------------------------------------------
1121  void
1123  std::vector<double> merge_vtxY,
1124  std::vector<double> merge_vtxZ,
1125  std::vector<double> merge_vtxStgth)
1126  {
1127 
1128  std::vector<double> x_3dVertex_dupRemoved = {0.};
1129  std::vector<double> y_3dVertex_dupRemoved = {0.};
1130  std::vector<double> z_3dVertex_dupRemoved = {0.};
1131  std::vector<double> strength_dupRemoved = {0.};
1132 
1133  // Looping over the 3d candidates found thus far
1134 
1135  for (size_t dup = 0; dup < merge_vtxX.size(); dup++) {
1136  // Temperary storing the current vertex
1137  float tempX_dup = merge_vtxX[dup];
1138  float tempY_dup = merge_vtxY[dup];
1139  float tempZ_dup = merge_vtxZ[dup];
1140  float tempStgth = merge_vtxStgth[dup];
1141 
1142  // Setting a boolian to see if this is a duplicate
1143 
1144  bool duplicate_found = false;
1145 
1146  // Looping over the rest of the list for duplicate check
1147 
1148  for (size_t check = dup + 1; check < merge_vtxX.size(); check++) {
1149 
1150  // I am going to call a duplicate vertex one that matches in x, y,
1151  // and z within 0.1 cm for all 3 coordinates simultaneously
1152 
1153  if (std::abs(merge_vtxX[check] - tempX_dup) < 0.1 &&
1154  std::abs(merge_vtxY[check] - tempY_dup) < 0.1 &&
1155  std::abs(merge_vtxZ[check] - tempZ_dup) < 0.1) {
1156  duplicate_found = true;
1157  } //<---End checking to see if this is a duplicate vertex
1158 
1159  } //<---End check for loop
1160 
1161  // If we didn't find a duplicate then lets save this 3d vertex
1162  // as a real candidate for consideration
1163 
1164  if (!duplicate_found && tempX_dup > 0) {
1165  x_3dVertex_dupRemoved.push_back(tempX_dup);
1166  y_3dVertex_dupRemoved.push_back(tempY_dup);
1167  z_3dVertex_dupRemoved.push_back(tempZ_dup);
1168  strength_dupRemoved.push_back(tempStgth);
1169  } //<---End storing only non-duplicates
1170 
1171  } //<---End dup for loop
1172 
1173  // Sorting the verticies I have found such that the first in the
1174  // list is the vertex with the highest vertex strength and the
1175  // lowest z location
1176 
1177  int flag = 1;
1178  double tempX, tempY, tempZ, tempS;
1179 
1180  // Looping over all duplicate removed candidates
1181 
1182  for (size_t npri = 0; (npri < x_3dVertex_dupRemoved.size()) && flag; npri++) {
1183  flag = 0;
1184  for (size_t mpri = 0; mpri < x_3dVertex_dupRemoved.size() - 1; mpri++) {
1185  // Swap the order of the two elements
1186  if (strength_dupRemoved[mpri + 1] > strength_dupRemoved[mpri] ||
1187  (strength_dupRemoved[mpri + 1] == strength_dupRemoved[mpri] &&
1188  z_3dVertex_dupRemoved[mpri] > z_3dVertex_dupRemoved[mpri + 1])) {
1189  tempX = x_3dVertex_dupRemoved[mpri];
1190  x_3dVertex_dupRemoved[mpri] = x_3dVertex_dupRemoved[mpri + 1];
1191  x_3dVertex_dupRemoved[mpri + 1] = tempX;
1192 
1193  tempY = y_3dVertex_dupRemoved[mpri];
1194  y_3dVertex_dupRemoved[mpri] = y_3dVertex_dupRemoved[mpri + 1];
1195  y_3dVertex_dupRemoved[mpri + 1] = tempY;
1196 
1197  tempZ = z_3dVertex_dupRemoved[mpri];
1198  z_3dVertex_dupRemoved[mpri] = z_3dVertex_dupRemoved[mpri + 1];
1199  z_3dVertex_dupRemoved[mpri + 1] = tempZ;
1200 
1201  tempS = strength_dupRemoved[mpri];
1202  strength_dupRemoved[mpri] = strength_dupRemoved[mpri + 1];
1203  strength_dupRemoved[mpri + 1] = tempS;
1204 
1205  flag = 1;
1206 
1207  } //<---Inside swap loop
1208  } //<---End mpri
1209  } //<---End npri loop
1210 
1211  // Pushing into a vector of merged and sorted verticies
1212 
1213  for (size_t count = 0; count < x_3dVertex_dupRemoved.size(); count++) {
1214  MergeSort3dVtx_xpos.push_back(x_3dVertex_dupRemoved[count]);
1215  MergeSort3dVtx_ypos.push_back(y_3dVertex_dupRemoved[count]);
1216  MergeSort3dVtx_zpos.push_back(z_3dVertex_dupRemoved[count]);
1217  MergeSort3dVtx_strength.push_back(strength_dupRemoved[count]);
1218  }
1219 
1220  } // End MergeAndSort3dVtxCandidate
1221 
1222  DEFINE_ART_MODULE(FeatureVertexFinder)
1223 
1224  // -----------------------------------------------------------------------------
1225 
1226 } //<---End namespace vertex
process_name vertex
Definition: cheaterreco.fcl:51
process_name opflash particleana ie ie ie z
void MergeAndSort3dVtxCandidate(std::vector< double > merge_vtxX, std::vector< double > merge_vtxY, std::vector< double > merge_vtxZ, std::vector< double > merge_vtxStgth)
Encapsulate the construction of a single cyostat.
BEGIN_PROLOG could also be cerr
then echo unknown compiler flag
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Declaration of signal hit object.
void produce(art::Event &evt) override
BEGIN_PROLOG StartTick
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
process_name hit
Definition: cheaterreco.fcl:51
std::vector< double > MergeSort3dVtx_strength
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< std::vector< int > > Cls
T abs(T value)
void Find3dVtxFrom2dClusterVtxCand(detinfo::DetectorPropertiesData const &detProp, std::vector< double > const &Wire_2dvtx, std::vector< double > const &Time_2dvtx, std::vector< double > const &Plane_2dvtx)
process_name opflash particleana ie ie y
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void Get3dVertexCandidates(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::EndPoint2D >> EndPoints, bool PlaneDet)
void Find2dClusterVertexCandidates(detinfo::DetectorPropertiesData const &detProp, art::PtrVector< recob::Cluster > RawClusters, art::FindManyP< recob::Hit > fmhit)
process_name tightIsolTest check
FeatureVertexFinder(fhicl::ParameterSet const &pset)
Declaration of cluster object.
Provides recob::Track data product.
double ConvertTicksToX(double ticks, int p, int t, int c) const
TCEvent evt
Definition: DataStructs.cxx:8
std::size_t count(Cont const &cont)
art framework interface to geometry description
BEGIN_PROLOG could also be cout
auto const detProp
Encapsulate the construction of a single detector plane.