LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
CFAlgoVolumeOverlap.cxx
Go to the documentation of this file.
1 #ifndef RECOTOOL_CFALGOVOLUMEOVERLAP_CXX
2 #define RECOTOOL_CFALGOVOLUMEOVERLAP_CXX
3 
4 #include "CFAlgoVolumeOverlap.h"
5 #include <algorithm>
6 
7 namespace cmtool {
8 
9  //-------------------------------------------------------
11  //-------------------------------------------------------
12  {
14  _w2cm = geou.WireToCm();
15  _t2cm = geou.TimeToCm();
16  SetVerbose(false);
17  SetDebug(false);
18  SetUseAllPlanes(false); // Any plane combination OK
19  }
20 
21  //-----------------------------
23  //-----------------------------
24  {
25  }
26 
27  //----------------------------------------------------------------------------------------------
28  float CFAlgoVolumeOverlap::Float(const std::vector<const cluster::ClusterParamsAlg*> &clusters)
29  //----------------------------------------------------------------------------------------------
30  {
31 
33 
34  // Code-block by Kazu starts
35  // This ensures the algorithm works only if # clusters is > 2 (and not =2)
36  // You may take out this block if you want to allow matching using clusters from only 2 planes.
37  if (_UseAllPlanes) { if(clusters.size()==2) return -1; }
38  // Code-block by Kazu ends
39 
40  //This algorithm now works for 3 planes: find 3Dstart point from first 2 planes and find
41  //How well that agrees with 3rd plane's start point location.
42 
43  //So first, make sure clusters vector has more than 1 element.
44  //If not, return -1. Algorithm does not make sense
45  if ( clusters.size() == 1 )
46  return -1;
47 
48  if (_verbose) { std::cout << "Number of clusters taken into account: " << clusters.size() << std::endl; }
49 
50  //Nomenclature:
51  //Planes: U == 0; V == 1; Y == 2.
52 
53  //Get hits for all 3 clusters
54  std::vector<std::vector<util::PxHit> > Hits(3, std::vector<util::PxHit>());
55 
56  for (size_t c=0; c < clusters.size(); c++)
57  Hits.at( clusters.at(c)->Plane() ) = clusters.at(c)->GetHitVector();
58 
59  //std::vector<util::PxHit> hits0 = clusters.at(0)->GetHitVector();
60  //std::vector<util::PxHit> hits1 = clusters.at(1)->GetHitVector();
61  //std::vector<util::PxHit> hits2 = clusters.at(2)->GetHitVector();
62 
63  //Wire Range Vector. Entries 0,1,2 correspond to planes
64  std::vector<int> StartWires;
65  std::vector<int> EndWires;
66  std::vector<float> StartTimes;
67  std::vector<float> EndTimes;
68  //loop over number of planes and pre-fill StartWires and EndWires
69  for (int pl=0; pl < 3; pl++){
70  StartWires.push_back(9999);
71  EndWires.push_back(0);
72  StartTimes.push_back(9999);
73  EndTimes.push_back(0);
74  }
75 
76  for (size_t h=0; h < Hits.size(); h++){
77  for ( auto& hit: Hits.at(h) ){
78  if ( Hits.at(h).size() == 0 ){
79  std::cout << "Need to insert fake hit ranges...";
80  }
81  else{
82  if ( int(hit.w / _w2cm) < StartWires.at(h) ) { StartWires.at(h) = int(hit.w / _w2cm); }
83  if ( int(hit.w / _w2cm) > EndWires.at(h) ) { EndWires.at(h) = int(hit.w / _w2cm); }
84  if ( hit.t < StartTimes.at(h) ) { StartTimes.at(h) = hit.t; }
85  if ( hit.t > EndTimes.at(h) ) { EndTimes.at(h) = hit.t; }
86  }
87  }//for all hits in range
88  }//for all hit-lists (i.e. for all clusters)
89 
90  //if one of the plane's wire-range is still [9999, 0] then replace it
91  //with min/max wire number from that plane
92  //similarly for time-range
93  //This allows for easy 2-Plane matching: if we are ignoring one plane
94  //completely by giving the wire-range for the whole plane the intersection
95  //will effectively be the intersection of the other two planes
96  for (size_t h=0; h < Hits.size(); h++){
97  if ( StartWires.at(h) == 9999 ) { StartWires.at(h) = 1; }
98  if ( EndWires.at(h) == 0 ) { EndWires.at(h) = geo->Nwires(h)-1; }
99  if ( StartTimes.at(h) == 9999 ) { StartTimes.at(h) = 0; }
100  if ( EndTimes.at(h) == 0 ) { EndTimes.at(h) = 9999; }
101  }
102 
103 
104  //Find overlap in time between three planes
105  if ( (StartTimes.at(1) > EndTimes.at(0)) or (StartTimes.at(1) > EndTimes.at(2)) or
106  (StartTimes.at(2) > EndTimes.at(0)) or (StartTimes.at(2) > EndTimes.at(1)) or
107  (StartTimes.at(0) > EndTimes.at(1)) or (StartTimes.at(0) > EndTimes.at(2)) ){
108  if (_verbose) { std::cout << "No Time-Overlap!" << std::endl << std::endl; }
109  return -1;
110  }
111  //do two planes at a time...start with U and V
112  float Tmin=9999, Tmax=0;
113  ( StartTimes.at(1) > StartTimes.at(0) ) ? (Tmin = StartTimes.at(1)) : (Tmin = StartTimes.at(0));
114  if (StartTimes.at(2) > Tmin) { Tmin = StartTimes.at(2); }
115  ( EndTimes.at(1) < EndTimes.at(0) ) ? (Tmax = EndTimes.at(1)) : (Tmax = EndTimes.at(0));
116  if (EndTimes.at(2) < Tmax) { Tmax = EndTimes.at(2); }
117  float Trange = Tmax-Tmin;
118 
119  //Now get start & end points of all these wires
120  Double_t xyzStart0WireStart[3] = {0., 0., 0.}; //xyz array info of start point for smallest wire number on plane 0
121  Double_t xyzStart0WireEnd[3] = {0., 0., 0.};
122  Double_t xyzEnd0WireStart[3] = {0., 0., 0.};
123  Double_t xyzEnd0WireEnd[3] = {0., 0., 0.};
124  Double_t xyzStart1WireStart[3] = {0., 0., 0.}; //xyz array info of start point for smallest wire number on plane 1
125  Double_t xyzStart1WireEnd[3] = {0., 0., 0.};
126  Double_t xyzEnd1WireStart[3] = {0., 0., 0.};
127  Double_t xyzEnd1WireEnd[3] = {0., 0., 0.};
128  Double_t xyzStart2WireStart[3] = {0., 0., 0.}; //xyz array info of start point for smallest wire number on plane 2
129  Double_t xyzStart2WireEnd[3] = {0., 0., 0.};
130  Double_t xyzEnd2WireStart[3] = {0., 0., 0.};
131  Double_t xyzEnd2WireEnd[3] = {0., 0., 0.};
132 
133  if (_debug) {
134  std::cout << "Wire Ranges:" << std::endl;
135  std::cout << "U-Plane: [ " << StartWires.at(0) << ", " << EndWires.at(0) << "]" << std::endl;
136  std::cout << "V-Plane: [ " << StartWires.at(1) << ", " << EndWires.at(1) << "]" << std::endl;
137  std::cout << "Y-Plane: [ " << StartWires.at(2) << ", " << EndWires.at(2) << "]" << std::endl;
138  std::cout << std::endl;
139  }
140 
141  /*
142  geo->WireEndPoints(0, StartWires.at(0), xyzStart0WireStart, xyzStart0WireEnd);
143  geo->WireEndPoints(0, EndWires.at(0), xyzEnd0WireStart, xyzEnd0WireEnd);
144  geo->WireEndPoints(1, StartWires.at(1), xyzStart1WireStart, xyzStart1WireEnd);
145  geo->WireEndPoints(1, EndWires.at(1), xyzEnd1WireStart, xyzEnd1WireEnd);
146  geo->WireEndPoints(2, StartWires.at(2), xyzStart2WireStart, xyzStart2WireEnd);
147  geo->WireEndPoints(2, EndWires.at(2), xyzEnd2WireStart, xyzEnd2WireEnd);
148  */
149  geo->WireEndPoints(0, 0, 0, StartWires.at(0), xyzStart0WireStart, xyzStart0WireEnd);
150  geo->WireEndPoints(0, 0, 0, EndWires.at(0), xyzEnd0WireStart, xyzEnd0WireEnd);
151  geo->WireEndPoints(0, 0, 1, StartWires.at(1), xyzStart1WireStart, xyzStart1WireEnd);
152  geo->WireEndPoints(0, 0, 1, EndWires.at(1), xyzEnd1WireStart, xyzEnd1WireEnd);
153  geo->WireEndPoints(0, 0, 2, StartWires.at(2), xyzStart2WireStart, xyzStart2WireEnd);
154  geo->WireEndPoints(0, 0, 2, EndWires.at(2), xyzEnd2WireStart, xyzEnd2WireEnd);
155 
156  //check that z-positions for plane2 are the same...if not error!
157  //if ( xyzStart2WireStart[2] != xyzStart2WireEnd[2] ) { std::cout << "Y-wire does not have same Z start and end..." << std::endl; }
158  double zMin = xyzStart2WireStart[2];
159  //if ( xyzEnd2WireStart[2] != xyzEnd2WireEnd[2] ) { std::cout << "Y-wire does not have same Z start and end..." << std::endl; }
160  double zMax = xyzEnd2WireStart[2];
161 
162  //Plane U == Plane 0
163  //Plane V == Plane 1
164  //Plane Y == Plane 2
165 
166  //Each line can be described by function y = s*z + b (x,y,z coordinates same as uBooNE coord.)
167  //Slopes known: Pl0 is +60 clockwise from vertical. Pl1 is -60, counterclockwise from vertical. Looking at TPC with beam from left
168  double slopeU = tan(30*3.14/180.);
169  double slopeV = tan(-30*3.14/180.);
170 
171  //Find intercepts:
172  double bUup = xyzStart0WireStart[1] - xyzStart0WireStart[2] * slopeU;
173  double bUdn = xyzEnd0WireStart[1] - xyzEnd0WireStart[2] * slopeU;
174  double bVdn = xyzStart1WireStart[1] - xyzStart1WireStart[2] * slopeV;
175  double bVup = xyzEnd1WireStart[1] - xyzEnd1WireStart[2] * slopeV;
176  //make sure we know which line is above which
177  if ( bUup < bUdn ) { std::cout << "Uup and Udn are mixed up!" << std::endl; }
178  if ( bVdn > bVup ) { std::cout << "Vup and Vdn are mixed up!" << std::endl; }
179  //Pl2 lines are vertical...slope is infinite and no intercept.
180 
181  //Find intercepts of U wire-ranges with Y plane (easy since vertical)
182  //For now assume wire-ranges go to infinity, worry about TPC constraints later
183 
184  //Plug in Y-plane zMin and zMax coordinates into equations for U/V wire lines
185  double VdnZmin = slopeV * zMin + bVdn;
186  double VdnZmax = slopeV * zMax + bVdn;
187  double VupZmin = slopeV * zMin + bVup;
188  double VupZmax = slopeV * zMax + bVup;
189  double UdnZmin = slopeU * zMin + bUdn;
190  double UdnZmax = slopeU * zMax + bUdn;
191  double UupZmin = slopeU * zMin + bUup;
192  double UupZmax = slopeU * zMax + bUup;
193 
194  if (_debug){
195  std::cout << "Y-Plane and U-Plane points [Z,Y]:" << std::endl;
196  std::cout << "\t\t[ " << zMin << ", " << UdnZmin << "]" << std::endl;
197  std::cout << "\t\t[ " << zMin << ", " << UupZmin << "]" << std::endl;
198  std::cout << "\t\t[ " << zMax << ", " << UupZmax << "]" << std::endl;
199  std::cout << "\t\t[ " << zMax << ", " << UdnZmax << "]" << std::endl;
200  std::cout << "Y-Plane and V-Plane points [Z,Y]:" << std::endl;
201  std::cout << "\t\t[ " << zMin << ", " << VdnZmin << "]" << std::endl;
202  std::cout << "\t\t[ " << zMin << ", " << VupZmin << "]" << std::endl;
203  std::cout << "\t\t[ " << zMax << ", " << VupZmax << "]" << std::endl;
204  std::cout << "\t\t[ " << zMax << ", " << VdnZmax << "]" << std::endl;
205  }
206  //We now have Two polygons:
207  //One is the intersection of Y-Plane wires with U-Plane wires
208  //The other the intersection of planes Y and V.
209  //The intersection points of these two polygons is the
210  //overall intersection Area of the 3 clusters on the Y-Z plane.
211 
212  //Go through all segment intersections. If one is found add to
213  //list of points.
214  //Create a list of points for polygon
215  std::vector< std::pair<float,float> > WireIntersection;
216  double zInt; // temporary holder for z-intersection point of oblique sides
217  //Check: Vup and Uup, Vup and Uright, Vup and Uleft, Vup and Udn.
218  //Intersection between Vup and Uup: if within zMin, zMax then ok!
219  zInt = (bUup-bVup)/(slopeV-slopeU);
220  if ( (zInt > zMin) and (zInt < zMax) )
221  WireIntersection.push_back( std::make_pair( zInt, slopeV*zInt+bVup ) );
222  //Intersection between Vup and Uright:
223  if ( (VupZmax < UupZmax) and (VupZmax > UdnZmax) )
224  WireIntersection.push_back( std::make_pair( zMax, VupZmax ) );
225  //Intersection between Vup and Uleft:
226  if ( (VupZmin < UupZmin) and ( VupZmin > UdnZmin) )
227  WireIntersection.push_back( std::make_pair( zMin, VupZmin ) );
228  //Intersection between Vup and Udn:
229  zInt = (bUdn-bVup)/(slopeV-slopeU);
230  if ( (zInt > zMin) and (zInt < zMax) )
231  WireIntersection.push_back( std::make_pair( zInt, slopeV*zInt+bVup ) );
232 
233  //Check: Vdn and Uup, Uright, Uleft, Udn:
234  //Intersection between Vdn and Uup:
235  zInt = (bUup-bVdn)/(slopeV-slopeU);
236  if ( (zInt > zMin) and (zInt < zMax) )
237  WireIntersection.push_back( std::make_pair( zInt, slopeV*zInt+bVdn ) );
238  //Intersection between Vdn and Uright:
239  if ( (VdnZmax < UupZmax) and (VdnZmax > UdnZmax) )
240  WireIntersection.push_back( std::make_pair( zMax, VdnZmax ) );
241  //Intersection between Vdn and Uleft:
242  if ( (VdnZmin < UupZmin) and ( VdnZmin > UdnZmin) )
243  WireIntersection.push_back( std::make_pair( zMin, VdnZmin ) );
244  //Intersection between Vdn and Udn:
245  zInt = (bUdn-bVdn)/(slopeV-slopeU);
246  if ( (zInt > zMin) and (zInt < zMax) )
247  WireIntersection.push_back( std::make_pair( zInt, slopeV*zInt+bVdn ) );
248 
249  //Check: Vright and Uup, Udn:
250  //Intersection between Vright and Uup:
251  if ( (UupZmax < VupZmax) and ( UupZmax > VdnZmax) )
252  WireIntersection.push_back( std::make_pair( zMax, UupZmax ) );
253  //Intersection between Vright and Udn:
254  if ( (UdnZmax < VupZmax) and ( UdnZmax > VdnZmax) )
255  WireIntersection.push_back( std::make_pair( zMax, UdnZmax ) );
256 
257  //Check Vleft and Uup, Udn:
258  //Intersection between Vleft and Uup:
259  if ( (UupZmin < VupZmin) and ( UupZmin > VdnZmin) )
260  WireIntersection.push_back( std::make_pair( zMin, UupZmin ) );
261  //Intersection between Vleft and Udn:
262  if ( (UdnZmin < VupZmin) and ( UdnZmin > VdnZmin) )
263  WireIntersection.push_back( std::make_pair( zMin, UdnZmin ) );
264 
265  //If length is 0 then no intersection...return -1
266  if ( WireIntersection.size() == 0 ){
267  if (_verbose) { std::cout << "No intersection..." << std::endl << std::endl; }
268  return -1;
269  }
270 
271  //Now our polygon is complete...
272  //need to disentangle in case points added in incorrect order
273  //then calculate area
274  Polygon2D WirePolygon(WireIntersection);
275  //Variable to hold final output Area
276  double PolyArea = -1;
277  //Check order
278  WirePolygon.UntanglePolygon();
279 
280  //Create a Polygon for the Y-Z TPC Plane
281  std::vector< std::pair<float,float> > TPCCorners;
282  TPCCorners.push_back( std::make_pair(0., -geo->DetHalfHeight()) );
283  TPCCorners.push_back( std::make_pair(geo->DetLength(), -geo->DetHalfHeight()) );
284  TPCCorners.push_back( std::make_pair(geo->DetLength(), geo->DetHalfHeight()) );
285  TPCCorners.push_back( std::make_pair(0., geo->DetHalfHeight()) );
286  Polygon2D TPCPolygon(TPCCorners);
287  if (TPCPolygon.Contained(WirePolygon) ){
288  if (_verbose) {
289  std::cout << "Wire Overlap contained in TPC" << std::endl;
290  std::cout << "Intersection Polygon Coordinates [Z,Y]: " << std::endl;
291  for (unsigned int s=0; s < WirePolygon.Size(); s++)
292  std::cout << "\t\t[ " << WirePolygon.Point(s).first << ", " << WirePolygon.Point(s).second << "]" << std::endl;
293  std::cout << std::endl;
294  }
295  PolyArea = WirePolygon.Area();
296  }
297  else {
298  if (_verbose) {
299  std::cout << "Wire overlap not fully contained in TPC" << std::endl;
300  std::cout << "Intersection Polygon Coordinates [Z,Y]: " << std::endl;
301  for (unsigned int s=0; s < WirePolygon.Size(); s++)
302  std::cout << "\t\t[ " << WirePolygon.Point(s).first << ", " << WirePolygon.Point(s).second << "]" << std::endl;
303  std::cout << std::endl;
304  }
305  //product polygon should be the intersection of WirePolygon and TPCPolygon
306  Polygon2D IntersectionPolygon(TPCPolygon, WirePolygon);
307  PolyArea = IntersectionPolygon.Area();
308  }
309 
310  //return polygon area -> larger = better!
311  if (_verbose) { std::cout << "Intersection area: " << PolyArea << std::endl << std::endl; }
312  return Trange*PolyArea;
313  }
314 
315  //------------------------------
317  //------------------------------
318  {
319 
320  }
321 
322 }
323 #endif
CFAlgoVolumeOverlap()
Default constructor.
Float_t s
Definition: plot.C:23
float Area() const
Definition: Polygon2D.cxx:96
virtual void Reset()
Function to reset the algorithm instance, called together with manager&#39;s Reset()
virtual float Float(const std::vector< const cluster::ClusterParamsAlg * > &clusters)
bool Contained(const Polygon2D &poly2) const
Definition: Polygon2D.cxx:271
Double_t TimeToCm() const
const std::pair< float, float > & Point(unsigned int p) const
Definition: Polygon2D.cxx:135
Double_t WireToCm() const
unsigned int Size() const
Create Intersection Polygon.
Definition: Polygon2D.h:47
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.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
Detector simulation of raw signals on wires.
Class def header for a class CFAlgoVolumeOverlap.
art::PtrVector< recob::Hit > Hits
void SetDebug(bool on)
Function to set debug output.
void SetUseAllPlanes(bool on)
Function to set if _UseAllPlanes is on/off.
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
Namespace collecting geometry-related classes utilities.
void SetVerbose(bool on)
Function to set verbose output.
void UntanglePolygon()
check if poly2 is inside poly1
Definition: Polygon2D.cxx:286