LArSoft  v06_85_00
Liquid Argon Software toolkit - http://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 // ##########################
41 // ### Basic C++ Includes ###
42 // ##########################
43 #include <vector>
44 #include <string>
45 #include <iostream>
46 #include <iomanip>
47 #include <ios>
48 #include <sstream>
49 #include <fstream>
50 #include <cmath>
51 #include <algorithm>
52 #include <vector>
53 
54 // ##########################
55 // ### Framework Includes ###
56 // ##########################
61 #include "fhiclcpp/ParameterSet.h"
69 
70 // ########################
71 // ### LArSoft Includes ###
72 // ########################
86 //#include "RecoAlg/ClusterParamsAlg.h"
87 
88 // #####################
89 // ### ROOT Includes ###
90 // #####################
91 #include "TMath.h"
92 #include "TH1D.h"
93 #include "TVectorD.h"
94 #include "TGeoManager.h"
95 #include "TMath.h"
96 #include "TGraph.h"
97 #include "TF1.h"
98 #include "TVector3.h"
99 
100 // =====================================================================================================
101 // =====================================================================================================
102 #ifndef FeatureVertexFinder_H
103 #define FeatureVertexFinder_H
104 
105 class TH1D;
106 
108 namespace vertex {
109 
111 
112  public:
113 
114  explicit FeatureVertexFinder(fhicl::ParameterSet const& pset);
115  virtual ~FeatureVertexFinder();
116  void beginJob();
117  void reconfigure(fhicl::ParameterSet const& p);
118  void produce(art::Event& evt);
119 
120 
121 
122  private:
123 
124  // ### This function will take in and EndPoint2d from either cluster crawler
125  // ### or corner finder and only save points that make a 3d-candidate
126  void Get3dVertexCandidates(std::vector< art::Ptr<recob::EndPoint2D> > EndPoints, bool PlaneDet);
127 
128  // ### This function will take in 2d Clusters (by default dBCluster)
129  // ### and return 2d vertex candidates for sorting later
131 
132  // ### This function takes in 2d Vertex candidates (found by Find2dClusterVertexCandidates),
133  // ### does some basic merging and then finds 3d-candidates for use later
134  void Find3dVtxFrom2dClusterVtxCand(std::vector<double> Wire_2dvtx, std::vector<double> Time_2dvtx, std::vector<double> Plane_2dvtx);
135 
136  // ### This function merges and sorts all the 3d vertex candidates, it merges
137  // ### them if they are within 2.0 cm in X, Y, and Z simultaneously and then sorts
138  // ### the list by vertex strength and Z location (lowest Z is first on the list
139  void MergeAndSort3dVtxCandidate(std::vector<double> merge_vtxX, std::vector<double> merge_vtxY, std::vector<double> merge_vtxZ, std::vector<double> merge_vtxStgth);
140 
141 
142  std::string fClusterModuleLabel;
143  std::string fHitModuleLabel;
146  //cluster::ClusterParamsAlg fClParAlg;
147  Double_t fRunningMode;
148 
149  bool GT2PlaneDetector = false;
150 
151  // ########################################################
152  // ### Unsorted Raw list of 3d-Vertex candidates filled ###
153  // ########################################################
154  std::vector<double> candidate_x = {0.};
155  std::vector<double> candidate_y = {0.};
156  std::vector<double> candidate_z = {0.};
157  std::vector<double> candidate_strength = {0.};
158 
159 
160  // #############################################################
161  // ### Merged and sorted list of 3d-Vertex candidates filled ###
162  // #############################################################
163  std::vector<double> MergeSort3dVtx_xpos = {0.};
164  std::vector<double> MergeSort3dVtx_ypos = {0.};
165  std::vector<double> MergeSort3dVtx_zpos = {0.};
166  std::vector<double> MergeSort3dVtx_strength = {0.};
167 
168 
169  // ##################################
170  // ### 2d Cluster based Variables ###
171  // ##################################
172  std::vector<std::vector<int> > Cls; //<---- Index to clusters in each view
173  std::vector<double> dtdwstart = {0.}; //<----Slope (delta Time Tick vs delta Wire)
174  std::vector<double> dtdwstartError = {0.}; //<---Error on the slope
175  std::vector<double> Clu_Plane = {0.}; //<---Plane of the current cluster
176  std::vector<double> Clu_StartPos_Wire = {0.}; //<---Starting wire number of cluster
177  std::vector<double> Clu_StartPos_TimeTick = {0.}; //<---Starting TDC value of the cluster
178 
179  std::vector<double> Clu_EndPos_Wire = {0.}; //<---Ending wire number of cluster
180  std::vector<double> Clu_EndPos_TimeTick = {0.}; //<---Ending TDC value of the cluster
181 
182  std::vector<double> Clu_Slope = {0.}; //<---Calculated Slope of the cluster (TDC/Wire)
183  std::vector<double> Clu_Yintercept = {0.}; //<---Clusters Y Intercept using start positions
184  std::vector<double> Clu_Yintercept2 = {0.}; //<---Clusters Y Intercept using end positions
185  std::vector<double> Clu_Length = {0.}; //<---Calculated Length of the cluster
186 
187 
188  // ##################################
189  // ### 2d Cluster based verticies ###
190  // ##################################
191  std::vector<double> TwoDvtx_wire = {0.};
192  std::vector<double> TwoDvtx_time = {0.};
193  std::vector<double> TwoDvtx_plane = {0.};
194  };
195 
196 }//<---End namespace vertex
197 
198 #endif // FeatureVertexFinder_H
199 // =====================================================================================================
200 // =====================================================================================================
201 
202 
203 
204 
205 
206 
207 
208 // =====================================================================================================
209 // =====================================================================================================
210 namespace vertex{
211 
212 //-----------------------------------------------------------------------------
213 // fhicl::ParameterSet
215  //fClParAlg(pset.get<fhicl::ParameterSet>("ClusterParamsAlg"), pset.get< std::string >("module_type"))
216  {
217  /*this->*/reconfigure(pset);
218  produces< std::vector<recob::Vertex> >();
219  produces< std::vector<recob::EndPoint2D> >();
220  produces< art::Assns<recob::EndPoint2D, recob::Hit> >();
221 
222  // === Don't think I'll actually have any of these associations ===
223  // === should consider removing in the future
224  produces< art::Assns<recob::Vertex, recob::Hit> >();
225  produces< art::Assns<recob::Vertex, recob::Shower> >();
226  produces< art::Assns<recob::Vertex, recob::Track> >();
227 
229  Cls.resize(geom->Nplanes(),std::vector<int>());
230  }
231 //-----------------------------------------------------------------------------
232 // Destructor
234  {
235  }
236 
237 //---------------------------------------------------------------------------
239  {
240  fCornerFinderModuleLabel = p.get< std::string >("CornerFinderModuleLabel");
241  fClusterModuleLabel = p.get< std::string >("ClusterModuleLabel");
242  fHitModuleLabel = p.get< std::string >("HitModuleLabel");
243  fCCrawlerEndPoint2dModuleLabel = p.get< std::string >("CCrawlerEndPoint2dModuleLabel");
244  fRunningMode = p.get< double >("RunningMode");
245  return;
246  }
247 //-------------------------------------------------------------------------
248 // BeginJob
250  // get access to the TFile service
252 
253  //std::cout<<"Begin Job"<<std::endl;
254 
255  }
256 
257 // -----------------------------------------------------------------------------
258 // Produce
260  {
261 
262  // #########################
263  // ### Geometry Services ###
264  // #########################
266 
267  // ####################################
268  // ### Detector Properties Services ###
269  // ####################################
270  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
271 
272  // ######################################################
273  // ### Figuring out if I have a 2 or 3 plane detector ###
274  // ######################################################
275  GT2PlaneDetector = false;
276  // ##############################
277  // ### Looping over cryostats ###
278  // ##############################
279  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
280  {
281  // ##########################
282  // ### Looping over TPC's ###
283  // ##########################
284  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
285  {
286  if (geom->Cryostat(cstat).TPC(tpc).Nplanes() > 2){GT2PlaneDetector = true;}
287  }//<---End tpc loop
288  }//<---End cstat loop
289 
290  if(GT2PlaneDetector){std::cout<<"yeah"<<std::endl;}
291 
292  // #######################################################
293  // ### These are the things I want to put on the event ###
294  // #######################################################
295  std::unique_ptr<std::vector<recob::Vertex> > vcol(new std::vector<recob::Vertex>); //3D vertex
296  std::unique_ptr<std::vector<recob::EndPoint2D> > epcol(new std::vector<recob::EndPoint2D>); //2D vertex
297  std::unique_ptr< art::Assns<recob::EndPoint2D, recob::Hit> > assnep(new art::Assns<recob::EndPoint2D, recob::Hit>);
298  std::unique_ptr< art::Assns<recob::Vertex, recob::Shower> > assnsh(new art::Assns<recob::Vertex, recob::Shower>);
299  std::unique_ptr< art::Assns<recob::Vertex, recob::Track> > assntr(new art::Assns<recob::Vertex, recob::Track>);
300  std::unique_ptr< art::Assns<recob::Vertex, recob::Hit> > assnh(new art::Assns<recob::Vertex, recob::Hit>);
301 
302  //std::cout<<"Setup of outputs"<<std::endl;
303 
304 //-------------------------------------------------------------------------------------------------------------------------------------------------
305 //------------------------------------------------------- ClusterCrawler EndPoint2d's -------------------------------------------------------------
306 //-------------------------------------------------------------------------------------------------------------------------------------------------
307  // ####################################################
308  // ### Getting the EndPoint2d's for cluster crawler ###
309  // ####################################################
310  try
311  {
312  art::Handle< std::vector<recob::EndPoint2D> > ccrawlerFinderHandle;
313  evt.getByLabel(fCCrawlerEndPoint2dModuleLabel,ccrawlerFinderHandle);
314  std::vector< art::Ptr<recob::EndPoint2D> > ccrawlerEndPoints;
315  art::fill_ptr_vector(ccrawlerEndPoints, ccrawlerFinderHandle);
316 
317  //std::cout<<"Getting the EndPoint2d's for cluster crawler"<<std::endl;
318  //std::cout<<"Length of ccrawlerEndPoints vector = "<<ccrawlerEndPoints.size()<<std::endl;
319  // ########################################################
320  // ### Passing in the EndPoint2d's from Cluster Crawler ###
321  // ########################################################
322  Get3dVertexCandidates(ccrawlerEndPoints, GT2PlaneDetector);
323  //std::cout<<"Get3dVertexCandidates Cluster Crawler"<<std::endl;
324  //std::cout<<"Number of candidate verticies after cluster crawler = "<<candidate_x.size()<<std::endl;
325  }
326  catch(...)
327  {mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Cluster Crawler";}
328 //-------------------------------------------------------------------------------------------------------------------------------------------------
329 //-------------------------------------------------------- CornerFinder EndPoint2d's --------------------------------------------------------------
330 //-------------------------------------------------------------------------------------------------------------------------------------------------
331  // ##################################################
332  // ### Getting the EndPoint2d's for Corner Finder ###
333  // ##################################################
334  try
335  {
336  art::Handle< std::vector<recob::EndPoint2D> > CornerFinderHandle;
337  evt.getByLabel(fCornerFinderModuleLabel,CornerFinderHandle);
338  std::vector< art::Ptr<recob::EndPoint2D> > cornerEndPoints;
339  art::fill_ptr_vector(cornerEndPoints, CornerFinderHandle);
340 
341  //std::cout<<"Getting the EndPoint2d's for Corner Finder"<<std::endl;
342  //std::cout<<"Length of cornerEndPoints vector = "<<cornerEndPoints.size()<<std::endl;
343 
344  // ######################################################
345  // ### Passing in the EndPoint2d's from Corner Finder ###
346  // ######################################################
347  Get3dVertexCandidates(cornerEndPoints, GT2PlaneDetector);
348  //std::cout<<"Get3dVertexCandidates Corner Finder"<<std::endl;
349  //std::cout<<"Number of candidate verticies after corner finder = "<<candidate_x.size()<<std::endl;
350 
351  }
352  catch(...)
353  {mf::LogWarning("FeatureVertexFinder") << "Failed to get EndPoint2d's from Corner Finder";}
354 
355 
356 //---------------------------------------------------------------------------------------------------------------------------------------------------------
357 //-------------------------------------------------------- Making Cluster Slope EndPoint2d's --------------------------------------------------------------
358 //---------------------------------------------------------------------------------------------------------------------------------------------------------
359  // ###################################################
360  // ### Retreiving the Cluster Module for the event ###
361  // ###################################################
362  try
363  {
364  art::Handle< std::vector<recob::Cluster> > clusterListHandle;
365  evt.getByLabel(fClusterModuleLabel,clusterListHandle);
366 
367  //std::cout<<"Retreiving the Cluster Module for the event"<<std::endl;
368 
369 
370  // #################################################
371  // ### Finding hits associated with the clusters ###
372  // #################################################
373  art::FindManyP<recob::Hit> fmh(clusterListHandle, evt, fClusterModuleLabel);
374  //std::cout<<"Finding hits associated with the clusters"<<std::endl;
375 
376  // ##################################
377  // ### Filling the Cluster Vector ###
378  // ##################################
380  for (unsigned int ii = 0; ii < clusterListHandle->size(); ++ii){
381  art::Ptr<recob::Cluster> clusterHolder(clusterListHandle,ii);
382  clusters.push_back(clusterHolder);
383  }//<---End ii loop
384 
385  //std::cout<<"Number of clusters found = "<<clusters.size()<<std::endl;
386 
387  // ####################################################
388  // ### Passing in the clusters to find 2d Verticies ###
389  // ####################################################
390  Find2dClusterVertexCandidates(clusters, fmh);
391  //std::cout<<"Made 2d vertex candidates"<<std::endl;
392  //std::cout<<"Number of 2d cluster vertex candidates found = "<<TwoDvtx_wire.size()<<std::endl;
393  // ###############################################################
394  // ### Finding 3d Candidates from 2d cluster vertex candidates ###
395  // ###############################################################
397  //std::cout<<"Made 3d vertex candidates from 2d cluster candidates"<<std::endl;
398  //std::cout<<"Number of candidate verticies after cluster step = "<<candidate_x.size()<<std::endl;
399 
400  }
401  catch(...)
402  {mf::LogWarning("FeatureVertexFinder") << "Failed to get Cluster from default cluster module";}
403 
404 
405  // ################################################
406  // ### Merging and sorting 3d vertex candidates ###
407  // ################################################
409  /*std::cout<<std::endl;
410  std::cout<<"Merged and sorted the cadidates"<<std::endl;
411  std::cout<<"Number of merged and sorted verticies = "<<MergeSort3dVtx_xpos.size()<<std::endl;
412  std::cout<<"MergeSort3dVtx_xpos[0] = "<<MergeSort3dVtx_xpos[0]<<std::endl;
413  std::cout<<"MergeSort3dVtx_ypos[0] = "<<MergeSort3dVtx_ypos[0]<<std::endl;
414  std::cout<<"MergeSort3dVtx_zpos[0] = "<<MergeSort3dVtx_zpos[0]<<std::endl;*/
415 
416 
417 //------------------------------------------------------------------------------------------------------------------------------------------------------
418 //-------------------------------------------------------- Putting Verticies on the event --------------------------------------------------------------
419 //------------------------------------------------------------------------------------------------------------------------------------------------------
420 
421  // ########################################################################################################
422  // ### Now that I have a list of 3d vertex candidates I will return 3d/2d verticies ###
423  // ### based on which option the user has chosen ###
424  // ### fRunningMode == 0 (this returns a full list of all 3d/2d vertex candidates) ###
425  // ### fRunningMode == 1 (this returns only one vertex which is established as the most likely primary) ###
426  // ########################################################################################################
427 
428  // =======================================
429  // === Returning all vertex candidates ===
430  // =======================================
431  if(fRunningMode == 0)
432  {
433  // ######################################
434  // ### Looping over Primary Verticies ###
435  // ######################################
436  for(size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++)
437  {
438  // ###############################################
439  // ### Push each primary vertex onto the event ###
440  // ###############################################
441  double tempxyz[3] = {MergeSort3dVtx_xpos[pri], MergeSort3dVtx_ypos[pri], MergeSort3dVtx_zpos[pri]};
442  // ######################################
443  // ### Skipping a vertex that is zero ###
444  // ######################################
445  if(tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0){continue;}
446  recob::Vertex the3Dvertex(tempxyz, vcol->size());
447  vcol->push_back(the3Dvertex);
448  // ---------------------------------------------------------------------
449  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
450  // ---------------------------------------------------------------------
451 
452  // ##############################
453  // ### Looping over cryostats ###
454  // ##############################
455  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
456  {
457  // ### Looping over TPC's ###
458  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
459  {
460  // ### Loop over the wire planes ###
461  for (size_t plane = 0; plane < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++plane)
462  {
463  double temp2dXYZ[3] = {MergeSort3dVtx_xpos[pri], MergeSort3dVtx_ypos[pri], MergeSort3dVtx_zpos[pri]};
464  double temp2dStrength = MergeSort3dVtx_strength[pri];
465  // ######################################
466  // ### Skipping a vertex that is zero ###
467  // ######################################
468  if(temp2dXYZ[0] == 0 && temp2dXYZ[1] == 0 && temp2dXYZ[2] == 0){continue;}
469 
470  // ######################################################################
471  // ### Converting the 3d vertex into 2d time ticks, wire, and channel ###
472  // ######################################################################
473  double EndPoint2d_TimeTick = detprop->ConvertXToTicks(temp2dXYZ[0],plane, tpc, cstat);
474  int EndPoint2d_Wire = 0;
475  int EndPoint2d_Channel = 0;
476  // ### Putting in protection in case NearestWire Fails ###
477  try
478  {EndPoint2d_Wire = geom->NearestWire(temp2dXYZ , plane, tpc, cstat);}
479  catch(...)
480  {mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
481  continue;}
482  // ### Putting in protection in case NearestChannel Fails ###
483  try
484  {EndPoint2d_Channel = geom->NearestChannel(temp2dXYZ, plane, tpc, cstat);}
485  catch(...)
486  {mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
487  continue;}
488 
489  // ### Making geo::WireID and getting the current View number ###
490  geo::View_t View = geom->View(EndPoint2d_Channel);
491  geo::WireID wireID(cstat,tpc,plane,EndPoint2d_Wire);
492 
493  // ################################################
494  // ### Putting the 2d Vertex found on the event ###
495  // ################################################
496  recob::EndPoint2D vertex( EndPoint2d_TimeTick , //<---TimeTick
497  wireID , //<---geo::WireID
498  temp2dStrength , //<---Vtx strength (JA: ?)
499  epcol->size() , //<---Vtx ID (JA: ?)
500  View , //<---Vtx View
501  1 ); //<---Total Charge (JA: Need to figure this one?)
502  epcol->push_back(vertex);
503  }//<---End Plane loop
504  }//<---End TPC loop
505  }//<---End cstat loop
506  }//<---End pri loop
507  }//<---End fRunningMode == 0
508 
509 
510  // ================================================
511  // === Returning only primary vertex candidates ===
512  // ================================================
513  if(fRunningMode != 0)
514  {
515  int position = 0;
516  int bail = 0;
517  // ######################################
518  // ### Looping over Primary Verticies ###
519  // ######################################
520  for(size_t pri = 0; pri < MergeSort3dVtx_xpos.size(); pri++)
521  {
522  // ###############################################
523  // ### Push each primary vertex onto the event ###
524  // ###############################################
525  double tempxyz[3] = {MergeSort3dVtx_xpos[pri], MergeSort3dVtx_ypos[pri], MergeSort3dVtx_zpos[pri]};
526  // ######################################
527  // ### Skipping a vertex that is zero ###
528  // ######################################
529  if(bail > 0){continue;}
530  if(tempxyz[0] == 0 && tempxyz[1] == 0 && tempxyz[2] == 0){continue;}
531  position = pri;
532  bail++;
533  recob::Vertex the3Dvertex(tempxyz, vcol->size());
534  vcol->push_back(the3Dvertex);
535 
536 
537  }
538 
539  // ---------------------------------------------------------------------
540  // --- Now go make the 2DEndPoints that correspond to each 3d vertex ---
541  // ---------------------------------------------------------------------
542 
543  // ##############################
544  // ### Looping over cryostats ###
545  // ##############################
546  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
547  {
548  // ### Looping over TPC's ###
549  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
550  {
551  // ### Loop over the wire planes ###
552  for (size_t plane = 0; plane < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++plane)
553  {
554  double temp2dXYZ[3] = {MergeSort3dVtx_xpos[position], MergeSort3dVtx_ypos[position], MergeSort3dVtx_zpos[position]};
555  double temp2dStrength = MergeSort3dVtx_strength[position];
556 
557  // ######################################################################
558  // ### Converting the 3d vertex into 2d time ticks, wire, and channel ###
559  // ######################################################################
560  double EndPoint2d_TimeTick = detprop->ConvertXToTicks(temp2dXYZ[0],plane, tpc, cstat);
561  int EndPoint2d_Wire = 0;
562  int EndPoint2d_Channel = 0;
563  // ### Putting in protection in case NearestWire Fails ###
564  try
565  {EndPoint2d_Wire = geom->NearestWire(temp2dXYZ , plane, tpc, cstat);}
566  catch(...)
567  {mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
568  continue;}
569  // ### Putting in protection in case NearestChannel Fails ###
570  try
571  {EndPoint2d_Channel = geom->NearestChannel(temp2dXYZ, plane, tpc, cstat);}
572  catch(...)
573  {mf::LogWarning("FeatureVertexFinder") << "2dWire failed";
574  continue;}
575 
576  // ### Making geo::WireID and getting the current View number ###
577  geo::View_t View = geom->View(EndPoint2d_Channel);
578  geo::WireID wireID(cstat,tpc,plane,EndPoint2d_Wire);
579 
580  // ################################################
581  // ### Putting the 2d Vertex found on the event ###
582  // ################################################
583  recob::EndPoint2D vertex( EndPoint2d_TimeTick , //<---TimeTick
584  wireID , //<---geo::WireID
585  temp2dStrength , //<---Vtx strength (JA: ?)
586  epcol->size() , //<---Vtx ID (JA: ?)
587  View , //<---Vtx View
588  1 ); //<---Total Charge (JA: Need to figure this one?)
589  epcol->push_back(vertex);
590  }//<---End Plane loop
591  }//<---End TPC loop
592  }//<---End cstat loop
593  }//<---End fRunningMode == 1
594 
595 
596  mf::LogVerbatim("Summary") << std::setfill('-') << std::setw(175) << "-" << std::setfill(' ');
597  mf::LogVerbatim("Summary") << "FeatureVertexFinder Summary:";
598  for(size_t i = 0; i<epcol->size(); ++i) mf::LogVerbatim("Summary") << epcol->at(i) ;
599  for(size_t i = 0; i<vcol->size(); ++i) mf::LogVerbatim("Summary") << vcol->at(i) ;
600 
601 
602  /*for(size_t j = 0; j<epcol->size(); ++j) std::cout<<" EndPoint2d = " << epcol->at(j) ;
603  std::cout<<std::endl;
604  for(size_t j = 0; j<vcol->size(); ++j) {std::cout<< " Vertex 3d = " << vcol->at(j) << std::endl;}
605  std::cout<<std::endl;*/
606 
607 
608 
609  evt.put(std::move(epcol));
610  evt.put(std::move(vcol));
611  evt.put(std::move(assnep));
612  evt.put(std::move(assntr));
613  evt.put(std::move(assnsh));
614  evt.put(std::move(assnh));
615 
616  // ################################################
617  // ### Clearing vectors at the end of the event ###
618  // ################################################
619  vcol.reset();
620  epcol.reset();
621  candidate_x.clear();
622  candidate_y.clear();
623  candidate_z.clear();
624  candidate_strength.clear();
625  MergeSort3dVtx_xpos.clear();
626  MergeSort3dVtx_ypos.clear();
627  MergeSort3dVtx_zpos.clear();
628  MergeSort3dVtx_strength.clear();
629  dtdwstart.clear();
630  dtdwstartError.clear();
631  Clu_Plane.clear();
632  Clu_StartPos_Wire.clear();
633  Clu_StartPos_TimeTick.clear();
634  Clu_EndPos_Wire.clear();
635  Clu_EndPos_TimeTick.clear();
636  Clu_Slope.clear();
637  Clu_Yintercept.clear();
638  Clu_Yintercept2.clear();
639  Clu_Length.clear();
640  TwoDvtx_wire.clear();
641  TwoDvtx_time.clear();
642  TwoDvtx_plane.clear();
643 
644  }//<--End FeatureVertexFinder::produce
645 
646 
647 
648 
649 
650 //==============================================================================================================================================================================
651 //==============================================================================================================================================================================
652 //==============================================================================================================================================================================
653 //==============================================================================================================================================================================
654 
655 
656 
657 
658 
659 // -----------------------------------------------------------------------------
660 // Get 3d Vertex Candidates
661 // -----------------------------------------------------------------------------
663  {
664  // #########################
665  // ### Geometry Services ###
666  // #########################
668 
669  // ####################################
670  // ### Detector Properties Services ###
671  // ####################################
672  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
673 
674  double y = 0., z = 0.;
675  double yy = 0., zz = 0.;
676  double yy2 = 0., zz2 = 0.;
677  double yy3 = 0., zz3 = 0.;
678  // ##############################
679  // ### Looping over cryostats ###
680  // ##############################
681  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
682  {
683  // ##########################
684  // ### Looping over TPC's ###
685  // ##########################
686  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
687  {
688  // ###############################################################################
689  // ### Now loop over those Endpoints and see if they match up in between views ###
690  // ###############################################################################
691  for(size_t endpt1 = 0; endpt1 < EndPoints.size(); endpt1++)
692  {
693  // #########################################
694  // ### Looping over the rest of the list ###
695  // #########################################
696  for(size_t endpt2 = endpt1+1; endpt2 < EndPoints.size(); endpt2++)
697  {
698  // ##########################################################################
699  // ### Check to make sure we are comparing features from different planes ###
700  // ##########################################################################
701  if(EndPoints.at(endpt1)->WireID().Plane != EndPoints.at(endpt2)->WireID().Plane)
702  {
703  // #############################################################################
704  // ### Get the appropriate time offset for the two planes we are considering ###
705  // #############################################################################
706  float tempXFeature1 = detprop->ConvertTicksToX(EndPoints.at(endpt1)->DriftTime(), EndPoints.at(endpt1)->WireID().Plane, tpc, cstat);
707  float tempXFeature2 = detprop->ConvertTicksToX(EndPoints.at(endpt2)->DriftTime(), EndPoints.at(endpt2)->WireID().Plane, tpc, cstat);
708  // ####################################################################
709  // ### Checking to see if these features have intersecting channels ###
710  // ### and are within 0.5 cm in projected X ###
711  // ####################################################################
712  if( geom->ChannelsIntersect( geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane, EndPoints.at(endpt2)->WireID().Wire, tpc, cstat),
713  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane, EndPoints.at(endpt1)->WireID().Wire, tpc, cstat),
714  yy, zz) &&
715  std::abs(tempXFeature1 - tempXFeature2) < 0.5)
716  {
717  // #####################################################################################
718  // ### Use this fill if we are in a detector with fewer than 3 plane (e.g. ArgoNeuT) ###
719  // #####################################################################################
720  if(!PlaneDet)
721  {
722  candidate_x.push_back(tempXFeature1);
723  candidate_y.push_back(yy);
724  candidate_z.push_back(zz);
725  candidate_strength.push_back(EndPoints.at(endpt1)->Strength() + EndPoints.at(endpt2)->Strength());
726  }//<---End fill for 2 plane detector
727  // ##############################################################################
728  // ### Adding a check to see if I am in a 3-plane detector and therefore need ###
729  // ### to check for a match across more than 2 planes ###
730  // ##############################################################################
731  if(PlaneDet)
732  {
733  // #########################################
734  // ### Looping over the rest of the list ###
735  // #########################################
736  for(size_t endpt3 = endpt2+1; endpt3 < EndPoints.size(); endpt3++)
737  {
738  // ##########################################################################
739  // ### Check to make sure we are comparing features from different planes ###
740  // ##########################################################################
741  if(EndPoints.at(endpt3)->WireID().Plane != EndPoints.at(endpt2)->WireID().Plane &&
742  EndPoints.at(endpt3)->WireID().Plane != EndPoints.at(endpt1)->WireID().Plane &&
743  EndPoints.at(endpt1)->WireID().Plane != EndPoints.at(endpt2)->WireID().Plane )
744  {
745  float tempXFeature3 = detprop->ConvertTicksToX(EndPoints.at(endpt3)->DriftTime(), EndPoints.at(endpt3)->WireID().Plane, tpc, cstat);
746  // ####################################################################################
747  // ### Checking to make sure our third feature has an intersecting channel with our ###
748  // ### other two channels and is within 1.0 cm projected in X ###
749  // ####################################################################################
750  if(geom->ChannelsIntersect( geom->PlaneWireToChannel(EndPoints.at(endpt3)->WireID().Plane, EndPoints.at(endpt3)->WireID().Wire, tpc, cstat),
751  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane, EndPoints.at(endpt1)->WireID().Wire, tpc, cstat),
752  yy3, zz3) &&
753  geom->ChannelsIntersect( geom->PlaneWireToChannel(EndPoints.at(endpt3)->WireID().Plane, EndPoints.at(endpt3)->WireID().Wire, tpc, cstat),
754  geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane, EndPoints.at(endpt2)->WireID().Wire, tpc, cstat),
755  yy2, zz2) &&
756  geom->ChannelsIntersect( geom->PlaneWireToChannel(EndPoints.at(endpt2)->WireID().Plane, EndPoints.at(endpt2)->WireID().Wire, tpc, cstat),
757  geom->PlaneWireToChannel(EndPoints.at(endpt1)->WireID().Plane, EndPoints.at(endpt1)->WireID().Wire, tpc, cstat),
758  yy, zz) &&
759  std::abs(tempXFeature3 - tempXFeature2) < 1.0 && std::abs(tempXFeature3 - tempXFeature1) < 1.0 &&
760  std::abs(tempXFeature1 - tempXFeature2) < 1.0 )
761  {
762  candidate_x.push_back(detprop->ConvertTicksToX(EndPoints.at(endpt1)->DriftTime(), EndPoints.at(endpt1)->WireID().Plane, tpc, cstat));
763 
764  // ###################################
765  // ### Finding intersection points ###
766  // ###################################
767  geom->IntersectionPoint(EndPoints.at(endpt1)->WireID().Wire, EndPoints.at(endpt2)->WireID().Wire,
768  EndPoints.at(endpt1)->WireID().Plane, EndPoints.at(endpt2)->WireID().Plane, cstat, tpc, y, z);
769 
770  candidate_y.push_back(y);
771  candidate_z.push_back(z);
772  candidate_strength.push_back(EndPoints.at(endpt1)->Strength()+EndPoints.at(endpt2)->Strength()+EndPoints.at(endpt3)->Strength());
773 
774  // ### Note: If I've made it here I have a matched triplet...since I don't want to use any of these ###
775  // ### features again I am going to iterate each of the counters so we move to the next one ###
776  if(endpt1 < EndPoints.size())
777  {endpt1++;}
778  if(endpt2 < EndPoints.size())
779  {endpt2++;}
780  if(endpt3 < EndPoints.size())
781  {endpt3++;}
782  }//<---End finding 3d point across all three planes
783 
784  }//<---End checking for all different planes
785  }//<---End endpt3
786 
787  }//<---End fill for 3 plane detector
788 
789  }//<---End intersecting channels
790 
791  }//<---End making sure we are looking across planes
792  }//<---End endpt2 loop
793  }//<---End endpt1 loop
794  }//<---End TPC loop
795  }//<---End cstat
796 
797 
798 
799  }//<---End Get3dVertexCandidates
800 
801 
802 
803 
804 // -----------------------------------------------------------------------------
805 // Get 2d Vertex Candidates from clusters
806 // -----------------------------------------------------------------------------
808  {
809  // #########################
810  // ### Geometry Services ###
811  // #########################
813 
814  // ####################################
815  // ### Detector Properties Services ###
816  // ####################################
817  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
818 
819  int nClustersFound = 0;
820 
821  // Initialize Cls
822  for(auto& c : Cls) c.clear();
823 
824  for(size_t iclu = 0; iclu < RawClusters.size(); ++iclu)
825  {
826  // ### Gathering the hits associated with the current cluster ###
827  std::vector< art::Ptr<recob::Hit> > hit = fmhit.at(iclu);
828 
829  // ### I only want to consider this cluster if it has a sufficient number of hits ###
830  if(hit.size() < 15){continue;}
831 
832  // ######################################################
833  // ### Determine which view the current cluster is in ###
834  // ######################################################
835  const geo::View_t view = RawClusters.at(iclu)->View();
836  if(view >= Cls.size()) {
837  std::cerr << __PRETTY_FUNCTION__
838  <<"\033[93m Logic error in my code ... view " << view << " not supported ! \033[00m"
839  << std::endl;
840  throw std::exception();
841  }
842 
843  Cls.at(RawClusters.at(iclu)->View()).push_back(iclu);
844  /*
845  switch(RawClusters[iclu]->View())
846  {
847  case geo::kU :
848  Cls[0].push_back(iclu);
849  break;
850  case geo::kV :
851  Cls[1].push_back(iclu);
852  break;
853  case geo::kZ :
854  Cls[2].push_back(iclu);
855  break;
856  default :
857  break;
858  }
859  */
860  // #############################################################
861  // ### Filling wires and times into a TGraph for the cluster ###
862  // #############################################################
863  std::vector<double> wires;
864  std::vector<double> times;
865 
866  // ### Counting the number of hits in the current cluster (n) ###
867  int n = 0;
868  // ############################################
869  // ### Looping over the hits in the cluster ###
870  // ############################################
871  for(size_t i = 0; i < hit.size(); ++i)
872  {
873  wires.push_back(hit[i]->WireID().Wire);
874  times.push_back(hit[i]->PeakTime());
875  ++n;
876  }//<---End loop over hits (i)
877  // ################################################################
878  // ### If there are 2 or more hits in the cluster fill a TGraph ###
879  // ### and fit a from a polynomial or order 1 ###
880  // ################################################################
881  if(n>=15)
882  {
883  // ###################################
884  // ### Push the hits into a TGraph ###
885  // ###################################
886  TGraph *the2Dtrack = new TGraph(n,&wires[0],&times[0]);
887  // === Try to fit the TGraph with a 1st order polynomial ===
888  try
889  {
890  the2Dtrack->Fit("pol1","Q");
891  TF1 *pol1=(TF1*) the2Dtrack->GetFunction("pol1");
892  double par[2];
893  double parerror[2];
894  pol1->GetParameters(par);
895  parerror[1] = pol1->GetParError(1);
896  double FitChi2 = pol1->GetChisquare();
897  double FitNDF = pol1->GetNDF();
898 
899  double fitGoodness = FitChi2/FitNDF;
900 
901  // ######################################################
902  // ### Skipping the fitted slope if the Chi2/NDF < 5 ###
903  // ######################################################
904  if( fitGoodness > 10)
905  {
906  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
907  continue;
908 
909  }//<---End check on chi2/ndf fit
910 
911  // #######################################################################
912  // ### Take change in time tick vs change in wire (dT/dW) from the fit ###
913  // #######################################################################
914  dtdwstart.push_back(par[1]);
915  dtdwstartError.push_back(parerror[1]);
916  }//<---End try to fit with a polynomial order 1
917 
918 
919  // ### If the fitter fails just take dT/dW from the cluster ###
920  catch(...)
921  {
922  mf::LogWarning("FeatureVertexFinder") << "Fitter failed, using the clusters default dTdW()";
923  delete the2Dtrack;
924  dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));
925  continue;
926  }
927 
928  delete the2Dtrack;
929  }//<---End if the cluster has 2 or more hits
930  // #################################################
931  // ### If the cluster has fewer than 2 hits just ###
932  // ### take the dT/dW from the cluster ###
933  // #################################################
934  else {dtdwstart.push_back(std::tan(RawClusters[iclu]->StartAngle()));}
935  }//<---End loop over clusters iclu
936 
937 
938 
939  // ##########################################################################################
940  // ##########################################################################################
941  // ### Now that I have slopes for all the clusters move on to finding intersection points ###
942  // ##########################################################################################
943  // ##########################################################################################
944 
945 
946  // ##############################
947  // ### Looping over cryostats ###
948  // ##############################
949  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
950  {
951  // ##########################
952  // ### Looping over TPC's ###
953  // ##########################
954  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
955  {
956  // #################################
957  // ### Loop over the wire planes ###
958  // #################################
959  for (unsigned int i = 0; i < geom->Cryostat(cstat).TPC(tpc).Nplanes(); ++i)
960  {
961  // ##############################################
962  // ### If there is at least one cluster found ###
963  // ##############################################
964  if (Cls[i].size() >= 1)
965  {
966  // ##############################
967  // ### Loop over each cluster ###
968  // ##############################
969  for (unsigned int j = 0; j<Cls[i].size(); ++j)
970  {
971  // === Current Clusters Plane ===
972  Clu_Plane.push_back(RawClusters.at(Cls.at(i).at(j))->View());
973  // === Current Clusters StartPos ===
974  Clu_StartPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->StartWire());
975  Clu_StartPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->StartTick());
976  // === Current Clusters EndPos ===
977  Clu_EndPos_Wire.push_back(RawClusters.at(Cls.at(i).at(j))->EndWire());
978  Clu_EndPos_TimeTick.push_back(RawClusters.at(Cls.at(i).at(j))->EndTick());
979  // === Current Clusters Slope (In Wire and Time Tick)
980  Clu_Slope.push_back(dtdwstart[Cls[i][j]]);
981  Clu_Length.push_back(std::sqrt(pow((RawClusters.at(Cls.at(i).at(j))->StartWire()-RawClusters.at(Cls.at(i).at(j))->EndWire())*13.5,2) +
982  pow(RawClusters.at(Cls.at(i).at(j))->StartTick()-RawClusters.at(Cls.at(i).at(j))->EndTick(),2)));
983  // ######################################################
984  // ### Given a slope and a point find the y-intercept ###
985  // ### c = y-mx ###
986  // ######################################################
987  Clu_Yintercept.push_back(RawClusters.at(Cls.at(i).at(j))->StartTick() - (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->StartWire()));
988  // #################################################################
989  // ### Also calculating the y-intercept but using the ###
990  // ### end time of the cluster correct for the possibility ###
991  // ### that the clustering didn't get start and end points right ###
992  // #################################################################
993  Clu_Yintercept2.push_back(RawClusters.at(Cls.at(i).at(j))->EndTick() - (dtdwstart[Cls[i][j]] * RawClusters.at(Cls.at(i).at(j))->EndWire()));
994 
995  // #######################################################
996  // ### Iterating on the total number of clusters found ###
997  // #######################################################
998 
999  nClustersFound++;
1000  }//<---End loop over all clusters
1001 
1002  }//<---End check if we have at least one cluster
1003  // ################################################################
1004  // ## If no clusters were found then put in dummy vertex values ###
1005  // ################################################################
1006  else
1007  {
1008  TwoDvtx_wire.push_back(-1);
1009  TwoDvtx_time.push_back(-1);
1010  TwoDvtx_plane.push_back(-1);
1011  }//<---End no clusters found else statement
1012 
1013  }//<---End loop over planes (i)
1014  }//<---End loop over tpc's
1015  }//<---End loop over cryostats
1016 
1017  // ##########################################################################
1018  // ### Now loop over all the clusters found and establish a preliminary ###
1019  // ### set of 2d-verticies based on the slope/intercept of those clusters ###
1020  // ##########################################################################
1021  for(unsigned int n = nClustersFound; n > 0; n--)
1022  {
1023  // #######################################################
1024  // ### Looping over the clusters starting from the ###
1025  // ### first cluster and checking against the nCluster ###
1026  // #######################################################
1027  for (unsigned int m = 0; m < n; m++)
1028  {
1029  // ###########################################################
1030  // ### Checking to make sure clusters are in the same view ###
1031  // ###########################################################
1032  if(Clu_Plane[n] == Clu_Plane[m])
1033  {
1034  // --- Skip the vertex if the lines slope don't intercept ---
1035  if(Clu_Slope[m] - Clu_Slope[n] == 0){break;}
1036  // ============================================================
1037  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
1038  float intersection_X = (Clu_Yintercept[n] - Clu_Yintercept[m]) / (Clu_Slope[m] - Clu_Slope[n]);
1039  // ================================================
1040  // === Y intersection = (slope1 * XInt) + yInt1 ===
1041  float intersection_Y = (Clu_Slope[m] * intersection_X) + Clu_Yintercept[m];
1042  // ============================================================
1043  // === X intersection = (yInt2 - yInt1) / (slope1 - slope2) ===
1044  float intersection_X2 = (Clu_Yintercept2[n] - Clu_Yintercept2[m]) / (Clu_Slope[m] - Clu_Slope[n]);
1045  // ================================================
1046  // === Y intersection = (slope1 * XInt) + yInt1 ===
1047  float intersection_Y2 = (Clu_Slope[m] * intersection_X2) + Clu_Yintercept2[m];
1048 
1049  // #########################################
1050  // ### Skipping crap intersection points ###
1051  // #########################################
1052  if(intersection_X2 < 1){intersection_X2 = -999;}
1053  if(intersection_X2 > geom->Nwires(Clu_Plane[m],0,0)){intersection_X2 = -999;}
1054  if(intersection_Y2 < 0){intersection_Y2 = -999;}
1055  if(intersection_Y2 > detprop->NumberTimeSamples() ){intersection_Y2 = -999;}
1056  if(intersection_X < 1){intersection_X = -999;}
1057  if(intersection_X > geom->Nwires(Clu_Plane[m],0,0)){intersection_X = -999;}
1058  if(intersection_Y < 0){intersection_Y = -999;}
1059  if(intersection_Y > detprop->NumberTimeSamples() ){intersection_Y = -999;}
1060 
1061  // ############################################################
1062  // ### Putting in a protection for the findManyHit function ###
1063  // ############################################################
1064  try
1065  {
1066  // ### Gathering the hits associated with the current cluster ###
1067  std::vector< art::Ptr<recob::Hit> > hitClu1 = fmhit.at(m);
1068  std::vector< art::Ptr<recob::Hit> > hitClu2 = fmhit.at(n);
1069 
1070  // ### If the intersection point is 80 or more wires away from either cluster
1071  // ### and one of the clusters has fewer than 8 hits the intersection
1072  // ### is likely a crap one and we won't save this point
1073  if((abs( Clu_EndPos_Wire[m] - intersection_X2 ) > 80 && hitClu1.size() < 8) ||
1074  (abs( Clu_EndPos_Wire[n] - intersection_X2 ) > 80 && hitClu2.size() < 8) )
1075  {intersection_X2 = -999;intersection_Y2 = -999;}
1076 
1077  if((abs( Clu_StartPos_Wire[m] - intersection_X ) > 80 && hitClu1.size() < 8) ||
1078  (abs( Clu_StartPos_Wire[n] - intersection_X ) > 80 && hitClu2.size() < 8) )
1079  {intersection_X = -999;intersection_Y = -999;}
1080 
1081  // ### If the intersection point is 50 or more wires away from either cluster
1082  // ### and the one of the clusters has fewer than 3 hits the intersection
1083  // ### is likely a crap one and we won't save this point
1084  if((abs( Clu_EndPos_Wire[m] - intersection_X2 ) > 50 && hitClu1.size() < 4) ||
1085  (abs( Clu_EndPos_Wire[n] - intersection_X2 ) > 50 && hitClu2.size() < 4) )
1086  {intersection_X2 = -999;intersection_Y2 = -999;}
1087 
1088  if((abs( Clu_StartPos_Wire[m] - intersection_X ) > 50 && hitClu1.size() < 4) ||
1089  (abs( Clu_StartPos_Wire[n] - intersection_X ) > 50 && hitClu2.size() < 4) )
1090  {intersection_X = -999;intersection_Y = -999;}
1091 
1092  }
1093  catch(...)
1094  {
1095  mf::LogWarning("FeatureVertexFinder") << "FindManyHit Function faild";
1096  intersection_X = -999;intersection_Y = -999;
1097  intersection_X2 = -999;intersection_Y2 = -999;
1098  continue;
1099  }
1100 
1101  // ##########################################################################
1102  // ### Push back a candidate 2dClusterVertex if it is inside the detector ###
1103  // ##########################################################################
1104  if( intersection_X2 > 1 && intersection_Y2 > 0 &&
1105  ( intersection_X2 < geom->Nwires(Clu_Plane[m],0,0) ) &&
1106  ( intersection_Y2 < detprop->NumberTimeSamples() ) )
1107  {
1108 
1109  TwoDvtx_wire.push_back(intersection_X2);
1110  TwoDvtx_time.push_back(intersection_Y2);
1111  TwoDvtx_plane.push_back(Clu_Plane[m]);
1112  }//<---End saving a "good 2d vertex" candidate
1113 
1114  // ##########################################################################
1115  // ### Push back a candidate 2dClusterVertex if it is inside the detector ###
1116  // ##########################################################################
1117  if( intersection_X > 1 && intersection_Y > 0 &&
1118  ( intersection_X < geom->Nwires(Clu_Plane[m],0,0) ) &&
1119  ( intersection_Y < detprop->NumberTimeSamples() ) )
1120  {
1121  TwoDvtx_wire.push_back(intersection_X);
1122  TwoDvtx_time.push_back(intersection_Y);
1123  TwoDvtx_plane.push_back(Clu_Plane[m]);
1124  }//<---End saving a "good 2d vertex" candidate
1125 
1126  }//<---End check that they are in differnt planes
1127  }//<---End m loop
1128  }//<---End n loop
1129 
1130  }//<---End 2dClusterVertexCandidates
1131 
1132 
1133 
1134 
1135 
1136 
1137 
1138 
1139 
1140 
1141 
1142 
1143 // -----------------------------------------------------------------------------
1144 // Get 3d Vertex Candidates from clusters 2d Vertex candidates
1145 // -----------------------------------------------------------------------------
1146 void vertex::FeatureVertexFinder::Find3dVtxFrom2dClusterVtxCand(std::vector<double> Wire_2dvtx, std::vector<double> Time_2dvtx, std::vector<double> Plane_2dvtx)
1147  {
1148 
1149  //std::cout<<"####################################################################"<<std::endl;
1150  //std::cout<<"Get 3d Vertex Candidates from clusters 2d Vertex candidates Function"<<std::endl;
1151  //std::cout<<std::endl;
1152  std::vector<double> vtx_wire_merged;
1153  std::vector<double> vtx_time_merged;
1154  std::vector<double> vtx_plane_merged;
1155 
1156  double y_coord = 0, z_coord = 0;
1157 
1158  bool merged = false;
1159 
1160  // #########################
1161  // ### Geometry Services ###
1162  // #########################
1164 
1165  // ####################################
1166  // ### Detector Properties Services ###
1167  // ####################################
1168  const detinfo::DetectorProperties* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
1169 
1170  // ---------------------- MERGING THE LONG LIST OF 2D CANDIDATES ---------------------------
1171 
1172  // #########################################
1173  // ### Looping over 2d-verticies (loop1) ###
1174  // #########################################
1175  for(size_t vtxloop1 = 0 ; vtxloop1 < Wire_2dvtx.size(); vtxloop1++)
1176  {
1177  if(Wire_2dvtx[vtxloop1] < 0){continue;}
1178 
1179  merged = false;
1180  // #########################################
1181  // ### Looping over 2d-verticies (loop2) ###
1182  // #########################################
1183  for(size_t vtxloop2 = vtxloop1+1; vtxloop2 < Wire_2dvtx.size(); vtxloop2++)
1184  {
1185  if(Wire_2dvtx[vtxloop2] < 0){continue;}
1186 
1187  // ########################################################
1188  // ### Make sure the 2d-Verticies are in the same plane ###
1189  // ########################################################
1190  if(Plane_2dvtx[vtxloop1] == Plane_2dvtx[vtxloop2])
1191  {
1192  // ###############################################
1193  // ### Considering merging 2d vertices if they ###
1194  // ### are within 3 wires of each other ###
1195  // ###############################################
1196  if( fabs(Wire_2dvtx[vtxloop1] - Wire_2dvtx[vtxloop2]) < 4 )
1197  {
1198  // ############################################################
1199  // ### Merge the verticies if they are within 10 time ticks ###
1200  // ############################################################
1201  if( fabs(Time_2dvtx[vtxloop1] - Time_2dvtx[vtxloop2]) < 10 )
1202  {
1203  vtx_wire_merged.push_back( ((Wire_2dvtx[vtxloop2] + Wire_2dvtx[vtxloop1])/ 2) );
1204  vtx_time_merged.push_back( ((Time_2dvtx[vtxloop2] + Time_2dvtx[vtxloop1])/ 2) ) ;
1205  vtx_plane_merged.push_back( Plane_2dvtx[vtxloop1] );
1206 
1207  merged = true;
1208  if(vtxloop2<Wire_2dvtx.size()){vtxloop2++;}
1209  if(vtxloop1<Wire_2dvtx.size()){vtxloop1++;}
1210  }//<---End the check within 10 time ticks for merging
1211  }//<---Looking at vertices that are within 3 wires of each other
1212  }//<---Only looking at vertices that are in the same plane
1213  }//<---End vtxloop2
1214  if(!merged)
1215  {
1216  vtx_wire_merged.push_back( Wire_2dvtx[vtxloop1] );
1217  vtx_time_merged.push_back( Time_2dvtx[vtxloop1] );
1218  vtx_plane_merged.push_back( Plane_2dvtx[vtxloop1] );
1219  }//<---end saving unmerged verticies
1220  }//<---End vtxloop1
1221 
1222  // #####################################
1223  // ### Variables for channel numbers ###
1224  // #####################################
1225  uint32_t vtx1_channel = 0;
1226  uint32_t vtx2_channel = 0;
1227  // --------------------------------------------------------------------------
1228  // --- Having now found a very long list of potential 2-d end points ---
1229  // --- we need to check if any of them match between planes and only keep ---
1230  // --- those that have matches ---
1231  // --------------------------------------------------------------------------
1232  // ##############################
1233  // ### Looping over cryostats ###
1234  // ##############################
1235  for(size_t cstat = 0; cstat < geom->Ncryostats(); ++cstat)
1236  {
1237  // ##########################
1238  // ### Looping over TPC's ###
1239  // ##########################
1240  for(size_t tpc = 0; tpc < geom->Cryostat(cstat).NTPC(); ++tpc)
1241  {
1242  for(unsigned int vtx = vtx_wire_merged.size(); vtx > 0; vtx--)
1243  {
1244  for (unsigned int vtx1 = 0; vtx1 < vtx; vtx1++)
1245  {
1246  // ###########################################################################
1247  // ### Check to make sure we are comparing verticies from different planes ###
1248  // ###########################################################################
1249  if(vtx_plane_merged[vtx1] != vtx_plane_merged[vtx])
1250  {
1251  // === To figure out if these two verticies are from a common point
1252  // === we need to check if the channels intersect and if they are
1253  // === close in time ticks as well...to do this we have to do some
1254  // === converting to use geom->PlaneWireToChannel(PlaneNo, Wire, tpc, cstat)
1255  bool match = false;
1256 
1257  unsigned int vtx1_plane = vtx_plane_merged[vtx1];
1258  unsigned int vtx1_wire = vtx_wire_merged[vtx1];
1259  try
1260  {vtx1_channel = geom->PlaneWireToChannel(vtx1_plane, vtx1_wire, tpc, cstat);}
1261  catch(...)
1262  {mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
1263  match = false;
1264  continue;}
1265 
1266  unsigned int vtx2_plane = vtx_plane_merged[vtx];
1267  unsigned int vtx2_wire = vtx_wire_merged[vtx];
1268  try
1269  {vtx2_channel = geom->PlaneWireToChannel(vtx2_plane, vtx2_wire, tpc, cstat);}
1270  catch(...)
1271  {mf::LogWarning("FeatureVertexFinder") << "PlaneWireToChannel Failed";
1272  match = false;
1273  continue;}
1274 
1275  // ##############################################################################
1276  // ### Check to see if the channels intersect and save the y and z coordinate ###
1277  // ##############################################################################
1278 
1279  try
1280  {match = geom->ChannelsIntersect( vtx1_channel, vtx2_channel, y_coord, z_coord);}
1281  catch(...)
1282  {mf::LogWarning("FeatureVertexFinder") << "match failed for some reason";
1283  match = false;
1284  continue;}
1285  // ####################################################################
1286  // ### If the channels intersect establish if they are close in "X" ###
1287  // ####################################################################
1288  if( match )
1289  {
1290  float tempXCluster1 = detprop->ConvertTicksToX(vtx_time_merged[vtx1], vtx1_plane, tpc, cstat);
1291  float tempXCluster2 = detprop->ConvertTicksToX(vtx_time_merged[vtx], vtx2_plane, tpc, cstat);
1292  // ###############################################################################
1293  // ### Now check if the matched channels are within 0.5 cm when projected in X ###
1294  // ### and that we have less than 100 of these candidates... ###
1295  // ### because more than that seems silly ###
1296  // ###############################################################################
1297  if(std::abs(tempXCluster1 - tempXCluster2) < 0.5 && candidate_x.size() < 101)
1298  {
1299  // detprop->ConvertTicksToX(ticks, plane, tpc, cryostat)
1300  candidate_x.push_back( detprop->ConvertTicksToX(vtx_time_merged[vtx1], vtx_plane_merged[vtx1], tpc, cstat) );
1301  candidate_y.push_back( y_coord );
1302  candidate_z.push_back( z_coord );
1303  candidate_strength.push_back( 10 ); //<--For cluster verticies I give it a strength of "10" arbitrarily for now
1304 
1305  }//<---End Checking if the vertices agree "well enough" in time tick
1306  }//<---End Checking if verticies intersect
1307 
1308  }//<--- End checking we are in different planes
1309  }//<---end vtx1 for loop
1310  }//<---End vtx for loop
1311  }//<---End loop over TPC's
1312  }//<---End loop over cryostats
1313 
1314  }//<---End Find3dVtxFrom2dClusterVtxCand
1315 
1316 
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324 // -----------------------------------------------------------------------------
1325 // Get 3d Vertex Candidates from clusters 2d Vertex candidates
1326 // -----------------------------------------------------------------------------
1327 void vertex::FeatureVertexFinder::MergeAndSort3dVtxCandidate(std::vector<double> merge_vtxX, std::vector<double> merge_vtxY, std::vector<double> merge_vtxZ, std::vector<double> merge_vtxStgth)
1328  {
1329 
1330  std::vector<double> x_3dVertex_dupRemoved = {0.};
1331  std::vector<double> y_3dVertex_dupRemoved = {0.};
1332  std::vector<double> z_3dVertex_dupRemoved = {0.};
1333  std::vector<double> strength_dupRemoved = {0.};
1334 
1335  // #####################################################
1336  // ### Looping over the 3d candidates found thus far ###
1337  // #####################################################
1338  for(size_t dup = 0; dup < merge_vtxX.size(); dup ++)
1339  {
1340  // ### Temperary storing the current vertex ###
1341  float tempX_dup = merge_vtxX[dup];
1342  float tempY_dup = merge_vtxY[dup];
1343  float tempZ_dup = merge_vtxZ[dup];
1344  float tempStgth = merge_vtxStgth[dup];
1345 
1346  // #######################################################
1347  // ### Setting a boolian to see if this is a duplicate ###
1348  // #######################################################
1349  bool duplicate_found = false;
1350  // #############################################################
1351  // ### Looping over the rest of the list for duplicate check ###
1352  // #############################################################
1353  for(size_t check = dup+1; check < merge_vtxX.size(); check++)
1354  {
1355  // #############################################################################
1356  // ### I am going to call a duplicate vertex one that matches in x, y, and z ###
1357  // ### within 0.1 cm for all 3 coordinates simultaneously ###
1358  // #############################################################################
1359  if(std::abs( merge_vtxX[check] - tempX_dup ) < 0.1 && std::abs( merge_vtxY[check] - tempY_dup ) < 0.1 &&
1360  std::abs( merge_vtxZ[check] - tempZ_dup ) < 0.1 )
1361  {duplicate_found = true;}//<---End checking to see if this is a duplicate vertex
1362 
1363  }//<---End check for loop
1364 
1365  // ######################################################################
1366  // ### If we didn't find a duplicate then lets save this 3d vertex as ###
1367  // ### a real candidate for consideration ###
1368  // ######################################################################
1369  if(!duplicate_found && tempX_dup > 0)
1370  {
1371  x_3dVertex_dupRemoved.push_back(tempX_dup);
1372  y_3dVertex_dupRemoved.push_back(tempY_dup);
1373  z_3dVertex_dupRemoved.push_back(tempZ_dup);
1374  strength_dupRemoved.push_back(tempStgth);
1375  }//<---End storing only non-duplicates
1376 
1377  }//<---End dup for loop
1378 
1379  // ########################################################################################
1380  // ### Sorting the verticies I have found such that the first in the list is the vertex ###
1381  // ### with the highest vertex strength and the lowest z location ###
1382  // ########################################################################################
1383 
1384  int flag = 1;
1385  double tempX, tempY, tempZ, tempS;
1386 
1387  // #####################################################
1388  // ### Looping over all duplicate removed candidates ###
1389  // #####################################################
1390  for(size_t npri = 0; (npri < x_3dVertex_dupRemoved.size()) && flag; npri++)
1391  {
1392  flag = 0;
1393  for(size_t mpri = 0; mpri < x_3dVertex_dupRemoved.size() -1; mpri++)
1394  {
1395  // Swap the order of the two elements
1396  if(strength_dupRemoved[mpri+1] > strength_dupRemoved[mpri] ||
1397  (strength_dupRemoved[mpri+1] == strength_dupRemoved[mpri] && z_3dVertex_dupRemoved[mpri] > z_3dVertex_dupRemoved[mpri+1]) )
1398  {
1399  tempX = x_3dVertex_dupRemoved[mpri];
1400  x_3dVertex_dupRemoved[mpri] = x_3dVertex_dupRemoved[mpri+1];
1401  x_3dVertex_dupRemoved[mpri+1] = tempX;
1402 
1403  tempY = y_3dVertex_dupRemoved[mpri];
1404  y_3dVertex_dupRemoved[mpri] = y_3dVertex_dupRemoved[mpri+1];
1405  y_3dVertex_dupRemoved[mpri+1] = tempY;
1406 
1407  tempZ = z_3dVertex_dupRemoved[mpri];
1408  z_3dVertex_dupRemoved[mpri] = z_3dVertex_dupRemoved[mpri+1];
1409  z_3dVertex_dupRemoved[mpri+1] = tempZ;
1410 
1411  tempS = strength_dupRemoved[mpri];
1412  strength_dupRemoved[mpri] = strength_dupRemoved[mpri+1];
1413  strength_dupRemoved[mpri+1] = tempS;
1414 
1415  flag = 1;
1416 
1417  }//<---Inside swap loop
1418  }//<---End mpri
1419  }//<---End npri loop
1420 
1421  // ############################################################
1422  // ### Pushing into a vector of merged and sorted verticies ###
1423  // ############################################################
1424  for(size_t count = 0; count < x_3dVertex_dupRemoved.size(); count++)
1425  {
1426  MergeSort3dVtx_xpos.push_back(x_3dVertex_dupRemoved[count]);
1427  MergeSort3dVtx_ypos.push_back(y_3dVertex_dupRemoved[count]);
1428  MergeSort3dVtx_zpos.push_back(z_3dVertex_dupRemoved[count]);
1429  MergeSort3dVtx_strength.push_back(strength_dupRemoved[count]);
1430 
1431 
1432 
1433  }//<---End count loop
1434 
1435 
1436  }// End MergeAndSort3dVtxCandidate
1437 
1439 
1440 // -----------------------------------------------------------------------------
1441 
1442 }//<---End namespace vertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
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.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
void Find3dVtxFrom2dClusterVtxCand(std::vector< double > Wire_2dvtx, std::vector< double > Time_2dvtx, std::vector< double > Plane_2dvtx)
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
Declaration of signal hit object.
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:279
bool ChannelsIntersect(raw::ChannelID_t c1, raw::ChannelID_t c2, double &y, double &z) const
Returns an intersection point of two channels.
Double_t zz
Definition: plot.C:279
void reconfigure(fhicl::ParameterSet const &p)
std::vector< double > MergeSort3dVtx_strength
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition of vertex object for LArSoft.
Definition: Vertex.h:35
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
void Find2dClusterVertexCandidates(art::PtrVector< recob::Cluster > RawClusters, art::FindManyP< recob::Hit > fmhit)
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::vector< std::vector< int > > Cls
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:441
void Get3dVertexCandidates(std::vector< art::Ptr< recob::EndPoint2D > > EndPoints, bool PlaneDet)
T get(std::string const &key) const
Definition: ParameterSet.h:231
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:155
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
reference at(size_type n)
Definition: PtrVector.h:365
FeatureVertexFinder(fhicl::ParameterSet const &pset)
virtual unsigned int NumberTimeSamples() const =0
Declaration of cluster object.
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
Provides recob::Track data product.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
size_type size() const
Definition: PtrVector.h:308
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
Utility object to perform functions of association.
Encapsulate the construction of a single detector plane.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Char_t n[5]
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:464
raw::ChannelID_t NearestChannel(geo::Point_t const &worldLoc, geo::PlaneID const &planeid) const
Returns the ID of the channel nearest to the specified position.
Definition: fwd.h:25
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