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