LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
CBAlgoCenterOfMassSmall.cxx
Go to the documentation of this file.
2 
3 #include "TString.h"
4 
5 namespace cmtool {
6 
7  //----------------------------------------
9  //----------------------------------------
10  {
11 
12  SetDebug(false);
14  SetMaxDistance(20.);
15  SetMaxCOMDistance(25.);
16  UseCOMInPoly(true);
17  UseCOMClose(true);
18  UseCOMNearClus(true);
19  }
20 
21  //---------------------------------------------------------------------------
22  bool CBAlgoCenterOfMassSmall::Bool(const ::cluster::ClusterParamsAlg& cluster1,
23  const ::cluster::ClusterParamsAlg& cluster2)
24  //---------------------------------------------------------------------------
25  {
26 
27  int Nhits1 = 0;
28  int Nhits2 = 0;
29 
30  //Both clusters should have less hits than some threshold
31  if ((cluster1.GetHitVector().size() > _maxHits) or (cluster2.GetHitVector().size() > _maxHits))
32  return false;
33 
34  //Define COM values on w & t
35  double COM_t_1 = 0;
36  double COM_w_1 = 0;
37  double Q_1 = 0;
38  double start_w_1;
39  double start_t_1;
40  double end_w_1;
41  double end_t_1;
42  Polygon2D poly1;
43  double COM_t_2 = 0;
44  double COM_w_2 = 0;
45  double Q_2 = 0;
46  double start_w_2;
47  double start_t_2;
48  double end_w_2;
49  double end_t_2;
50  Polygon2D poly2;
51 
52  //Get Hit vector for cluster 1
53  //std::vector<util::PxHit> hits1;
54  std::vector<util::PxHit> hits1;
55  hits1 = cluster1.GetHitVector();
56  Nhits1 = hits1.size();
57  poly1 = cluster1.GetParams().PolyObject;
58  start_w_1 = cluster1.GetParams().start_point.w;
59  start_t_1 = cluster1.GetParams().start_point.t;
60  end_w_1 = cluster1.GetParams().end_point.w;
61  end_t_1 = cluster1.GetParams().end_point.t;
62  //Get Hit vector for cluster 2
63  //std::vector<util::PxHit> hits2;
64  std::vector<util::PxHit> hits2;
65  hits2 = cluster2.GetHitVector();
66  Nhits2 = hits2.size();
67  poly2 = cluster2.GetParams().PolyObject;
68  start_w_2 = cluster2.GetParams().start_point.w;
69  start_t_2 = cluster2.GetParams().start_point.t;
70  end_w_2 = cluster2.GetParams().end_point.w;
71  end_t_2 = cluster2.GetParams().end_point.t;
72 
73  //Find COM for cluster 1
74  for (auto& hit : hits1) {
75  COM_t_1 += hit.t * hit.charge;
76  COM_w_1 += hit.w * hit.charge;
77  Q_1 += hit.charge;
78  }
79  COM_t_1 /= Q_1;
80  COM_w_1 /= Q_1;
81 
82  //Find COM for cluster 2
83  for (auto& hit : hits2) {
84  COM_t_2 += hit.t * hit.charge;
85  COM_w_2 += hit.w * hit.charge;
86  Q_2 += hit.charge;
87  }
88  COM_t_2 /= Q_2;
89  COM_w_2 /= Q_2;
90 
91  if (_debug) {
92  std::cout << "Cluster 1: " << std::endl;
93  std::cout << "N Hits: " << Nhits1 << std::endl;
94  std::cout << "COM: (w,t) -> (" << COM_w_1 << ", " << COM_t_1 << ")" << std::endl;
95  std::cout << "Cluster 2: " << std::endl;
96  std::cout << "N Hits: " << Nhits2 << std::endl;
97  std::cout << "COM: (w,t) -> (" << COM_w_2 << ", " << COM_t_2 << ")" << std::endl;
98  std::cout << std::endl;
99  }
100 
101  //Get COM
102  std::pair<float, float> COM_1;
103  COM_1 = std::make_pair(COM_w_1, COM_t_1);
104  std::pair<float, float> COM_2;
105  COM_2 = std::make_pair(COM_w_2, COM_t_2);
106 
107  //look for polygon overlap
108  if (((poly2.PointInside(COM_1)) and _COMinPolyAlg) or
109  ((poly1.PointInside(COM_2)) and _COMinPolyAlg)) {
110  if (_verbose) { std::cout << "Polygon Overlap -> Merge!" << std::endl << std::endl; }
111  return true;
112  }
113 
114  //look for COM of 1 close to COM of 2
115  double distCOMs =
116  (COM_w_1 - COM_w_2) * (COM_w_1 - COM_w_2) + (COM_t_1 - COM_t_2) * (COM_t_1 - COM_t_2);
117  if (_COMsClose and (distCOMs < _MaxCOMDistSquared)) {
118  if (_verbose) { std::cout << "COMs close to each other -> Merge!" << std::endl << std::endl; }
119  return true;
120  }
121 
122  //look for COM close to start-end of other cluster
123  if (_COMNearClus and
124  ((ShortestDistanceSquared(COM_w_1, COM_t_1, start_w_2, start_t_2, end_w_2, end_t_2) <
125  _MaxDist) or
126  (ShortestDistanceSquared(COM_w_2, COM_t_2, start_w_1, start_t_1, end_w_1, end_t_1) <
127  _MaxDist))) {
128  if (_verbose) { std::cout << "COM close to start-end -> Merge!" << std::endl; }
129  return true;
130  }
131 
132  return false;
133  }
134 
135  //-----------------------
137  //-----------------------
138  {}
139 
141  double point_y,
142  double start_x,
143  double start_y,
144  double end_x,
145  double end_y) const
146  {
147 
148  //This code finds the shortest distance between a point and a line segment.
149  //code based off sample from
150  //http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
151  //note to self: rewrite this with TVector2 and compare time differences...
152  //TVector2 code might be more understandable
153 
154  double distance_squared = -1;
155 
156  // Line segment: from ("V") = (start_x, start_y) to ("W")=(end_x, end_y)
157  double length_squared = pow((end_x - start_x), 2) + pow((end_y - start_y), 2);
158 
159  // Treat the case start & end point overlaps
160  if (length_squared < 0.1) {
161  if (_verbose) {
162  std::cout << std::endl;
163  std::cout << Form(" Provided very short line segment: (%g,%g) => (%g,%g)",
164  start_x,
165  start_y,
166  end_x,
167  end_y)
168  << std::endl;
169  std::cout << " Likely this means one of two clusters have start & end point identical."
170  << std::endl;
171  std::cout << " Check the cluster output!" << std::endl;
172  std::cout << std::endl;
173  std::cout << Form(" At this time, the algorithm uses a point (%g,%g)", start_x, start_y)
174  << std::endl;
175  std::cout << " to represent this cluster's location." << std::endl;
176  std::cout << std::endl;
177  }
178 
179  return (pow((point_x - start_x), 2) + pow((point_y - start_y), 2));
180  }
181 
182  //Find shortest distance between point ("P")=(point_x,point_y) to this line segment
183  double t = ((point_x - start_x) * (end_x - start_x) + (point_y - start_y) * (end_y - start_y)) /
184  length_squared;
185 
186  if (t < 0.0)
187  distance_squared = pow((point_x - start_x), 2) + pow((point_y - start_y), 2);
188 
189  else if (t > 1.0)
190  distance_squared = pow((point_x - end_x), 2) + pow(point_y - end_y, 2);
191 
192  else
193  distance_squared = pow((point_x - (start_x + t * (end_x - start_x))), 2) +
194  pow((point_y - (start_y + t * (end_y - start_y))), 2);
195 
196  return distance_squared;
197 
198  } //end ShortestDistanceSquared function
199 
200 }
bool _COMinPolyAlg
How four out - as percent of cluster length - cone will extend from start point.
virtual bool Bool(const ::cluster::ClusterParamsAlg &cluster1, const ::cluster::ClusterParamsAlg &cluster2)
void SetMaxCOMDistance(double d)
Function to set Max Distance between COMs.
virtual void Report()
Function to report what&#39;s going on per merging iteration.
double ShortestDistanceSquared(double point_x, double point_y, double start_x, double start_y, double end_x, double end_y) const
void UseCOMClose(bool on)
Use COM in Poly algo to decide merging.
CBAlgoCenterOfMassSmall()
Default constructor.
Detector simulation of raw signals on wires.
Class def header for a class CBAlgoCenterOfMassSmall.
void SetMaxDistance(double d)
Function to set Max Distance for COM to be from start-end.
void UseCOMInPoly(bool on)
Use COM in Poly algo to decide merging.
void SetDebug(bool on)
Function to set Debug mode of output.
void UseCOMNearClus(bool on)
Use COM in Poly algo to decide merging.
bool PointInside(const std::pair< float, float > &point) const
Definition: Polygon2D.cxx:271
void SetMaxHitsSmallClus(size_t n)
Function to set Max hits for small clsuters.
bool _verbose
Boolean to choose verbose mode. Turned on if CMergeManager/CMatchManager&#39;s verbosity level is >= kPer...
Definition: CMAlgoBase.h:82