LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LineMerger_module.cc
Go to the documentation of this file.
1 //
3 // LineMerger class
4 //
5 // maddalena.antonello@lngs.infn.it
6 // ornella.palamara@lngs.infn.it
7 // biagio.rossi@lhep.unibe.ch
8 // msoderbe@syr.edu
9 // joshua.spitz@yale.edu
10 //
11 // This algorithm is designed to merge 2D lines with similar slope and endpoints
12 //
14 
15 #include <string>
16 #include <cmath> // std::abs(), std::sqrt()
17 #include <iomanip>
18 #include <vector>
19 #include <array>
20 #include <memory> // std::unique_ptr<>
21 #include <utility> // std::move()
22 
23 
24 //Framework includes:
25 #include "fhiclcpp/ParameterSet.h"
34 
35 //LArSoft includes:
43 
44 
45 
46 //#ifndef LINEMERGER_H
47 //#define LINEMERGER_H
48 
49 
50 namespace cluster {
51 
52  class LineMerger : public art::EDProducer {
53 
54  public:
55 
56  explicit LineMerger(fhicl::ParameterSet const& pset);
57  ~LineMerger();
58 
59  void produce(art::Event& evt);
60  void beginJob();
61 
62  private:
63 
64  std::string fClusterModuleLabel;
65  double fSlope; // tolerance for matching angles between two lines (in units of radians)
66  double fEndpointWindow; // tolerance for matching endpoints (in units of time samples)
67 
68  bool SlopeCompatibility(double slope1,double slope2);
70  float sclstartwire, float sclstarttime,
71  float sclendwire, float sclendtime,
72  float cl2startwire, float cl2starttime,
73  float cl2endwire, float cl2endtime
74  );
75 
76  protected:
77 
78  }; // class LineMerger
79 
80 }
81 
82 //#endif // LINEMERGER_H
83 
84 
85 
86 namespace cluster{
87 
88 
90  class ClusterMerger {
91  public:
92  // NOTE if you feel like copying this class, move it into its own header
93  // instead, and if you need it for a different hit or hit pointer, make it
94  // a template instead
96  using HitVector_t = std::vector<HitPtr_t>;
97 
100 
101  /*
102  typedef enum {
103  clStart, ///< Represents the most likely start of the cluster
104  clEnd, ///< Represents the end, or the alternative start, of the cluster
105  NEnds, ///< End count
106  clFirstEnd = 0 ///< Just an alias for loops
107  } ClusterEnds_t; ///< Used to decide which end to use
108  */
109 
110  ClusterMerger() = default;
111 
113  ClusterMerger()
114  { Add(cluster); }
115 
131  bool Add(recob::Cluster const& cluster);
132 
133 
136 
138  float StartWire() const { return fEndWires[ClusterEnds_t::clStart]; }
139 
141  float StartTick() const { return fEndTicks[ClusterEnds_t::clStart]; }
142 
144  float SigmaStartWire() const { return fSigmaEndWires[ClusterEnds_t::clStart]; }
145 
146  // Returns the uncertainty on tick coordinate of the start of the cluster
147  float SigmaStartTick() const { return fSigmaEndTicks[ClusterEnds_t::clStart]; }
148 
150  float EndWire() const { return fEndWires[ClusterEnds_t::clEnd]; }
151 
153  float EndTick() const { return fEndTicks[ClusterEnds_t::clEnd]; }
154 
156  float SigmaEndWire() const { return fSigmaEndWires[ClusterEnds_t::clEnd]; }
157 
159  float SigmaEndTick() const { return fSigmaEndTicks[ClusterEnds_t::clEnd]; }
160 
162  float WireCoord(ClusterEnds_t side) const { return fEndWires[side]; }
163  // float WireCoord(unsigned int side) const { return fEndWires[side]; }
164 
166  float TickCoord(ClusterEnds_t side) const { return fEndTicks[side]; }
167  // float TickCoord(unsigned int side) const { return fEndTicks[side]; }
168 
170  float SigmaWireCoord(ClusterEnds_t side) const { return fSigmaEndWires[side]; }
171  // float SigmaWireCoord(unsigned int side) const { return fSigmaEndWires[side]; }
172 
174  float SigmaTickCoord(ClusterEnds_t side) const { return fSigmaEndTicks[side]; }
175  // float SigmaTickCoord(unsigned int side) const { return fSigmaEndTicks[side]; }
176 
177 
179  float StartCharge() const { return fEndCharges[ClusterEnds_t::clStart]; }
180 
182  float StartAngle() const { return fAngles[ClusterEnds_t::clStart]; }
183 
185  float StartOpeningAngle() const { return fOpeningAngles[ClusterEnds_t::clStart]; }
186 
188  float EndCharge() const { return fEndCharges[ClusterEnds_t::clEnd]; }
189 
191  float EndAngle() const { return fAngles[ClusterEnds_t::clEnd]; }
192 
194  float EndOpeningAngle() const { return fOpeningAngles[ClusterEnds_t::clEnd]; }
195 
197  float EdgeCharge(ClusterEnds_t side) const { return fEndCharges[side]; }
198  // float EdgeCharge(unsigned int side) const { return fEndCharges[side]; }
199 
201  float Angle(ClusterEnds_t side) const { return fAngles[side]; }
202  // float Angle(unsigned int side) const { return fAngles[side]; }
203 
205  float OpeningAngle(ClusterEnds_t side) const { return fOpeningAngles[side]; }
206  // float OpeningAngle(unsigned int side) const { return fOpeningAngles[side]; }
207 
208 
210  float Width() const { return fWidth; }
211 
213  geo::View_t View() const { return fView; }
214 
216  geo::PlaneID Plane() const { return fPlaneID; }
217 
219  bool hasPlane() const { return Plane().isValid; }
220 
221 
222  protected:
223 
225  float fEndWires[ClusterEnds_t::NEnds];
226 
228  float fSigmaEndWires[ClusterEnds_t::NEnds];
229 
231  float fEndTicks[ClusterEnds_t::NEnds];
232 
234  float fSigmaEndTicks[ClusterEnds_t::NEnds];
235 
237  float fEndCharges[ClusterEnds_t::NEnds];
238 
240  float fAngles[ClusterEnds_t::NEnds];
241 
243  float fOpeningAngles[ClusterEnds_t::NEnds];
244 
246  float fWidth;
247 
249 
251 
252  unsigned int n_clusters = 0;
253 
255  void AdoptEnd(recob::Cluster const& cluster, ClusterEnds_t iEnd);
256 
257  template <typename T>
258  static void top(T& var, T value) { if (value > var) var = value; }
259  template <typename T>
260  static void bot(T& var, T value) { if (value < var) var = value; }
261  }; // class ClusterMerger
262 
265  {
266  const ClusterEnds_t iDestEnd = iSrcEnd;
267  fEndWires[iDestEnd] = cluster.WireCoord(iSrcEnd);
268  fSigmaEndWires[iDestEnd] = cluster.SigmaWireCoord(iSrcEnd);
269  fEndTicks[iDestEnd] = cluster.TickCoord(iSrcEnd);
270  fSigmaEndTicks[iDestEnd] = cluster.SigmaTickCoord(iSrcEnd);
271  fEndCharges[iDestEnd] = cluster.EdgeCharge(iSrcEnd);
272  fAngles[iDestEnd] = cluster.Angle(iSrcEnd);
273  fOpeningAngles[iDestEnd] = cluster.OpeningAngle(iSrcEnd);
274  } // ClusterMerger::AdoptEnd()
275 
276  bool ClusterMerger::Add(recob::Cluster const& cluster) {
277  if (!cluster.isValid()) return false;
278 
279  if (n_clusters == 0) { // special case: we are still empty
280  AdoptEnd(cluster, ClusterEnds_t::clStart);
281  AdoptEnd(cluster, ClusterEnds_t::clEnd);
282  fWidth = cluster.Width();
283  fView = cluster.View();
284  fPlaneID = cluster.Plane();
285  ++n_clusters;
286  return true;
287  } // if empty
288 
289  if (cluster.View() != View()) return false;
290 
291  if (cluster.hasPlane() && hasPlane() && (cluster.Plane() != Plane()))
292  return false;
293 
294  // this code has been moved here from the old recon::Cluster::operator+
295  // of recob::Cluster v13.
296  if (cluster.StartWire() < StartWire()) { // adopt the new start
297  AdoptEnd(cluster, ClusterEnds_t::clStart);
298  }
299  if (cluster.EndWire() < EndWire()) { // adopt the new end
300  AdoptEnd(cluster, ClusterEnds_t::clEnd);
301  }
302 
303  top(fWidth, cluster.Width()); // extend width
304 
305  if (!hasPlane()) fPlaneID = cluster.Plane();
306 
307  return true;
308  } // ClusterMerger::Add(Cluster)
309 
310 
313  public:
314  // NOTE if you feel like copying this class, move it into its own header
315  // instead, and if you need it for a different hit or hit pointer, make it
316  // a template instead
318  using HitVector_t = std::vector<HitPtr_t>;
319 
320  ClusterAndHitMerger() = default;
321 
323  (recob::Cluster const& cluster, HitVector_t const& cluster_hits)
324  { Add(cluster, cluster_hits); }
325 
339  bool Add(
340  recob::Cluster const& cluster, HitVector_t const& cluster_hits,
341  bool prepend = false
342  );
343 
346 
348  HitVector_t const& Hits() const { return hits; }
349 
351  unsigned int NHits() const { return hits.size(); }
352 
354 
355  protected:
356 
358 
359  void AddHits(HitVector_t const& cluster_hits, bool prepend)
360  {
361  hits.insert(prepend? hits.begin(): hits.end(),
362  cluster_hits.begin(), cluster_hits.end());
363  } // AddHits()
364 
365  }; // class ClusterAndHitMerger
366 
368  recob::Cluster const& cluster, HitVector_t const& cluster_hits,
369  bool prepend /* = false */
370  ) {
371  if (!ClusterMerger::Add(cluster)) return false;
372 
373  AddHits(cluster_hits, prepend);
374  return true;
375  } // ClusterAndHitMerger::Add()
376 
377 
378  //-------------------------------------------------
380  : fClusterModuleLabel(pset.get<std::string>("ClusterModuleLabel"))
381  , fSlope (pset.get<double >("Slope"))
382  , fEndpointWindow (pset.get<double >("EndpointWindow"))
383  {
384  produces< std::vector<recob::Cluster> >();
385  produces< art::Assns<recob::Cluster, recob::Hit> >();
386  }
387 
388  //-------------------------------------------------
390  {
391  }
392 
393  //-------------------------------------------------
395  {
396  //this doesn't do anything now, but it might someday
397  }
398 
399  //------------------------------------------------------------------------------------//
401  {
402  // Get a Handle for the input Cluster object(s).
403  art::Handle< std::vector<recob::Cluster> > clusterVecHandle;
404  evt.getByLabel(fClusterModuleLabel,clusterVecHandle);
405 
406  constexpr size_t nViews = 3; // number of views we map
407 
408  //one vector for each view in the geometry (holds the index of the cluster)
409  std::array< std::vector<size_t>, nViews > ClsIndices;
410 
411  //vector with indicators for whether a cluster has been merged already
412  std::array< std::vector<int>, nViews > Cls_matches;
413 
414  // loop over the input Clusters
415  for(size_t i = 0; i < clusterVecHandle->size(); ++i){
416 
417  //get a art::Ptr to each Cluster
418  art::Ptr<recob::Cluster> cl(clusterVecHandle, i);
419 
420  size_t view = 0;
421  switch(cl->View()){
422  case geo::kU :
423  view = 0;
424  break;
425  case geo::kV :
426  view = 1;
427  break;
428  case geo::kZ :
429  view = 2;
430  break;
431  default :
432  continue; // ignore this cluster and process the next one
433  }// end switch on view
434 
435  Cls_matches[view].push_back(0);
436  ClsIndices[view].push_back(i);
437  }// end loop over input clusters
438 
439  std::unique_ptr<std::vector<recob::Cluster> > SuperClusters(new std::vector<recob::Cluster>);
440  std::unique_ptr< art::Assns<recob::Cluster, recob::Hit> > assn(new art::Assns<recob::Cluster, recob::Hit>);
441 
442  // prepare the algorithm to compute the cluster characteristics;
443  // we use the "standard" one here; configuration would happen here,
444  // but we are using the default configuration for that algorithm
446 
447  art::FindManyP<recob::Hit> fmh(clusterVecHandle, evt, fClusterModuleLabel);
448 
449  for(size_t i = 0; i < nViews; ++i){
450 
451  int clustersfound = 0; // how many merged clusters found in each plane
452  int clsnum1 = 0;
453 
454  for(size_t c = 0; c < ClsIndices[i].size(); ++c){
455  if(Cls_matches[i][clsnum1] == 1){
456  ++clsnum1;
457  continue;
458  }
459 
460  // make a new cluster to put into the SuperClusters collection
461  // because we want to be able to adjust it later;
462  // use the hits associated with the current cluster
463  recob::Cluster const& StartingCluster
464  = clusterVecHandle->at(ClsIndices[i][c]);
465  ClusterAndHitMerger cl1(StartingCluster, fmh.at(ClsIndices[i][c]));
466  const recob::Cluster::ID_t clusterID = StartingCluster.ID();
467 
468  Cls_matches[i][clsnum1] = 1;
469  ++clustersfound;
470 
471  int clsnum2 = 0;
472  for(size_t c2 = 0; c2 < ClsIndices[i].size(); ++c2){
473 
474  if(Cls_matches[i][clsnum2] == 1){
475  ++clsnum2;
476  continue;
477  }
478 
479  const recob::Cluster& cl2( clusterVecHandle->at(ClsIndices[i][c2]) );
480 
481 
482  // check that the slopes are the same
483  // added 13.5 ticks/wirelength in ArgoNeuT.
484  // \todo need to make this detector agnostic
485  // would be nice to have a LArProperties function that returns ticks/wire.
486  bool sameSlope = SlopeCompatibility(cl1.StartAngle(), cl2.EndAngle())
487  || SlopeCompatibility(cl1.EndAngle(), cl2.StartAngle());
488 
489  // check that the endpoints fall within a circular window of each other
490  // done in place of intercept matching
491  int sameEndpoint = EndpointCompatibility(
492  cl1.StartWire(), cl1.StartTick(),
493  cl1.EndWire(), cl1.EndTick(),
494  cl2.StartWire(), cl2.StartTick(),
495  cl2.EndWire(), cl2.EndTick()
496  );
497 
498  // if the slopes and end points are the same, combine the clusters
499  // note that after 1 combination cl1 is no longer what we started
500  // with
501  if(sameSlope && (sameEndpoint != 0)) {
502  // combine the hit collections too
503  // (find the hits associated with this second cluster);
504  // take into account order when merging hits from two clusters: doc-1776
505  // if sameEndpoint is 1, the new hits come first
506  cl1.Add(cl2, fmh.at(ClsIndices[i][c2]), sameEndpoint == 1);
507  Cls_matches[i][clsnum2] = 1;
508  }
509 
510  ++clsnum2;
511  }// end loop over second cluster iterator
512 
513  // now add the final version of cl1 to the collection of SuperClusters
514  // and create the association between the super cluster and the hits
515  ClusterParamAlgo.ImportHits(cl1.Hits());
516 
517  // create the recob::Cluster directly in the vector
518  SuperClusters->emplace_back(
519  cl1.StartWire(), // start_wire
520  cl1.SigmaStartWire(), // sigma_start_wire
521  cl1.StartTick(), // start_tick
522  cl1.SigmaStartTick(), // sigma_start_tick
523  cl1.StartCharge(), // start_charge
524  cl1.StartAngle(), // start_angle
525  cl1.StartOpeningAngle(), // start_opening
526  cl1.EndWire(), // end_wire
527  cl1.SigmaEndWire(), // sigma_end_wire
528  cl1.EndTick(), // end_time
529  cl1.SigmaEndTick(), // sigma_end_tick
530  cl1.EndCharge(), // end_charge
531  cl1.EndAngle(), // end_angle
532  cl1.EndOpeningAngle(), // end_opening
533  ClusterParamAlgo.Integral().value(), // integral
534  ClusterParamAlgo.IntegralStdDev().value(), // integral_stddev
535  ClusterParamAlgo.SummedADC().value(), // summedADC
536  ClusterParamAlgo.SummedADCStdDev().value(), // summedADC_stddev
537  ClusterParamAlgo.NHits(), // n_hits
538  ClusterParamAlgo.MultipleHitDensity(), // multiple_hit_density
539  cl1.Width(), // width
540  clusterID, // ID
541  cl1.View(), // view
542  cl1.Plane(), // planeID
543  recob::Cluster::Sentry // sentry
544  );
545 
546  util::CreateAssn(*this, evt, *(SuperClusters.get()), cl1.Hits(), *(assn.get()));
547  ++clsnum1;
548 
549  }// end loop over first cluster iterator
550  }// end loop over planes
551 
552  mf::LogVerbatim("Summary") << std::setfill('-') << std::setw(175) << "-" << std::setfill(' ');
553  mf::LogVerbatim("Summary") << "LineMerger Summary:";
554  for(size_t i = 0; i < SuperClusters->size(); ++i)
555  mf::LogVerbatim("Summary") << SuperClusters->at(i);
556 
557  evt.put(std::move(SuperClusters));
558  evt.put(std::move(assn));
559 
560  return;
561 
562  }
563 
564  //------------------------------------------------------------------------------------//
565  //checks the difference between angles of the two lines
566  bool LineMerger::SlopeCompatibility(double slope1, double slope2)
567  {
568  double sl1 = atan(slope1);
569  double sl2 = atan(slope2);
570 
571  //the units of fSlope are radians
572  bool comp = std::abs(sl1-sl2) < fSlope ? true : false;
573 
574  return comp;
575  }
576  //------------------------------------------------------------------------------------//
578  float sclstartwire, float sclstarttime,
579  float sclendwire, float sclendtime,
580  float cl2startwire, float cl2starttime,
581  float cl2endwire, float cl2endtime
582  ) {
583 
585  float distance = std::sqrt((pow(sclendwire-cl2startwire,2)*13.5) + pow(sclendtime-cl2starttime,2));
586 
587  //not sure if this line is necessary--spitz
588  float distance2 = std::sqrt((pow(sclstartwire-cl2endwire,2)*13.5) + pow(sclstarttime-cl2endtime,2));
589 
590 // bool comp = (distance < fEndpointWindow ||
591 // distance2 < fEndpointWindow) ? true : false;
592 
593  //determine which way the two clusters should be merged. TY
594  int comp = 0;
595  if (distance < fEndpointWindow)
596  comp = 1;
597  else if (distance2 < fEndpointWindow)
598  comp = -1;
599  return comp;
600  }
601 
602 
603 
604 } // end namespace
605 
606 
607 
608 
609 
610 namespace cluster{
611 
613 
614 } // end namespace
615 
float EndOpeningAngle() const
Returns the opening angle at the end of the cluster.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int EndpointCompatibility(float sclstartwire, float sclstarttime, float sclendwire, float sclendtime, float cl2startwire, float cl2starttime, float cl2endwire, float cl2endtime)
float EndWire() const
Returns the wire coordinate of the end of the cluster.
float SigmaStartWire() const
Returns the uncertainty on wire coordinate of the start of the cluster.
float StartAngle() const
Returns the starting angle of the cluster.
float SigmaWireCoord(ClusterEnds_t side) const
Returns the uncertainty on wire coordinate of one of the end sides of the cluster.
Definition: Cluster.h:427
float EdgeCharge(ClusterEnds_t side) const
Returns the charge on the first or last wire of the cluster.
float Angle(ClusterEnds_t side) const
Returns the angle at either end of the cluster.
Definition: Cluster.h:569
ClusterMerger(recob::Cluster const &cluster)
float SigmaTickCoord(ClusterEnds_t side) const
Returns the uncertainty on tick coordinate of one of the end sides of the cluster.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:77
float TickCoord(ClusterEnds_t side) const
Returns the tick coordinate of one of the end sides of the cluster.
Definition: Cluster.h:413
Declaration of signal hit object.
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
float EdgeCharge(ClusterEnds_t side) const
Returns the charge on the first or last wire of the cluster.
Definition: Cluster.h:544
float SigmaTickCoord(ClusterEnds_t side) const
Returns the uncertainty on tick coordinate of one of the end sides of the cluster.
Definition: Cluster.h:440
float StartWire() const
Returns the wire coordinate of the start of the cluster.
Definition: Cluster.h:286
STL namespace.
Planes which measure Z direction.
Definition: geo_types.h:79
Set of hits with a 2D structure.
Definition: Cluster.h:71
geo::PlaneID Plane() const
Returns the plane ID this cluster lies on.
Definition: Cluster.h:744
Cluster finding and building.
static void bot(T &var, T value)
Data referring to start and end of the cluster.
float fWidth
A measure of the cluster width, in homogenized units.
bool isValid() const
Returns if the cluster is valid (that is, if its ID is not invalid)
Definition: Cluster.h:753
float SigmaStartTick() const
Data referring to start and end of the cluster.
float StartWire() const
Returns the wire coordinate of the start of the cluster.
static const SentryArgument_t Sentry
An instance of the sentry object.
Definition: Cluster.h:182
float StartOpeningAngle() const
Returns the opening angle at the start of the cluster.
LineMerger(fhicl::ParameterSet const &pset)
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
bool Add(recob::Cluster const &cluster, HitVector_t const &cluster_hits, bool prepend=false)
Merges a single cluster into this object.
Planes which measure U.
Definition: geo_types.h:76
float TickCoord(ClusterEnds_t side) const
Returns the tick coordinate of one of the end sides of the cluster.
void hits()
Definition: readHits.C:15
TCanvas * c2
Definition: plot_hist.C:75
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
static void top(T &var, T value)
Data referring to start and end of the cluster.
std::string fClusterModuleLabel
Helper functions to create a cluster.
Wrapper for ClusterParamsAlgBase objects to accept diverse input.
void AdoptEnd(recob::Cluster const &cluster, ClusterEnds_t iEnd)
Imports all the member of the corresponding end.
float SigmaEndWire() const
Returns the uncertainty on wire coordinate of the end of the cluster.
float Width() const
A measure of the cluster width, in homogenized units.
Definition: Cluster.h:727
float SigmaEndTick() const
Returns the uncertainty on tick coordinate of the end of the cluster.
Wrapper for ClusterParamsAlgBase objects to accept arbitrary input.
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
float Angle(ClusterEnds_t side) const
Returns the angle at either end of the cluster.
Declaration of cluster object.
float WireCoord(ClusterEnds_t side) const
Returns the wire coordinate of one of the end sides of the cluster.
Definition: Cluster.h:386
Definition of data types for geometry description.
void produce(art::Event &evt)
bool hasPlane() const
Returns whether geometry plane is valid.
float SigmaWireCoord(ClusterEnds_t side) const
Returns the uncertainty on wire coordinate of one of the end sides of the cluster.
float StartTick() const
Returns the tick coordinate of the start of the cluster.
Class merging clusters: recomputes start and end position and hit list.
float Width() const
A measure of the cluster width, in homogenized units.
HitVector_t hits
hits in the cluster
HitVector_t const & Hits() const
Returns a constant reference to the current list of hits.
geo::View_t View() const
Returns the view for this cluster.
Definition: Cluster.h:741
std::string value(boost::any const &)
geo::View_t fView
View for this cluster.
float StartCharge() const
Returns the charge on the first wire of the cluster.
Utility object to perform functions of association.
float OpeningAngle(ClusterEnds_t side) const
Returns the opening angle at either end of the cluster.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
ID_t ID() const
Identifier of this cluster.
Definition: Cluster.h:738
void ImportHits(Iter begin, Iter end)
Calls SetHits() with the hits in the sequence.
bool SlopeCompatibility(double slope1, double slope2)
unsigned int NHits() const
Number of hits in the cluster.
bool hasPlane() const
Returns whether geometry plane is valid.
Definition: Cluster.h:749
geo::View_t View() const
Returns the view for this cluster.
Interface to class computing cluster parameters.
geo::PlaneID Plane() const
Returns the plane ID this cluster lies on.
std::vector< HitPtr_t > HitVector_t
vector of pointers to hits
recob::tracking::Plane Plane
Definition: TrackState.h:17
Class merging clusters: recomputes start and end position and hit list.
float OpeningAngle(ClusterEnds_t side) const
Returns the opening angle at either end of the cluster.
Definition: Cluster.h:584
float EndAngle() const
Returns the ending angle of the cluster.
recob::Cluster::ID_t ID_t
Type of cluster ID.
float WireCoord(ClusterEnds_t side) const
Returns the wire coordinate of one of the end sides of the cluster.
int ID_t
Type of cluster ID.
Definition: Cluster.h:74
void AddHits(HitVector_t const &cluster_hits, bool prepend)
geo::PlaneID fPlaneID
Location of the start of the cluster.
float EndCharge() const
Returns the charge on the last wire of the cluster.
float EndTick() const
Returns the tick coordinate of the end of the cluster.
bool Add(recob::Cluster const &cluster)
Merges a single cluster into this object.
float EndWire() const
Returns the wire coordinate of the end of the cluster.
Definition: Cluster.h:329