All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeoObjectSorterSBND.cxx
Go to the documentation of this file.
1 /**
2  * @file GeoObjectSorterSBND.cxx
3  * @brief Algorithm class for sorting standard geo::XXXGeo objects for SBND.
4  * @date April 6, 2017
5  * @author petrillo@fnal.gov
6  */
7 
9 
10 // LArSoft libraries
17 
18 // framework libraries
19 #include "fhiclcpp/ParameterSet.h"
20 #include "cetlib_except/exception.h"
21 
22 // framework libraries
23 #include "cmath" // std::abs()
24 
25 
26 //----------------------------------------------------------------------------
27 //--- local helper functions
28 //---
29 static const double tol = 1e-4; /// Comparison tolerance, in centimeters
30 
31 
32 /// Returns whether the two values are equal (including some tolerance).
33 inline bool equal(double a, double b)
34  { return std::abs(a - b) <= tol; }
35 
36 
37 //----------------------------------------------------------------------------
38 bool CryostatSorter(geo::CryostatGeo const& c1, geo::CryostatGeo const& c2) {
39  //
40  // sort order for cryostats: by x
41  // (not that we have that many in SBND...)
42  //
43  return (c1.CenterX()) < (c2.CenterX());
44 
45 } // CryostatSorter()
46 
47 //----------------------------------------------------------------------------
48 static bool OpDetsSorter(geo::OpDetGeo const& t1, geo::OpDetGeo const& t2)
49 {
50  double xyz1[3] = {0.}, xyz2[3] = {0.};
51  double local[3] = {0.};
52  t1.LocalToWorld(local, xyz1);
53  t2.LocalToWorld(local, xyz2);
54 
55  if(xyz1[2] != xyz2[2])
56  return xyz1[2] < xyz2[2];
57  else if(xyz1[1] != xyz2[1])
58  return xyz1[1] < xyz2[1];
59  else
60  return xyz1[0] < xyz2[0];
61 } // OpDetsSorter
62 
63 //----------------------------------------------------------------------------
64 bool TPCSorter(geo::TPCGeo const& t1, geo::TPCGeo const& t2) {
65  //
66  // Define sort order for TPCs (in SBND case, by x).
67  //
68 
69  // The goal is to number TPCs first in the x direction so that,
70  // in the case of APA configuration, TPCs 2c and 2c+1 make up APA c.
71  // then numbering will go in y then in z direction.
72 
73  // First sort all TPCs belonging to different "z groups"
74  if (!equal(t1.CenterZ(), t2.CenterZ()))
75  return t1.CenterZ() < t2.CenterZ();
76 
77  // Within the same-z groups, sort TPCs belonging to different "y groups"
78  if (!equal(t1.CenterY(), t2.CenterY()))
79  return t1.CenterY() < t2.CenterY();
80 
81  // Within the same z and y groups, sort TPCs belonging to different
82  // "x groups";
83  // if the x is also the same, then t1 and t2 are the same TPC and strict
84  // ordering requires us to return false.
85  return t1.CenterX() < t2.CenterX();
86 
87 } // TPCSorter()
88 
89 
90 //----------------------------------------------------------------------------
91 // Define sort order for planes in APA configuration
92 // same as standard, but implemented differently
93 bool PlaneSorter(geo::PlaneGeo const& p1, geo::PlaneGeo const& p2) {
94 
95  /*
96  * Sort the wire planes so that the first faces the center of the TPC.
97  *
98  * This might be moved to geo::TPCGeo, which has all the information to
99  * enforce such a policy.
100  * In fact, we don't have as many here.
101  *
102  * We rely on a trick, that assumes the cathode to be located at x = 0,
103  * and we sort after |x| of the wire planes.
104  *
105  */
106  decltype(auto) p1c = p1.GetBoxCenter();
107  decltype(auto) p2c = p2.GetBoxCenter();
108 
109  /*
110  * #2 #1 #0 cathode #0 #1 #2
111  * | | | | | | |
112  * | | | | | | |
113  * | | | | | | |
114  * | | | | | | |
115  *
116  */
117  return std::abs(p1c.X()) < std::abs(p2c.X());
118 
119 } // PlaneSorter()
120 
121 
122 //----------------------------------------------------------------------------
123 bool WireSorter(geo::WireGeo const& w1, geo::WireGeo const& w2) {
124 
125  /*
126  * Wire comparison algorithm: compare wire centers:
127  *
128  * 1. if they have different z, sort by increasing z
129  * 2. if they have different y, sort by y:
130  * 1. increasing y if thetaZ is larger than 0
131  * 2. decreasing y if thetaZ is smaller than 0
132  * 3. if they have different x, sort by increasing x
133  * 4. otherwise, they are the same wire: return false
134  *
135  * This is strict weak ordering, as required by std::sort().
136  *
137  * The definition of "different" is that the difference is
138  * larger than the chosen tolerance.
139  *
140  * The wire plane dimensions are roughly 5 x 4 meters.
141  * The angle from z axis is +/- pi/6 for the inclined wires.
142  * The same angle for the diagonal of the plane is roughly pi/5.
143  * Therefore, the TPC is so "narrow" that there are wires connected to both
144  * sides, whose z is the same:
145  * ,------,-------,-----. ,--------------------.
146  * | ,.-' ,.-' ,.| uD |., |
147  * vA |-' ,.-' ,.-' | | `-., |
148  * | ,.-' ,.-' ,.| uC |., '-., | y
149  * vB |-' ,.-' ,.-' | | '-., '-., | ^
150  * | ,.-' ,.-' | uB |., '-., '-., | |
151  * vC |-' ,.-' | | '-., '-., '-| |
152  * | ,.-' | uA |., '-., '-., | ---+----> z
153  * vD |-' | | '-., '-., '-| |
154  * `--------------------' `------^-------^-----'
155  *
156  * This cartoon shows two views on the same APA, facing the same drift
157  * volume.
158  * We ask for wires to be sorted by increasing z coordinate.
159  * In the left view (V) the order should be vA, vB, vC, vD, that is left to
160  * right. That is also top to bottom.
161  * In the right view (U) the order should be uA, uB, uC, uD, that is left to
162  * right. In this case that is instead bottom to top.
163  * Wires can inform us of their start, end and middle. Start and end might
164  * be arbitrarily swapped and are not a reliable starting point. In the
165  * order we seek, the middle point ("center") monotonically increases with
166  * z, but because the plane is "narrow", some wires can cross it completely
167  * (vC and vD). In that case, the z coordinate of the center will be the
168  * same and it's not resolving the ambiguity. The y coordinate, on the other
169  * end, is always decreasing, and it may be relied upon for all wires.
170  * On the other view, the situation is similar, with the ambiguity on wires
171  * uC and uD resolved by y coordinate, but in this case the condition is for
172  * increasing y coordinate.
173  * The algorithm needs to figure out which is the right y direction from
174  * just the two wires being compared. The observation is that wires with
175  * angle larger than 0 with z are in planes with the leftmost disposition
176  * and need a decreasing y coordinate, while the others need an increasing
177  * y coordinate.
178  *
179  * In the case of a "short" TPC, the role of z and y would be swapped.
180  *
181  * This is stubbornly pretending there is no discontinuity in the wire plane
182  * (that is, it is ignoring the junction half way along z.
183  */
184  decltype(auto) c1 = w1.GetCenter(), c2 = w2.GetCenter();
185 
186  //
187  // we do z first, which easily resolves the vertical wires:
188  //
189  if (!equal(c1.Z(), c2.Z())) return c1.Z() < c2.Z();
190 
191  //
192  // here, z is the same: sort by y
193  //
194  if (!equal(c1.Y(), c2.Y())) {
195  // need to figure out the angle of the wires (we assume both share the same)
196  decltype(auto) e1 = w1.GetEnd();
197 
198  //
199  // We work with end - center (e1 - c1):
200  // * if its delta y and delta z have the same sign, thetaZ is positive and
201  // we need a decreasing y
202  // * otherwise, we want increasing y
203  //
204  bool const decreasingY = ((e1.Y() - c1.Y()) > 0) == ((e1.Z() - c1.Z()) > 0);
205  if (decreasingY) return c1.Y() > c2.Y(); // decreasing => first upper wires
206  else return c1.Y() < c2.Y(); // increasing => first lower wires
207  } // if same y
208 
209  //
210  // also y is the same... go check x
211  //
212  if (!equal(c1.X(), c2.X())) {
213  // mmh... here we are well beyond SBND realm.
214  throw cet::exception("GeoObjectSorterSBND")
215  << "Wires differ only for x coordinate... this is not SBND any more!\n";
216  // return c1.X() < c2.X();
217  }
218 
219  //
220  // same center, same wire; strict ordering requires us to return false
221  //
222  return false;
223 
224 } // WireSorter()
225 
226 
227 //----------------------------------------------------------------------------
228 //--- geo::GeoObjectSorterSBND implementation
229 //---
231  : fDetVersion(p.get<std::string>("DetectorVersion", "SBND"))
232  {}
233 
234 
235 //----------------------------------------------------------------------------
237  (std::vector<geo::CryostatGeo>& cgeo) const
238  { std::sort(cgeo.begin(), cgeo.end(), CryostatSorter); }
239 
240 //----------------------------------------------------------------------------
242  (std::vector<geo::OpDetGeo> & opdet) const
243  {
244  std::sort(opdet.begin(), opdet.end(), OpDetsSorter);
245  }
246 
247 //----------------------------------------------------------------------------
248 void geo::GeoObjectSorterSBND::SortTPCs(std::vector<geo::TPCGeo>& tgeo) const
249  { std::sort(tgeo.begin(), tgeo.end(), TPCSorter); }
250 
251 //----------------------------------------------------------------------------
253  (std::vector<geo::PlaneGeo>& pgeo, geo::DriftDirection_t const driftDir)
254  const
255 {
256  // The drift direction has to be set before this method is called.
257  // Using the drift direction would render the trick of the sorter unnecessary.
258 
259  std::sort(pgeo.begin(), pgeo.end(), PlaneSorter);
260 
261  /*
262  switch (driftDir) {
263  case geo::kPosX:
264  std::sort(pgeo.rbegin(), pgeo.rend(), SortPlanes);
265  break;
266  case geo::kNegX:
267  std::sort(pgeo.begin(), pgeo.end(), SortPlanes);
268  break;
269  case geo::kUnknownDrift:
270  throw cet::exception("TPCGeo")
271  << "Drift direction is unknown, can't sort the planes\n";
272  } // driftDir
273  */
274 
275 } // geo::GeoObjectSorterSBND::SortPlanes()
276 
277 //----------------------------------------------------------------------------
279  (std::vector<geo::WireGeo>& wgeo) const
280  { std::sort(wgeo.begin(), wgeo.end(), WireSorter); }
281 
282 
283 
284 //----------------------------------------------------------------------------
285 
287  (std::vector<geo::AuxDetGeo>& adgeo) const
288 {
289 // std::sort(adgeo.begin(), adgeo.end(), sortAuxDetSBND);
290 }
291 
293  (std::vector<geo::AuxDetSensitiveGeo>& adsgeo) const
294  {}
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:65
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
Encapsulate the construction of a single cyostat.
virtual void SortAuxDetSensitive(std::vector< geo::AuxDetSensitiveGeo > &adsgeo) const override
auto const tol
Definition: SurfXYZTest.cc:16
pdgs p
Definition: selectors.fcl:22
Geometry information for a single TPC.
Definition: TPCGeo.h:38
virtual void SortCryostats(std::vector< geo::CryostatGeo > &cgeo) const override
double CenterX() const
Returns the world x coordinate of the center of the box.
Definition: BoxBoundedGeo.h:94
virtual void SortAuxDets(std::vector< geo::AuxDetGeo > &adgeo) const override
Point GetBoxCenter() const
Returns the centre of the box representing the plane.
Definition: PlaneGeo.h:498
bool TPCSorter(geo::TPCGeo const &t1, geo::TPCGeo const &t2)
double CenterZ() const
Returns the world z coordinate of the center of the box.
static bool OpDetsSorter(geo::OpDetGeo const &t1, geo::OpDetGeo const &t2)
virtual void SortWires(std::vector< geo::WireGeo > &wgeo) const override
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
GeoObjectSorterSBND(fhicl::ParameterSet const &p)
bool PlaneSorter(geo::PlaneGeo const &p1, geo::PlaneGeo const &p2)
virtual void SortPlanes(std::vector< geo::PlaneGeo > &pgeo, geo::DriftDirection_t driftDir) const override
process_name gaushit a
then local
T abs(T value)
virtual void SortOpDets(std::vector< geo::OpDetGeo > &opdet) const override
enum geo::driftdir DriftDirection_t
Drift direction: positive or negative.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
bool CryostatSorter(geo::CryostatGeo const &c1, geo::CryostatGeo const &c2)
Encapsulate the geometry of an auxiliary detector.
Encapsulate the geometry of a wire.
Encapsulate the geometry of an optical detector.
bool equal(double a, double b)
Comparison tolerance, in centimeters.
virtual void SortTPCs(std::vector< geo::TPCGeo > &tgeo) const override
Encapsulate the construction of a single detector plane.
double CenterY() const
Returns the world y coordinate of the center of the box.
void GetEnd(double *xyz) const
Definition: WireGeo.h:163
do i e
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
Definition: WireGeo.cxx:73
bool WireSorter(geo::WireGeo const &w1, geo::WireGeo const &w2)
physics pm2 e1
void LocalToWorld(const double *opdet, double *world) const
Transform point from local optical detector frame to world frame.
Definition: OpDetGeo.h:112
physics associatedGroupsWithLeft p1
Encapsulate the construction of a single detector plane.