LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PlaneGeo.cxx
Go to the documentation of this file.
1 
7 // class header
9 
10 // LArSoft includes
12 #include "larcorealg/Geometry/Exceptions.h" // geo::InvalidWireError
14 #include "larcorealg/Geometry/geo_vectors_utils.h" // geo::vect::convertTo()
16 
17 // Framework includes
18 #include "cetlib/pow.h"
19 #include "cetlib_except/exception.h"
21 
22 // ROOT includes
23 #include "TClass.h"
24 #include "TGeoBBox.h"
25 #include "TGeoManager.h"
26 #include "TGeoMatrix.h"
27 #include "TGeoNode.h"
28 #include "TMath.h"
29 
30 // C/C++ standard library
31 #include <array>
32 #include <cassert>
33 #include <functional> // std::less<>, std::greater<>, std::transform()
34 #include <iterator> // std::back_inserter()
35 #include <sstream> // std::ostringstream
36 #include <type_traits> // std::is_same<>, std::decay_t<>
37 
38 namespace {
39 
41  template <typename T>
42  T symmetricCapDelta(T value, T limit)
43  {
44 
45  return (value < -limit) ? -limit - value : (value > +limit) ? +limit - value : 0.0;
46 
47  } // symmetricCapDelta()
48 
50  template <typename T>
51  T symmetricCap(T value, T limit)
52  {
53 
54  return value + symmetricCapDelta(value, limit);
55 
56  } // symmetricCap()
57 
58 } // local namespace
59 
60 namespace geo {
61 
62  namespace details {
63 
64  //......................................................................
79 
81  : plane(plane), wMargin(wMargin), dMargin(dMargin)
82  {}
83 
84  ActiveAreaCalculator(geo::PlaneGeo const& plane, double margin = 0.0)
85  : ActiveAreaCalculator(plane, margin, margin)
86  {}
87 
88  operator geo::PlaneGeo::Rect() { return recomputeArea(); }
89 
90  private:
91  using Projection_t = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<double>,
94 
96  "Necessary maintenance: remove the now optional conversions");
97 
98  static constexpr std::size_t kFirstWireStart = 0;
99  static constexpr std::size_t kFirstWireEnd = 1;
100  static constexpr std::size_t kLastWireStart = 2;
101  static constexpr std::size_t kLastWireEnd = 3;
102 
103  PlaneGeo const& plane;
104  double const wMargin = 0.0;
105  double const dMargin = 0.0;
107 
110 
112  {
113  //
114  // Collect the projections of the relevant points.
115  //
116  // Sorted so that start points have width not larger than end points.
117  //
118  // PointWidthDepthProjection() erroneously returns a vector rather
119  // than a point, so a conversion is required
120  auto makeProjection = [](auto v) { return Projection_t(v.X(), v.Y()); };
121 
122  wireEnds[kFirstWireStart] =
123  makeProjection(plane.PointWidthDepthProjection(plane.FirstWire().GetStart()));
124  wireEnds[kFirstWireEnd] =
125  makeProjection(plane.PointWidthDepthProjection(plane.FirstWire().GetEnd()));
126  if (wireEnds[kFirstWireStart].X() > wireEnds[kFirstWireEnd].X())
127  std::swap(wireEnds[kFirstWireStart], wireEnds[kFirstWireEnd]);
128  wireEnds[kLastWireStart] =
129  makeProjection(plane.PointWidthDepthProjection(plane.LastWire().GetStart()));
130  wireEnds[kLastWireEnd] =
131  makeProjection(plane.PointWidthDepthProjection(plane.LastWire().GetEnd()));
132  if (wireEnds[kLastWireStart].X() > wireEnds[kLastWireEnd].X())
133  std::swap(wireEnds[kLastWireStart], wireEnds[kLastWireEnd]);
134  } // initializeWireEnds()
135 
137  {
138  //
139  // Find the basic area containing all the coordinates.
140  //
141 
142  // include all the coordinates of the first and last wire
143  for (auto const& aWireEnd : wireEnds) {
144  activeArea.width.extendToInclude(aWireEnd.X());
145  activeArea.depth.extendToInclude(aWireEnd.Y());
146  }
147 
148  } // includeAllWireEnds()
149 
151  {
152  //
153  // Modify the corners so that none is father than half a pitch from all
154  // wires.
155  //
156  // directions in wire/depth plane
157  Vector_t const widthDir = {1.0, 0.0};
158  Vector_t const depthDir = {0.0, 1.0};
159  Vector_t wireCoordDir =
161  double const hp = plane.WirePitch() / 2.0; // half pitch
162 
163  //
164  // The plan: identify if wires are across or corner, and then:
165  // - across:
166  // - identify which sides
167  // - set the farther end of the wire from the side to be p/2 from
168  // its corner
169  // - corner:
170  // - identify which corners
171  // - move the corners to p/2 from the wires
172  //
173 
174  //
175  // are the wires crossing side to side, as opposed to cutting corners?
176  //
177 
178  // these are the angles of the original wire coordinate direction
179  double const cosAngleWidth = geo::vect::dot(wireCoordDir, widthDir);
180  double const cosAngleDepth = geo::vect::dot(wireCoordDir, depthDir);
181  // if the wire coordinate direction is on first or third quadrant:
182  bool const bPositiveAngle = none_or_both((wireCoordDir.X() >= 0), (wireCoordDir.Y() >= 0));
183 
184  // now we readjust the wire coordinate direction to always point
185  // toward positive width; this breaks the relation between
186  // wireCoordDir and which is the first/last wire
187  if (cosAngleWidth < 0) wireCoordDir = -wireCoordDir;
188 
189  // let's study the first wire (ends are sorted by width)
190  assert(wireEnds[kFirstWireEnd].X() >= wireEnds[kFirstWireStart].X());
191  bool const bAlongWidth // horizontal
192  = equal(wireEnds[kFirstWireEnd].X(), activeArea.width.upper) &&
193  equal(wireEnds[kFirstWireStart].X(), activeArea.width.lower);
194  bool const bAlongDepth =
195  !bAlongWidth && // vertical
196  equal(std::max(wireEnds[kFirstWireStart].Y(), wireEnds[kFirstWireEnd].Y()),
197  activeArea.depth.upper) &&
198  equal(std::min(wireEnds[kFirstWireStart].Y(), wireEnds[kFirstWireEnd].Y()),
199  activeArea.depth.lower);
200  assert(!(bAlongWidth && bAlongDepth));
201 
202  if (bAlongWidth) { // horizontal
203 
204  // +---------+
205  // | ___,--| upper width bound
206  // |--' |
207 
208  // find which is the wire with higher width:
209  // the last wire is highest if the wire coordinate direction (which
210  // is defined by what is first and what is last) is parallel to the
211  // width direction
212  std::size_t const iUpperWire = (cosAngleDepth > 0) ? kLastWireStart : kFirstWireStart;
213  // largest distance from upper depth bound of the two ends of wire
214  double const maxUpperDistance =
215  activeArea.depth.upper -
216  std::min(wireEnds[iUpperWire].Y(), wireEnds[iUpperWire ^ 0x1].Y());
217  // set the upper side so that the maximum distance is p/2
218  // (it may be actually less if the wire is not perfectly horizontal)
219  activeArea.depth.upper += (hp - maxUpperDistance);
220 
221  // |--.___ |
222  // | `--| deal with the lower bound now
223  // +---------+
224 
225  std::size_t const iLowerWire = (cosAngleDepth > 0) ? kFirstWireStart : kLastWireStart;
226  // largest distance from lower depth bound of the two ends of wire
227  double const maxLowerDistance =
228  std::max(wireEnds[iLowerWire].Y(), wireEnds[iLowerWire ^ 0x1].Y()) -
229  activeArea.depth.lower;
230  // set the upper side so that the minimum distance is p/2
231  activeArea.depth.lower -= (hp - maxLowerDistance);
232 
233  } // horizontal wires
234  else if (bAlongDepth) { // vertical
235  // --,---+
236  // | |
237  // \ |
238  // | | upper depth bound
239  // \ |
240  // | |
241  // ------+
242 
243  // find which is the wire with higher depth:
244  // the last wire is highest if the wire coordinate direction (which
245  // is defined by what is first and what is last) is parallel to the
246  // depth direction
247  std::size_t const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
248  // largest distance from upper depth bound of the two ends of wire
249  double const maxUpperDistance =
250  activeArea.width.upper -
251  std::min(wireEnds[iUpperWire].X(), wireEnds[iUpperWire ^ 0x1].X());
252  // set the upper side so that the minimum distance is p/2
253  activeArea.width.upper += (hp - maxUpperDistance);
254 
255  // +-,----
256  // | |
257  // | \ .
258  // | | deal with the lower bound now
259  // | \ .
260  // | |
261  // +------
262  std::size_t const iLowerWire = (cosAngleWidth > 0) ? kFirstWireStart : kLastWireStart;
263  // largest distance from lower width bound of the two ends of wire
264  double const maxLowerDistance =
265  std::max(wireEnds[iLowerWire].X(), wireEnds[iLowerWire ^ 0x1].X()) -
266  activeArea.width.lower;
267  // set the upper side so that the minimum distance is p/2
268  activeArea.width.lower -= (hp - maxLowerDistance);
269 
270  } // vertical wires
271  else if (bPositiveAngle) { // wires are not going across: corners!
272  // corners at (lower width, lower depth), (upper width, upper depth)
273 
274  // -._------+
275  // `-._ | upper width corner (upper depth)
276  // `-|
277 
278  // start of the wire on the upper corner
279  // (width coordinate is lower for start than for end)
280  std::size_t const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
281 
282  double const upperDistance = geo::vect::dot(
283  Vector_t(activeArea.width.upper - wireEnds[iUpperWire].X(), 0.0), wireCoordDir);
284  // make the upper distance become p/2
285  auto const upperDelta = (hp - upperDistance) * wireCoordDir;
286  activeArea.width.upper += upperDelta.X();
287  activeArea.depth.upper += upperDelta.Y();
288 
289  // |-._
290  // | `-._ lower width corner (lower depth)
291  // +-------`-
292 
293  // end of the wire on the lower corner
294  // (width coordinate is lower than the end)
295  std::size_t const iLowerWire = (cosAngleWidth > 0) ? kFirstWireEnd : kLastWireEnd;
296 
297  double const lowerDistance = geo::vect::dot(
298  Vector_t(wireEnds[iLowerWire].X() - activeArea.width.lower, 0.0), wireCoordDir);
299  // make the lower distance become p/2 (note direction of wire coord)
300  auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
301  activeArea.width.lower -= lowerDelta.X();
302  activeArea.depth.lower -= lowerDelta.Y();
303  }
304  else { // !bPositiveAngle
305  // corners at (lower width, upper depth), (upper width, lower depth)
306 
307  // _,-|
308  // _,-' | upper width corner (lower depth)
309  // -'-------+
310 
311  // start of the wire on the upper corner
312  // (width coordinate is lower than the end)
313  std::size_t const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
314 
315  double const upperDistance = geo::vect::dot(
316  Vector_t(activeArea.width.upper - wireEnds[iUpperWire].X(), 0.0), wireCoordDir);
317  // make the upper distance become p/2
318  auto const upperDelta = (hp - upperDistance) * wireCoordDir;
319  activeArea.width.upper += upperDelta.X();
320  activeArea.depth.lower += upperDelta.Y();
321 
322  // +------_,-
323  // | _,-' lower width corner (upper depth)
324  // |-'
325 
326  // end of the wire on the lower corner
327  // (width coordinate is lower than the end)
328  std::size_t const iLowerWire = (cosAngleWidth > 0) ? kFirstWireEnd : kLastWireEnd;
329 
330  double const lowerDistance = geo::vect::dot(
331  Vector_t(wireEnds[iLowerWire].X() - activeArea.width.lower, 0.0), wireCoordDir);
332  // make the lower distance become p/2 (note direction of wire coord)
333  auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
334  activeArea.width.lower -= lowerDelta.X();
335  activeArea.depth.upper -= lowerDelta.Y();
336 
337  } // if ...
338 
339  } // adjustCorners()
340 
341  void applyMargin()
342  {
343  if (wMargin != 0.0) {
344  activeArea.width.lower += wMargin;
345  activeArea.width.upper -= wMargin;
346  }
347  if (dMargin != 0.0) {
348  activeArea.depth.lower += dMargin;
349  activeArea.depth.upper -= dMargin;
350  }
351  } // applyMargin()
352 
354  {
355  activeArea = {};
356 
357  //
358  // 0. collect the projections of the relevant point
359  //
361 
362  //
363  // 1. find the basic area containing all the coordinates
364  //
366 
367  //
368  // 2. adjust area so that no corner is father than half a wire pitch
369  //
370  adjustCorners();
371 
372  //
373  // 3. apply an absolute margin
374  //
375  applyMargin();
376 
377  return activeArea;
378  } // computeArea()
379 
381  static bool none_or_both(bool a, bool b) { return a == b; }
382 
384  template <typename T>
385  static bool equal(T a, T b, T tol = T(1e-5))
386  {
387  return std::abs(a - b) <= tol;
388  }
389 
390  }; // struct ActiveAreaCalculator
391 
392  //......................................................................
393 
394  } // namespace details
395 
396  //----------------------------------------------------------------------------
397  //--- geo::PlaneGeo
398  //---
399  PlaneGeo::PlaneGeo(TGeoNode const& node,
401  WireCollection_t&& wires)
402  : fTrans(std::move(trans))
403  , fVolume(node.GetVolume())
404  , fView(geo::kUnknown)
405  , fOrientation(geo::kVertical)
406  , fWire(std::move(wires))
407  , fWirePitch(0.)
408  , fSinPhiZ(0.)
409  , fCosPhiZ(0.)
410  , fDecompWire()
411  , fDecompFrame()
412  , fCenter()
413  {
414 
415  if (!fVolume) {
416  throw cet::exception("PlaneGeo")
417  << "Plane geometry node " << node.IsA()->GetName() << "[" << node.GetName() << ", #"
418  << node.GetNumber() << "] has no volume!\n";
419  }
420 
421  // view is now set at TPC level with SetView
422 
425 
426  } // PlaneGeo::PlaneGeo()
427 
428  //......................................................................
429 
431  {
432 
433  //
434  // The algorithm is not very refined...
435  //
436 
437  TGeoBBox const* pShape = dynamic_cast<TGeoBBox const*>(fVolume->GetShape());
438  if (!pShape) {
439  throw cet::exception("PlaneGeo")
440  << "BoundingBox(): volume " << fVolume->IsA()->GetName() << " is not a TGeoBBox!";
441  }
442 
443  geo::BoxBoundedGeo box;
444  unsigned int points = 0;
445  for (double dx : {-(pShape->GetDX()), +(pShape->GetDX())}) {
446  for (double dy : {-(pShape->GetDY()), +(pShape->GetDY())}) {
447  for (double dz : {-(pShape->GetDZ()), +(pShape->GetDZ())}) {
448 
449  auto const p = toWorldCoords(LocalPoint_t{dx, dy, dz});
450 
451  if (points++ == 0)
452  box.SetBoundaries(p, p);
453  else
454  box.ExtendToInclude(p);
455 
456  } // for z
457  } // for y
458  } // for x
459  return box;
460 
461  } // PlaneGeo::BoundingBox()
462 
463  //......................................................................
464 
465  geo::WireGeo const& PlaneGeo::Wire(unsigned int iwire) const
466  {
467  geo::WireGeo const* pWire = WirePtr(iwire);
468  if (!pWire) {
469  throw cet::exception("WireOutOfRange") << "Request for non-existant wire " << iwire << "\n";
470  }
471  return *pWire;
472  } // PlaneGeo::Wire(int)
473 
474  //......................................................................
475 
476  // sort the WireGeo objects
478  {
479  sorter.SortWires(fWire);
480  }
481 
482  //......................................................................
484  {
486  } // PlaneGeo::WireIDincreasesWithZ()
487 
488  // //......................................................................
489  // lar::util::simple_geo::Volume<Point_t> PlaneGeo::Coverage() const
490  // {
491  // return {FirstWire().GetStart(), LastWire().GetEnd()};
492  // } // PlaneGeo::Coverage()
493 
494  //......................................................................
495  std::string PlaneGeo::PlaneInfo(std::string indent /* = "" */,
496  unsigned int verbosity /* = 1 */) const
497  {
498  std::ostringstream sstr;
499  PrintPlaneInfo(sstr, indent, verbosity);
500  return sstr.str();
501  } // PlaneGeo::PlaneInfo()
502 
503  //......................................................................
505  double wMargin,
506  double dMargin) const
507  {
508 
509  return {symmetricCapDelta(proj.X(), fFrameSize.HalfWidth() - wMargin),
510  symmetricCapDelta(proj.Y(), fFrameSize.HalfDepth() - dMargin)};
511 
512  } // PlaneGeo::DeltaFromPlane()
513 
514  //......................................................................
517  double wMargin,
518  double dMargin) const
519  {
520 
521  return {fActiveArea.width.delta(proj.X(), wMargin), fActiveArea.depth.delta(proj.Y(), dMargin)};
522 
523  } // PlaneGeo::DeltaFromActivePlane()
524 
525  //......................................................................
527  {
528 
529  auto const deltaProj = DeltaFromPlane(PointWidthDepthProjection(point));
530 
531  return (deltaProj.X() == 0.) && (deltaProj.Y() == 0.);
532 
533  } // PlaneGeo::isProjectionOnPlane()
534 
535  //......................................................................
537  WidthDepthProjection_t const& proj) const
538  {
539  //
540  // We have a more complicate implementation to avoid rounding errors.
541  // In this way, the result is really guaranteed to be exactly on the border.
542  //
543  auto const delta = DeltaFromPlane(proj);
544  return {(delta.X() == 0.0) ?
545  proj.X() :
546  ((delta.X() > 0) ? -fFrameSize.HalfWidth() // delta positive -> proj on negative side
547  :
549  (delta.Y() == 0.0) ?
550  proj.Y() :
551  ((delta.Y() > 0) ? -fFrameSize.HalfDepth() // delta positive -> proj on negative side
552  :
553  fFrameSize.HalfDepth())};
554 
555  } // PlaneGeo::MoveProjectionToPlane()
556 
557  //......................................................................
559  {
560  //
561  // This implementation is subject to rounding errors, since the result of
562  // the addition might jitter above or below the border.
563  //
564 
565  auto const deltaProj = DeltaFromPlane(PointWidthDepthProjection(point));
566 
567  return point + deltaProj.X() * WidthDir() + deltaProj.Y() * DepthDir();
568 
569  } // PlaneGeo::MovePointOverPlane()
570 
571  //......................................................................
573  {
574 
575  //
576  // 1) compute the wire coordinate of the point
577  // 2) get the closest wire number
578  // 3) check if the wire does exist
579  // 4) build and return the wire ID
580  //
581 
582  // this line merges parts (1) and (2); add 0.5 to have the correct rounding:
583  int nearestWireNo = int(0.5 + WireCoordinate(pos));
584 
585  // if we are outside of the wireplane range, throw an exception
586  if ((nearestWireNo < 0) || ((unsigned int)nearestWireNo >= Nwires())) {
587 
588  auto wireNo = nearestWireNo; // save for the output
589 
590  if (nearestWireNo < 0)
591  wireNo = 0;
592  else
593  wireNo = Nwires() - 1;
594 
595  throw InvalidWireError("Geometry", ID(), nearestWireNo, wireNo)
596  << "Can't find nearest wire for position " << pos << " in plane " << std::string(ID())
597  << " approx wire number # " << wireNo << " (capped from " << nearestWireNo << ")\n";
598  } // if invalid
599 
600  return {ID(), (geo::WireID::WireID_t)nearestWireNo};
601 
602  } // PlaneGeo::NearestWireID()
603 
604  //......................................................................
606  {
607 
608  //
609  // Note that this code is ready for when NearestWireID() will be changed
610  // to return an invalid ID instead of throwing.
611  // As things are now, `NearestWireID()` will never return an invalid ID,
612  // but it will throw an exception similar to this one.
613  //
614 
615  geo::WireID const wireID = NearestWireID(point);
616  if (wireID) return Wire(wireID); // we have that wire, so we return it
617 
618  // wire ID is invalid, meaning it's out of range. Throw an exception!
619  geo::WireID const closestID = ClosestWireID(wireID);
620  throw InvalidWireError("Geometry", ID(), closestID.Wire, wireID.Wire)
621  << "Can't find nearest wire for position " << point << " in plane " << std::string(ID())
622  << " approx wire number # " << closestID.Wire << " (capped from " << wireID.Wire << ")\n";
623 
624  } // PlaneGeo::NearestWire()
625 
626  //......................................................................
628  {
629  assert(lar::util::Vector2DComparison{1e-6}.nonZero(projDir));
630  return std::sqrt(cet::square(projDir.X() / projDir.Y()) + 1.0) * fWirePitch;
631  } // PlaneGeo::InterWireProjectedDistance()
632 
633  //......................................................................
635  {
636  // the secondary component of the wire decomposition basis is wire coord.
637  double const r = dir.R();
638  assert(r >= 1.e-6);
639 
640  double const absWireCoordProj = std::abs(fDecompWire.VectorSecondaryComponent(dir));
641  return r / absWireCoordProj * fWirePitch;
642 
643  } // PlaneGeo::InterWireDistance()
644 
645  //......................................................................
646  double PlaneGeo::ThetaZ() const
647  {
648  return FirstWire().ThetaZ();
649  }
650 
651  //......................................................................
653  {
654  // the order here matters
655 
656  // reset our ID
657  fID = planeid;
658 
659  UpdatePlaneNormal(TPCbox);
662 
663  // update wires
664  geo::WireID::WireID_t wireNo = 0;
665  for (auto& wire : fWire) {
666  wire.UpdateAfterSorting(geo::WireID(fID, wireNo), shouldFlipWire(wire));
667  ++wireNo;
668  } // for wires
669 
671  UpdateWireDir();
674  UpdateWirePitch();
676  UpdatePhiZ();
677  UpdateView();
678 
679  } // PlaneGeo::UpdateAfterSorting()
680 
681  //......................................................................
682  std::string PlaneGeo::ViewName(geo::View_t view)
683  {
684  switch (view) {
685  case geo::kU: return "U";
686  case geo::kV: return "V";
687  case geo::kZ: return "Z";
688  case geo::kY: return "Y";
689  case geo::kX: return "X";
690  case geo::k3D: return "3D";
691  case geo::kUnknown: return "?";
692  default: return "<UNSUPPORTED (" + std::to_string((int)view) + ")>";
693  } // switch
694  } // PlaneGeo::ViewName()
695 
696  //......................................................................
697  std::string PlaneGeo::OrientationName(geo::Orient_t orientation)
698  {
699  switch (orientation) {
700  case geo::kHorizontal: return "horizontal"; break;
701  case geo::kVertical: return "vertical"; break;
702  default: return "unexpected"; break;
703  } // switch
704  } // PlaneGeo::OrientationName()
705 
706  //......................................................................
708  {
709 
710  //
711  // We need to identify which are the "long" directions of the plane.
712  // We assume it is a box, and the shortest side is excluded.
713  // The first direction ("width") is given by preference to z.
714  // If z is the direction of the normal to the plane... oh well.
715  // Let's say privilege to the one which comes from local z, then y.
716  // That means: undefined.
717  //
718  // Requirements:
719  // - ROOT geometry information (shapes and transformations)
720  // - the shape must be a box (an error is PRINTED if not)
721  // - center of the wire plane (not just the center of the plane box)
722  //
723 
724  //
725  // how do they look like in the world?
726  //
727  TGeoBBox const* pShape = dynamic_cast<TGeoBBox const*>(fVolume->GetShape());
728  if (!pShape) {
729  mf::LogError("BoxInfo") << "Volume " << fVolume->IsA()->GetName()
730  << " is not a TGeoBBox! Dimensions won't be available.";
731  // set it invalid
733  fDecompFrame.SetMainDir({0., 0., 0.});
734  fDecompFrame.SetSecondaryDir({0., 0., 0.});
735  fFrameSize = {0.0, 0.0};
736  return;
737  }
738 
739  std::array<geo::Vector_t, 3U> sides;
740  size_t iSmallest = 3;
741  {
742  size_t iSide = 0;
743 
744  sides[iSide] = toWorldCoords(LocalVector_t{pShape->GetDX(), 0.0, 0.0});
745  iSmallest = iSide;
746  ++iSide;
747 
748  sides[iSide] = toWorldCoords(LocalVector_t{0.0, pShape->GetDY(), 0.0});
749  if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
750  ++iSide;
751 
752  sides[iSide] = toWorldCoords(LocalVector_t{0.0, 0.0, pShape->GetDZ()});
753  if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
754  ++iSide;
755  }
756 
757  //
758  // which are the largest ones?
759  //
760  size_t kept[2];
761  {
762  size_t iKept = 0;
763  for (size_t i = 0; i < 3; ++i)
764  if (i != iSmallest) kept[iKept++] = i;
765  }
766 
767  //
768  // which is which?
769  //
770  // Pick width as the most z-like.
771  //
772  size_t const iiWidth =
773  std::abs(sides[kept[0]].Unit().Z()) > std::abs(sides[kept[1]].Unit().Z()) ? 0 : 1;
774  size_t const iWidth = kept[iiWidth];
775  size_t const iDepth = kept[1 - iiWidth]; // the other
776 
777  fDecompFrame.SetMainDir(geo::vect::rounded01(sides[iWidth].Unit(), 1e-4));
778  fDecompFrame.SetSecondaryDir(geo::vect::rounded01(sides[iDepth].Unit(), 1e-4));
779  fFrameSize.halfWidth = sides[iWidth].R();
780  fFrameSize.halfDepth = sides[iDepth].R();
781 
782  } // PlaneGeo::DetectGeometryDirections()
783 
784  //......................................................................
786  {
787  const unsigned int NWires = Nwires();
788  if (NWires < 2) return {}; // why are we even here?
789 
790  // 1) get the direction of the middle wire
791  auto const WireDir = Wire(NWires / 2).Direction();
792 
793  // 2) get the direction between the middle wire and the next one
794  auto const ToNextWire = Wire(NWires / 2 + 1).GetCenter() - Wire(NWires / 2).GetCenter();
795 
796  // 3) get the direction perpendicular to the plane
797  // 4) round it
798  // 5) return its norm
799  return geo::vect::rounded01(WireDir.Cross(ToNextWire).Unit(), 1e-4);
800 
801  } // PlaneGeo::GetNormalAxis()
802 
803  //......................................................................
805  {
806 
807  //
808  // this algorithm needs to know about the axis;
809  // the normal is expected to be already updated.
810  //
811 
812  // sanity check
813  if (fWire.size() < 2) {
814  // this likely means construction is not complete yet
815  throw cet::exception("NoWireInPlane")
816  << "PlaneGeo::UpdateOrientation(): only " << fWire.size() << " wires!\n";
817  } // if
818 
819  auto normal = GetNormalDirection();
820 
821  if (std::abs(std::abs(normal.X()) - 1.) < 1e-3)
823  else if (std::abs(std::abs(normal.Y()) - 1.) < 1e-3)
825  else {
826  // at this point, the only problem is the lack of a label for this
827  // orientation; probably introducing a geo::kOtherOrientation would
828  // suffice
829  throw cet::exception("Geometry")
830  << "Plane with unsupported orientation (normal: " << normal << ")\n";
831  }
832 
833  } // PlaneGeo::UpdateOrientation()
834 
835  //......................................................................
837  {
838  // pick long wires around the center of the detector,
839  // so that their coordinates are defined with better precision
840  assert(Nwires() > 1);
841 
842  auto const iWire = Nwires() / 2;
843 
844  fWirePitch = geo::WireGeo::WirePitch(Wire(iWire - 1), Wire(iWire));
845 
846  } // PlaneGeo::UpdateWirePitch()
847 
848  //......................................................................
850  {
851  auto const& wire_coord_dir = GetIncreasingWireDirection();
852  fCosPhiZ = wire_coord_dir.Z();
853  fSinPhiZ = wire_coord_dir.Y();
854  } // PlaneGeo::UpdatePhiZ()
855 
857  {
858  /*
859  * This algorithm assigns views according to the angle the wire axis cuts
860  * with y axis ("thetaY"), but from the point of view of the center of the
861  * TPC.
862  * A special case is when the drift axis is on y axis.
863  *
864  * In the normal case, the discrimination happens on the the arctangent of
865  * the point { (y,w), (y x n,w) }, where w is the wire direction, y is the
866  * coordinate axis and n the normal to the wire plane. This definition gives
867  * the same value regardless of the direction of w on its axis.
868  *
869  * If thetaY is 0, wires are parallel to the y axis:
870  * the view is assigned as kX or kZ depending on whether the plane normal is
871  * closer to the z axis or the x axis, respectively (the normal describes
872  * a direction _not_ measured by the wires).
873  *
874  * If thetaY is a right angle, the wires are orthogonal to y axis and view
875  * kY view is assigned.
876  * If thetaY is smaller than 0, the view is called "U".
877  * If thetaY is larger than 0, the view is called "V".
878  *
879  * The special case where the drift axis is on y axis is treated separately.
880  * In that case, the role of y axis is replaced by the z axis and the
881  * discriminating figure is equivalent to the usual ThetaZ().
882  *
883  * If thetaZ is 0, the wires are measuring x and kX view is chosen.
884  * If thetaZ is a right angle, the wires are measuring z and kZ view is
885  * chosen.
886  * If thetaZ is smaller than 0, the view is called "U".
887  * If thetaZ is larger than 0, the view is called "V".
888  *
889  */
890 
891  auto const& normalDir = GetNormalDirection();
892  auto const& wireDir = GetWireDirection();
893 
894  // normal direction has been rounded, so exact comparison can work
895  if (std::abs(normalDir.Y()) != 1.0) {
896  //
897  // normal case: drift direction is not along y (vertical)
898  //
899 
900  // yw is pretty much GetWireDirection().Y()...
901  // thetaY is related to atan2(ynw, yw)
902  double const yw = geo::vect::dot(wireDir, geo::Yaxis());
903  double const ynw = geo::vect::mixedProduct(geo::Yaxis(), normalDir, wireDir);
904 
905  if (std::abs(yw) < 1.0e-4) { // wires orthogonal to y axis
906  double const closeToX = std::abs(geo::vect::dot(normalDir, geo::Xaxis()));
907  double const closeToZ = std::abs(geo::vect::dot(normalDir, geo::Zaxis()));
908  SetView((closeToZ > closeToX) ? geo::kX : geo::kY);
909  }
910  else if (std::abs(ynw) < 1.0e-4) { // wires parallel to y axis
911  SetView(geo::kZ);
912  }
913  else if ((ynw * yw) < 0)
914  SetView(geo::kU); // different sign => thetaY > 0
915  else if ((ynw * yw) > 0)
916  SetView(geo::kV); // same sign => thetaY < 0
917  else
918  assert(false); // logic error?!
919  }
920  else { // if drift is vertical
921  //
922  // special case: drift direction is along y (vertical)
923  //
924 
925  // zw is pretty much GetWireDirection().Z()...
926  double const zw = geo::vect::dot(wireDir, geo::Zaxis());
927  // while GetNormalDirection() axis is on y, its direction is not fixed:
928  double const znw = geo::vect::mixedProduct(geo::Zaxis(), normalDir, wireDir);
929 
930  // thetaZ is std::atan(znw/zw)
931 
932  if (std::abs(zw) < 1.0e-4) { // orthogonal to z, orthogonal to y...
933  // this is equivalent to thetaZ = +/- pi/2
934  SetView(geo::kZ);
935  }
936  else if (std::abs(znw) < 1.0e-4) { // parallel to z, orthogonal to y...
937  // this is equivalent to thetaZ = 0
938  SetView(geo::kX);
939  }
940  else if ((znw * zw) < 0)
941  SetView(geo::kU); // different sign => thetaZ > 0
942  else if ((znw * zw) > 0)
943  SetView(geo::kV); // same sign => thetaZ < 0
944  else
945  assert(false); // logic error?!
946 
947  } // if drift direction... else
948 
949  } // UpdateView()
950 
951  //......................................................................
953  {
954 
955  //
956  // direction normal to the wire plane, points toward the center of TPC
957  //
958 
959  // start from the axis
961 
962  // now evaluate where we are pointing
963  auto const towardCenter = TPCbox.Center() - GetBoxCenter();
964 
965  // if they are pointing in opposite directions, flip the normal
966  if (fNormal.Dot(towardCenter) < 0) fNormal = -fNormal;
968 
969  } // PlaneGeo::UpdatePlaneNormal()
970 
971  //......................................................................
973  {
974 
975  //
976  // fix the positiveness of the width/depth/normal frame
977  //
978 
979  // The basis is already set and orthonormal, with only the width
980  // and depth directions arbitrary.
981  // We choose the direction of the secondary axis ("depth")
982  // so that the frame normal is oriented in the general direction of the
983  // plane normal (the latter is computed independently).
984  if (WidthDir().Cross(DepthDir()).Dot(GetNormalDirection()) < 0.0) {
986  }
987 
988  } // PlaneGeo::UpdateWidthDepthDir()
989 
990  //......................................................................
992  {
993 
994  //
995  // Direction measured by the wires, pointing toward increasing wire number;
996  // requires:
997  // - the normal to the plane to be correct
998  // - wires to be sorted
999  //
1000 
1001  // 1) get the direction of the middle wire
1002  auto refWireNo = Nwires() / 2;
1003  if (refWireNo == Nwires() - 1) --refWireNo;
1004  auto const& refWire = Wire(refWireNo);
1005  auto const& WireDir = refWire.Direction(); // we only rely on the axis
1006 
1007  // 2) get the axis perpendicular to it on the wire plane
1008  // (arbitrary direction)
1009  auto wireCoordDir = GetNormalDirection().Cross(WireDir).Unit();
1010 
1011  // 3) where is the next wire?
1012  auto toNextWire = Wire(refWireNo + 1).GetCenter() - refWire.GetCenter();
1013 
1014  // 4) if wireCoordDir is pointing away from the next wire, flip it
1015  if (wireCoordDir.Dot(toNextWire) < 0) { wireCoordDir = -wireCoordDir; }
1017 
1018  } // PlaneGeo::UpdateIncreasingWireDir()
1019 
1020  //......................................................................
1022  {
1023 
1025 
1026  //
1027  // check that the resulting normal matches the plane one
1028  //
1029  assert(
1031 
1032  } // PlaneGeo::UpdateWireDir()
1033 
1034  //......................................................................
1036  {
1037 
1038  //
1039  // Compare one wire (the first one, for convenience) with all other wires;
1040  // the wire pitch is the smallest distance we find.
1041  //
1042  // This algorithm assumes wire pitch is constant, but it does not assume
1043  // wire ordering (which UpdateWirePitch() does).
1044  //
1045  auto firstWire = fWire.cbegin(), wire = firstWire, wend = fWire.cend();
1046  fWirePitch = geo::WireGeo::WirePitch(*firstWire, *(++wire));
1047 
1048  while (++wire != wend) {
1049  auto wirePitch = geo::WireGeo::WirePitch(*firstWire, *wire);
1050  if (wirePitch < 1e-4) continue; // it's 0!
1051  if (wirePitch < fWirePitch) fWirePitch = wirePitch;
1052  } // while
1053 
1054  } // PlaneGeo::UpdateWirePitchSlow()
1055 
1056  //......................................................................
1058  {
1059 
1060  //
1061  // update the origin of the reference frame (the middle of the first wire)
1062  //
1064 
1065  } // PlaneGeo::UpdateDecompWireOrigin()
1066 
1067  //......................................................................
1069  {
1070 
1071  //
1072  // The active area is defined in the width/depth space which include
1073  // approximatively all wires.
1074  //
1075  // See `ActiveAreaCalculator` for details of the algorithm.
1076  //
1077 
1078  // we scratch 1 um from each side to avoid rounding errors later
1079  fActiveArea = details::ActiveAreaCalculator(*this, 0.0001);
1080 
1081  } // PlaneGeo::UpdateActiveArea()
1082 
1083  //......................................................................
1085  {
1086 
1087  //
1088  // The center of the wire plane is defined as the center of the plane box,
1089  // translated to the plane the wires lie on.
1090  // This assumes that the thickness direction of the box is aligned with
1091  // the drift direction, so that the translated point is still in the middle
1092  // of width and depth dimensions.
1093  // It is possible to remove that assumption by translating the center of the
1094  // box along the thickness direction enough to bring it to the wire plane.
1095  // The math is just a bit less straightforward, so we don't bother yet.
1096  //
1097  // Requirements:
1098  // * the wire decomposition frame must be set up (at least its origin and
1099  // normal direction)
1100  //
1101 
1102  fCenter = GetBoxCenter();
1103 
1105 
1106  geo::vect::round0(fCenter, 1e-7); // round dimensions less than 1 nm to 0
1107 
1108  fDecompFrame.SetOrigin(fCenter); // equivalent to GetCenter() now
1109 
1110  } // PlaneGeo::UpdateWirePlaneCenter()
1111 
1112  //......................................................................
1113  bool PlaneGeo::shouldFlipWire(geo::WireGeo const& wire) const
1114  {
1115  //
1116  // The correct orientation is so that:
1117  //
1118  // (direction) x (wire coordinate direction) . (plane normal)
1119  //
1120  // is positive; it it's negative, then we should flip the wire.
1121  //
1122  // Note that the increasing wire direction comes from the wire frame, while
1123  // the normal direction is computed independently by geometry.
1124  // The resulting normal in the wire frame is expected to be the same as the
1125  // plane normal from GetNormalDirection(); if this is not the case, flipping
1126  // the wire direction should restore it.
1127  //
1128 
1129  return wire.Direction().Cross(GetIncreasingWireDirection()).Dot(GetNormalDirection()) <
1130  +0.5; // should be in fact exactly +1
1131 
1132  } // PlaneGeo::shouldFlipWire()
1133 
1134  //......................................................................
1135 
1136 } // namespace geo
static std::string OrientationName(geo::Orient_t orientation)
Returns the name of the specified orientation.
Definition: PlaneGeo.cxx:697
TRandom r
Definition: spectrum.C:23
geo::WirePtr WirePtr(unsigned int iwire) const
Returns the wire number iwire from this plane.
Definition: PlaneGeo.h:293
void round01(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:114
double HalfWidth() const
Definition: PlaneGeo.h:1324
auto VectorSecondaryComponent(Vector_t const &v) const
Returns the secondary component of a vector.
Definition: Decomposer.h:530
void SetView(geo::View_t view)
Set the signal view (for TPCGeo).
Definition: PlaneGeo.h:1254
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthDisplacement_t
Type for vector projections in the plane frame base representation.
Definition: PlaneGeo.h:144
Point_t const & GetCenter() const
Returns the world coordinate of the center of the wire [cm].
Definition: WireGeo.h:221
WidthDepthProjection_t VectorWidthDepthProjection(geo::Vector_t const &v) const
Returns the projection of the specified vector on the plane.
Definition: PlaneGeo.h:1018
geo::Point_t fCenter
Center of the plane, lying on the wire plane.
Definition: PlaneGeo.h:1352
static std::string ViewName(geo::View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:682
std::string PlaneInfo(std::string indent="", unsigned int verbosity=1) const
Returns a string with plane information.
Definition: PlaneGeo.cxx:495
void UpdateIncreasingWireDir()
Updates the cached direction to increasing wires.
Definition: PlaneGeo.cxx:991
double fWirePitch
Pitch of wires in this plane.
Definition: PlaneGeo.h:1335
void SetSecondaryDir(Vector_t const &dir)
Change the secondary direction of the projection base.
Definition: Decomposer.h:441
std::vector< geo::WireGeo > WireCollection_t
Definition: PlaneGeo.h:81
void UpdateWirePitch()
Updates the stored wire pitch.
Definition: PlaneGeo.cxx:836
void UpdateWidthDepthDir()
Updates the cached depth and width direction.
Definition: PlaneGeo.cxx:972
Vector_t const & DepthDir() const
Return the direction of plane depth.
Definition: PlaneGeo.h:212
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:160
Point_t const & GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
Definition: PlaneGeo.h:435
double const dMargin
Margin subtracted from each side of depth.
Definition: PlaneGeo.cxx:105
static bool none_or_both(bool a, bool b)
Returns true if a and b are both true or both false (exclusive nor).
Definition: PlaneGeo.cxx:381
lar::util::simple_geo::Rectangle< double > Rect
Type for description of rectangles.
Definition: PlaneGeo.h:157
Vector_t const & NormalDir() const
Returns the plane normal axis direction.
Definition: Decomposer.h:461
WireGeo const & Wire(unsigned int iwire) const
Definition: PlaneGeo.cxx:465
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:136
auto mixedProduct(Vector const &a, Vector const &b, Vector const &c)
Unknown view.
Definition: geo_types.h:142
enum geo::_plane_orient Orient_t
Enumerate the possible plane projections.
Float_t x1[n_points_granero]
Definition: compare.C:5
Provides simple real number checks.
void UpdateOrientation()
Updates plane orientation.
Definition: PlaneGeo.cxx:804
Float_t Y
Definition: plot.C:37
geo::PlaneID fID
ID of this plane.
Definition: PlaneGeo.h:1354
Planes which measure X direction.
Definition: geo_types.h:140
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
void extendToInclude(Data_t)
Extends the range to include the specified point.
Definition: SimpleGeo.h:484
constexpr Vector Yaxis()
Returns a y axis vector of the specified type.
Definition: geo_vectors.h:215
geo::PlaneGeo::WidthDepthDisplacement_t Vector_t
Definition: PlaneGeo.cxx:93
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool isProjectionOnPlane(geo::Point_t const &point) const
Returns if the projection of specified point is within the plane.
Definition: PlaneGeo.cxx:526
static constexpr std::size_t kLastWireStart
Definition: PlaneGeo.cxx:100
WidthDepthProjection_t PointWidthDepthProjection(geo::Point_t const &point) const
Returns the projection of the specified point on the plane.
Definition: PlaneGeo.h:1000
STL namespace.
static constexpr std::size_t kFirstWireStart
Definition: PlaneGeo.cxx:98
Planes which measure Z direction.
Definition: geo_types.h:138
geo::WireGeo const & NearestWire(geo::Point_t const &pos) const
Returns the wire closest to the specified position.
Definition: PlaneGeo.cxx:605
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:563
double WireCoordinate(geo::Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:797
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool shouldFlipWire(geo::WireGeo const &wire) const
Whether the specified wire should have start and end swapped.
Definition: PlaneGeo.cxx:1113
void round0(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
Point_t GetStart() const
Returns the world coordinate of one end of the wire [cm].
Definition: WireGeo.h:226
Point_t GetEnd() const
Returns the world coordinate of one end of the wire [cm].
Definition: WireGeo.h:231
PlaneGeo const & plane
Plane to work on.
Definition: PlaneGeo.cxx:103
WidthDepthProjection_t MoveProjectionToPlane(WidthDepthProjection_t const &proj) const
Returns the projection, moved onto the plane if necessary.
Definition: PlaneGeo.cxx:536
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
Definition: WireGeo.h:248
geo::BoxBoundedGeo BoundingBox() const
Definition: PlaneGeo.cxx:430
Class for approximate comparisons.
Planes which measure Y direction.
Definition: geo_types.h:139
void DetectGeometryDirections()
Sets the geometry directions.
Definition: PlaneGeo.cxx:707
Projection_t wireEnds[4]
Cache: wire end projections.
Definition: PlaneGeo.cxx:109
double InterWireProjectedDistance(WireCoordProjection_t const &projDir) const
Returns the distance between wires along the specified direction.
Definition: PlaneGeo.cxx:627
void DriftPoint(geo::Point_t &position, double distance) const
Shifts the position of an electron drifted by a distance.
Definition: PlaneGeo.h:579
geo::Vector_t fNormal
Definition: PlaneGeo.h:1339
Rect fActiveArea
Area covered by wires in frame base.
Definition: PlaneGeo.h:1350
geo::PlaneGeo::Rect recomputeArea()
Definition: PlaneGeo.cxx:353
3-dimensional objects, potentially hits, clusters, prongs, etc.
Definition: geo_types.h:141
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:646
Float_t Z
Definition: plot.C:37
void UpdatePlaneNormal(geo::BoxBoundedGeo const &TPCbox)
Updates the cached normal to plane versor; needs the TPC box coordinates.
Definition: PlaneGeo.cxx:952
TGeoVolume const * fVolume
Plane volume description.
Definition: PlaneGeo.h:1331
Planes which measure U.
Definition: geo_types.h:135
Planes that are in the horizontal plane.
Definition: geo_types.h:146
Collection of exceptions for Geometry system.
Point_t GetBoxCenter() const
Returns the centre of the box representing the plane.
Definition: PlaneGeo.h:449
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object.
geo::WireID NearestWireID(geo::Point_t const &pos) const
Returns the ID of wire closest to the specified position.
Definition: PlaneGeo.cxx:572
WidthDepthDecomposer_t fDecompFrame
Definition: PlaneGeo.h:1347
void UpdatePhiZ()
Updates the stored .
Definition: PlaneGeo.cxx:849
Vector_t Direction() const
Definition: WireGeo.h:289
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
Planes that are in the vertical plane (e.g. ArgoNeuT).
Definition: geo_types.h:147
geo::Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local plane frame to world frame.
Definition: PlaneGeo.h:1225
Vector_t const & GetWireDirection() const
Returns the direction of the wires.
Definition: PlaneGeo.h:459
WireCollection_t fWire
List of wires in this plane.
Definition: PlaneGeo.h:1334
geo::Point_t MovePointOverPlane(geo::Point_t const &point) const
Returns the point, moved so that its projection is over the plane.
Definition: PlaneGeo.cxx:558
std::string indent(std::size_t const i)
double fSinPhiZ
Sine of .
Definition: PlaneGeo.h:1336
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:78
double InterWireDistance(geo::Vector_t const &dir) const
Returns the distance between wires along the specified direction.
Definition: PlaneGeo.cxx:634
Utilities to extend the interface of geometry vectors.
constexpr Vector Xaxis()
Returns a x axis vector of the specified type.
Definition: geo_vectors.h:208
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WireCoordinateReferenceTag > WireCoordProjection_t
Type for projections in the wire base representation.
Definition: PlaneGeo.h:121
Class comparing 2D vectors.
Range_t width
Range along width direction.
Definition: SimpleGeo.h:429
void UpdateWirePitchSlow()
Updates the stored wire pitch with a slower, more robust algorithm.
Definition: PlaneGeo.cxx:1035
const WireGeo & FirstWire() const
Return the first wire in the plane.
Definition: PlaneGeo.h:312
RectSpecs fFrameSize
Definition: PlaneGeo.h:1348
void UpdateAfterSorting(geo::PlaneID planeid, geo::BoxBoundedGeo const &TPCbox)
Performs all needed updates after the TPC has sorted the planes.
Definition: PlaneGeo.cxx:652
constexpr auto dot(Vector const &a, OtherVector const &b)
Return cross product of two vectors.
static constexpr std::size_t kLastWireEnd
Definition: PlaneGeo.cxx:101
double value
Definition: spectrum.C:18
void UpdateView()
Updates the stored view.
Definition: PlaneGeo.cxx:856
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
double HalfDepth() const
Definition: PlaneGeo.h:1325
Encapsulate the geometry of a wire.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthProjection_t
Definition: PlaneGeo.h:140
constexpr Vector Zaxis()
Returns a z axis vector of the specified type.
Definition: geo_vectors.h:222
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
Range_t depth
Range along depth direction.
Definition: SimpleGeo.h:430
Tag for plane frame base vectors.
Definition: PlaneGeo.h:135
ActiveAreaCalculator(geo::PlaneGeo const &plane, double margin=0.0)
Definition: PlaneGeo.cxx:84
void SetOrigin(Point_t const &point)
Change the 3D point of the reference frame origin.
Definition: Decomposer.h:435
Vector_t const & SecondaryDir() const
Returns the plane secondary axis direction.
Definition: Decomposer.h:458
WidthDepthProjection_t DeltaFromPlane(WidthDepthProjection_t const &proj, double wMargin, double dMargin) const
Returns a projection vector that, added to the argument, gives a projection inside (or at the border ...
Definition: PlaneGeo.cxx:504
Data_t delta(Data_t v, Data_t margin=0.0) const
Definition: SimpleGeo.h:473
WidthDepthProjection_t DeltaFromActivePlane(WidthDepthProjection_t const &proj, double wMargin, double dMargin) const
Returns a projection vector that, added to the argument, gives a projection inside (or at the border ...
Definition: PlaneGeo.cxx:515
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
geo::Vector_t GetNormalAxis() const
Returns a direction normal to the plane (pointing is not defined).
Definition: PlaneGeo.cxx:785
Encapsulate the construction of a single detector plane.
void PrintPlaneInfo(Stream &&out, std::string indent="", unsigned int verbosity=1) const
Returns a volume including all the wires in the plane.
Definition: PlaneGeo.h:1384
double DistanceFromPlane(geo::Point_t const &point) const
Returns the distance of the specified point from the wire plane.
Definition: PlaneGeo.h:558
TDirectory * dir
Definition: macro.C:5
void SetBoundaries(Coord_t x_min, Coord_t x_max, Coord_t y_min, Coord_t y_max, Coord_t z_min, Coord_t z_max)
Sets the boundaries in world coordinates as specified.
constexpr bool nonNegative(Value_t value) const
Returns whether value is larger than or equal() to zero.
geo::PlaneID const & ID() const
Returns the identifier of this plane.
Definition: PlaneGeo.h:184
double const wMargin
Margin subtracted from each side of width.
Definition: PlaneGeo.cxx:104
Vector_t const & WidthDir() const
Return the direction of plane width.
Definition: PlaneGeo.h:200
ActiveAreaCalculator(geo::PlaneGeo const &plane, double wMargin, double dMargin)
Definition: PlaneGeo.cxx:80
Float_t proj
Definition: plot.C:35
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:242
geo::WireID ClosestWireID(geo::WireID::WireID_t wireNo) const
Returns the closest valid wire ID to the specified wire.
Definition: PlaneGeo.h:1365
bool WireIDincreasesWithZ() const
Returns whether the higher z wires have higher wire ID.
Definition: PlaneGeo.cxx:483
void ExtendToInclude(Coord_t x, Coord_t y, Coord_t z)
Extends the current box to also include the specified point.
double fCosPhiZ
Cosine of .
Definition: PlaneGeo.h:1337
Data_t upper
Ending coordinate.
Definition: SimpleGeo.h:359
Vector_t const & GetIncreasingWireDirection() const
Returns the direction of increasing wires.
Definition: PlaneGeo.h:418
Exception thrown on invalid wire number.
Definition: Exceptions.h:39
Vector_t const & GetNormalDirection() const
Returns the direction normal to the plane.
Definition: PlaneGeo.h:407
static double WirePitch(WireGeo const &w1, WireGeo const &w2)
Returns the pitch (distance on y/z plane) between two wires, in cm.
Definition: WireGeo.h:449
static constexpr std::size_t kFirstWireEnd
Definition: PlaneGeo.cxx:99
unsigned int WireID_t
Type for the ID number.
Definition: geo_types.h:546
void UpdateWirePlaneCenter()
Updates the stored wire plane center.
Definition: PlaneGeo.cxx:1084
Direction
Definition: types.h:12
WireDecomposer_t fDecompWire
Definition: PlaneGeo.h:1343
static bool equal(T a, T b, T tol=T(1e-5))
Returns whether the two numbers are the same, lest a tolerance.
Definition: PlaneGeo.cxx:385
virtual void SortWires(std::vector< geo::WireGeo > &wgeo) const =0
void UpdateDecompWireOrigin()
Updates the position of the wire coordinate decomposition.
Definition: PlaneGeo.cxx:1057
Class computing the active area of the plane.
Definition: PlaneGeo.cxx:78
void UpdateActiveArea()
Updates the internally used active area.
Definition: PlaneGeo.cxx:1068
Collection of Physical constants used in LArSoft.
Float_t e
Definition: plot.C:35
geo::Vector3DBase_t< PlaneGeoCoordinatesTag > LocalVector_t
Type of displacement vectors in the local GDML wire plane frame.
Definition: PlaneGeo.h:109
Data_t lower
Starting coordinate.
Definition: SimpleGeo.h:358
const WireGeo & LastWire() const
Return the last wire in the plane.
Definition: PlaneGeo.h:318
Float_t X
Definition: plot.C:37
Namespace collecting geometry-related classes utilities.
void SortWires(geo::GeoObjectSorter const &sorter)
Apply sorting to WireGeo objects.
Definition: PlaneGeo.cxx:477
Orient_t fOrientation
Is the plane vertical or horizontal?
Definition: PlaneGeo.h:1333
void UpdateWireDir()
Updates the cached direction to wire.
Definition: PlaneGeo.cxx:1021
geo::Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
Definition: PlaneGeo.h:106
ROOT::Math::Transform3D TransformationMatrix
Type of transformation matrix used in geometry.
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:229
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h:378
geo::PlaneGeo::Rect activeArea
Result.
Definition: PlaneGeo.cxx:106
PlaneGeo(TGeoNode const &node, geo::TransformationMatrix &&trans, WireCollection_t &&wires)
Construct a representation of a single plane of the detector.
Definition: PlaneGeo.cxx:399
void SetMainDir(Vector_t const &dir)
Change the main direction of the projection base.
Definition: Decomposer.h:438
geo::Point_t Center() const
Returns the center point of the box.
ROOT::Math::PositionVector2D< ROOT::Math::Cartesian2D< double >, geo::PlaneGeo::WidthDepthReferenceTag > Projection_t
Definition: PlaneGeo.cxx:92