16 #include "cetlib/pow.h" 17 #include "cetlib_except/exception.h" 23 #include "TGeoManager.h" 24 #include "TGeoMatrix.h" 35 #include <type_traits> 42 T symmetricCapDelta(T
value, T limit)
44 return (value < -limit) ? -limit - value : (value > +limit) ? +limit - value : 0.0;
60 struct ActiveAreaCalculator {
62 ActiveAreaCalculator(
PlaneGeo const& plane,
double margin)
63 : plane(plane), wMargin(margin), dMargin(margin)
69 using Projection_t = ROOT::Math::PositionVector2D<ROOT::Math::Cartesian2D<double>,
74 "Necessary maintenance: remove the now optional conversions");
76 static constexpr std::size_t kFirstWireStart = 0;
77 static constexpr std::size_t kFirstWireEnd = 1;
78 static constexpr std::size_t kLastWireStart = 2;
79 static constexpr std::size_t kLastWireEnd = 3;
87 Projection_t wireEnds[4];
89 void initializeWireEnds()
97 auto project = [](
auto v) -> Projection_t {
return {v.X(), v.Y()}; };
99 wireEnds[kFirstWireStart] =
101 wireEnds[kFirstWireEnd] =
103 if (wireEnds[kFirstWireStart].
X() > wireEnds[kFirstWireEnd].
X())
104 std::swap(wireEnds[kFirstWireStart], wireEnds[kFirstWireEnd]);
105 wireEnds[kLastWireStart] =
108 if (wireEnds[kLastWireStart].
X() > wireEnds[kLastWireEnd].
X())
109 std::swap(wireEnds[kLastWireStart], wireEnds[kLastWireEnd]);
112 void includeAllWireEnds()
119 for (
auto const& aWireEnd : wireEnds) {
131 Vector_t const widthDir = {1.0, 0.0};
132 Vector_t const depthDir = {0.0, 1.0};
134 double const hp = plane.
WirePitch() / 2.0;
148 double const cosAngleWidth =
vect::dot(wireCoordDir, widthDir);
149 double const cosAngleDepth =
vect::dot(wireCoordDir, depthDir);
151 bool const bPositiveAngle = none_or_both((wireCoordDir.X() >= 0), (wireCoordDir.Y() >= 0));
156 if (cosAngleWidth < 0) wireCoordDir = -wireCoordDir;
159 assert(wireEnds[kFirstWireEnd].
X() >= wireEnds[kFirstWireStart].
X());
160 bool const bAlongWidth
161 = equal(wireEnds[kFirstWireEnd].
X(), activeArea.
width.
upper) &&
162 equal(wireEnds[kFirstWireStart].
X(), activeArea.
width.
lower);
163 bool const bAlongDepth =
165 equal(std::max(wireEnds[kFirstWireStart].
Y(), wireEnds[kFirstWireEnd].
Y()),
167 equal(std::min(wireEnds[kFirstWireStart].
Y(), wireEnds[kFirstWireEnd].
Y()),
169 assert(!(bAlongWidth && bAlongDepth));
180 std::size_t
const iUpperWire = (cosAngleDepth > 0) ? kLastWireStart : kFirstWireStart;
182 double const maxUpperDistance =
184 std::min(wireEnds[iUpperWire].
Y(), wireEnds[iUpperWire ^ 0
x1].
Y());
187 activeArea.
depth.
upper += (hp - maxUpperDistance);
193 std::size_t
const iLowerWire = (cosAngleDepth > 0) ? kFirstWireStart : kLastWireStart;
195 double const maxLowerDistance =
196 std::max(wireEnds[iLowerWire].
Y(), wireEnds[iLowerWire ^ 0
x1].
Y()) -
199 activeArea.
depth.
lower -= (hp - maxLowerDistance);
201 else if (bAlongDepth) {
213 std::size_t
const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
215 double const maxUpperDistance =
217 std::min(wireEnds[iUpperWire].
X(), wireEnds[iUpperWire ^ 0
x1].
X());
219 activeArea.
width.
upper += (hp - maxUpperDistance);
228 std::size_t
const iLowerWire = (cosAngleWidth > 0) ? kFirstWireStart : kLastWireStart;
230 double const maxLowerDistance =
231 std::max(wireEnds[iLowerWire].
X(), wireEnds[iLowerWire ^ 0
x1].
X()) -
234 activeArea.
width.
lower -= (hp - maxLowerDistance);
237 else if (bPositiveAngle) {
246 std::size_t
const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
248 double const upperDistance =
251 auto const upperDelta = (hp - upperDistance) * wireCoordDir;
260 std::size_t
const iLowerWire = (cosAngleWidth > 0) ? kFirstWireEnd : kLastWireEnd;
262 double const lowerDistance =
265 auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
277 std::size_t
const iUpperWire = (cosAngleWidth > 0) ? kLastWireStart : kFirstWireStart;
279 double const upperDistance =
282 auto const upperDelta = (hp - upperDistance) * wireCoordDir;
291 std::size_t
const iLowerWire = (cosAngleWidth > 0) ? kFirstWireEnd : kLastWireEnd;
293 double const lowerDistance =
296 auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
306 if (wMargin != 0.0) {
310 if (dMargin != 0.0) {
321 initializeWireEnds();
324 includeAllWireEnds();
336 static bool none_or_both(
bool a,
bool b) {
return a == b; }
339 template <
typename T>
340 static bool equal(T a, T b, T tol = T(1
e-5))
354 : fNode(node), fTrans(
std::move(trans)), fWire(
std::move(wires))
356 if (!
fNode->GetVolume()) {
358 <<
"Plane geometry node " <<
fNode->IsA()->GetName() <<
"[" <<
fNode->GetName() <<
", #" 359 <<
fNode->GetNumber() <<
"] has no volume!\n";
376 TGeoBBox
const* pShape =
dynamic_cast<TGeoBBox const*
>(
Volume().GetShape());
379 <<
"BoundingBox(): volume " <<
Volume().IsA()->GetName() <<
" is not a TGeoBBox!";
383 unsigned int points = 0;
384 for (
double dx : {-(pShape->GetDX()), +(pShape->GetDX())}) {
385 for (
double dy : {-(pShape->GetDY()), +(pShape->GetDY())}) {
386 for (
double dz : {-(pShape->GetDZ()), +(pShape->GetDZ())}) {
406 throw cet::exception(
"WireOutOfRange") <<
"Request for non-existant wire " << iwire <<
"\n";
423 unsigned int verbosity )
const 425 std::ostringstream sstr;
433 double dMargin)
const 443 double dMargin)
const 452 return (deltaProj.X() == 0.) && (deltaProj.Y() == 0.);
462 return {(delta.X() == 0.0) ?
496 if ((nearestWireNo < 0) || ((
unsigned int)nearestWireNo >=
Nwires())) {
498 auto wireNo = nearestWireNo;
500 if (nearestWireNo < 0)
506 <<
"Can't find nearest wire for position " << pos <<
" in plane " << std::string(
ID())
507 <<
" approx wire number # " << wireNo <<
" (capped from " << nearestWireNo <<
")\n";
521 if (wireID)
return Wire(wireID);
526 <<
"Can't find nearest wire for position " << point <<
" in plane " << std::string(
ID())
527 <<
" approx wire number # " << closestID.
Wire <<
" (capped from " << wireID.
Wire <<
")\n";
534 return std::sqrt(cet::square(projDir.X() / projDir.Y()) + 1.0) *
fWirePitch;
541 double const r = dir.R();
568 for (
auto& wire :
fWire) {
592 case k3D:
return "3D";
594 default:
return "<UNSUPPORTED (" +
std::to_string((
int)view) +
")>";
601 switch (orientation) {
603 case kVertical:
return "vertical";
break;
604 default:
return "unexpected";
break;
623 TGeoBBox
const* pShape =
dynamic_cast<TGeoBBox const*
>(
Volume().GetShape());
626 <<
" is not a TGeoBBox! Dimensions won't be available.";
635 std::array<Vector_t, 3U> sides;
636 size_t iSmallest = 3;
645 if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
649 if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
657 for (
size_t i = 0; i < 3; ++i)
658 if (i != iSmallest) kept[iKept++] = i;
664 size_t const iiWidth =
666 size_t const iWidth = kept[iiWidth];
667 size_t const iDepth = kept[1 - iiWidth];
678 unsigned const int NWires =
Nwires();
679 if (NWires < 2)
return {};
700 if (
fWire.size() < 2) {
703 <<
"PlaneGeo::UpdateOrientation(): only " <<
fWire.size() <<
" wires!\n";
716 <<
"Plane with unsupported orientation (normal: " << normal <<
")\n";
727 auto const iWire =
Nwires() / 2;
775 if (
std::abs(normalDir.Y()) != 1.0) {
790 else if ((ynw * yw) < 0)
792 else if ((ynw * yw) > 0)
815 else if ((znw * zw) < 0)
817 else if ((znw * zw) > 0)
863 auto refWireNo =
Nwires() / 2;
864 if (refWireNo ==
Nwires() - 1) --refWireNo;
865 auto const& refWire =
Wire(refWireNo);
866 auto const& WireDir = refWire.Direction();
872 auto toNextWire =
Wire(refWireNo + 1).
GetCenter() - refWire.GetCenter();
875 if (wireCoordDir.Dot(toNextWire) < 0) { wireCoordDir = -wireCoordDir; }
892 if (
fWire.empty()) {
return; }
898 auto firstWire =
fWire.cbegin(), wire = firstWire, wend =
fWire.cend();
901 while (++wire != wend) {
903 if (wirePitch < 1
e-4)
continue;
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...
Vector_t GetNormalAxis() const
Returns a direction normal to the plane (pointing is not defined).
TGeoNode const * fNode
Node within full geometry.
auto VectorSecondaryComponent(Vector_t const &v) const
Returns the secondary component of a vector.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthDisplacement_t
Type for vector projections in the plane frame base representation.
Point_t const & GetCenter() const
Returns the world coordinate of the center of the wire [cm].
BoxBoundedGeo BoundingBox() const
std::string PlaneInfo(std::string indent="", unsigned int verbosity=1) const
Returns a string with plane information.
void UpdateIncreasingWireDir()
Updates the cached direction to increasing wires.
double fWirePitch
Pitch of wires in this plane.
TGeoVolume const & Volume() const
void SetSecondaryDir(Vector_t const &dir)
Change the secondary direction of the projection base.
static std::string ViewName(View_t view)
Returns the name of the specified view.
void UpdateWirePitch()
Updates the stored wire pitch.
void UpdateWidthDepthDir()
Updates the cached depth and width direction.
Point_t Center() const
Returns the center point of the box.
Vector_t const & DepthDir() const
Return the direction of plane depth.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Point_t const & GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
lar::util::simple_geo::Rectangle< double > Rect
Type for description of rectangles.
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Vector_t const & NormalDir() const
Returns the plane normal axis direction.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
WireID NearestWireID(Point_t const &pos) const
Returns the ID of wire closest to the specified position.
auto mixedProduct(Vector const &a, Vector const &b, Vector const &c)
enum geo::_plane_orient Orient_t
Enumerate the possible plane projections.
Float_t x1[n_points_granero]
Provides simple real number checks.
void UpdateOrientation()
Updates plane orientation.
void UpdateAfterSorting(PlaneID planeid, BoxBoundedGeo const &TPCbox)
Performs all needed updates after the TPC has sorted the planes.
Planes which measure X direction.
The data type to uniquely identify a Plane.
void extendToInclude(Data_t)
Extends the range to include the specified point.
Point_t fCenter
Center of the plane, lying on the wire plane.
constexpr Vector Yaxis()
Returns a y axis vector of the specified type.
bool isProjectionOnPlane(Point_t const &point) const
Returns if the projection of specified point is within the plane.
constexpr auto abs(T v)
Returns the absolute value of the argument.
Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local plane frame to world frame.
WireGeo const & Wire(unsigned int iwire) const
Planes which measure Z direction.
double DistanceFromPlane(Point_t const &point) const
Returns the distance of the specified point from the wire plane.
WireID_t Wire
Index of the wire within its plane.
PlaneID fID
ID of this plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
void round0(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
WidthDepthProjection_t VectorWidthDepthProjection(Vector_t const &v) const
Returns the projection of the specified vector on the plane.
Point_t GetStart() const
Returns the world coordinate of one end of the wire [cm].
Point_t GetEnd() const
Returns the world coordinate of one end of the wire [cm].
void UpdatePlaneNormal(BoxBoundedGeo const &TPCbox)
Updates the cached normal to plane versor; needs the TPC box coordinates.
WidthDepthProjection_t MoveProjectionToPlane(WidthDepthProjection_t const &proj) const
Returns the projection, moved onto the plane if necessary.
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
Class for approximate comparisons.
Planes which measure Y direction.
void DetectGeometryDirections()
Sets the geometry directions.
WireGeo const & NearestWire(Point_t const &pos) const
Returns the wire closest to the specified position.
double InterWireProjectedDistance(WireCoordProjection_t const &projDir) const
Returns the distance between wires along the specified direction.
Rect fActiveArea
Area covered by wires in frame base.
void DriftPoint(Point_t &position, double distance) const
Shifts the position of an electron drifted by a distance.
3-dimensional objects, potentially hits, clusters, prongs, etc.
double ThetaZ() const
Angle of the wires from positive z axis; .
Planes that are in the horizontal plane.
Collection of exceptions for Geometry system.
Point_t GetBoxCenter() const
Returns the centre of the box representing the plane.
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object.
double InterWireDistance(Vector_t const &dir) const
Returns the distance between wires along the specified direction.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
WidthDepthDecomposer_t fDecompFrame
std::function< bool(T const &, T const &)> Compare
void UpdatePhiZ()
Updates the stored .
Vector_t Direction() const
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
Planes that are in the vertical plane (e.g. ArgoNeuT).
Vector_t const & GetWireDirection() const
Returns the direction of the wires.
WireCollection_t fWire
List of wires in this plane.
std::string indent(std::size_t const i)
WidthDepthProjection_t PointWidthDepthProjection(Point_t const &point) const
Returns the projection of the specified point on the plane.
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Utilities to extend the interface of geometry vectors.This library provides facilities that can be us...
std::vector< WireGeo > WireCollection_t
WireGeo const & FirstWire() const
Return the first wire in the plane.
constexpr Vector Xaxis()
Returns a x axis vector of the specified type.
void SortWires(Compare< WireGeo > cmp)
Apply sorting to WireGeo objects.
Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WireCoordinateReferenceTag > WireCoordProjection_t
Type for projections in the wire base representation.
Class comparing 2D vectors.
Range_t width
Range along width direction.
void UpdateWirePitchSlow()
Updates the stored wire pitch with a slower, more robust algorithm.
constexpr auto dot(Vector const &a, OtherVector const &b)
Return cross product of two vectors.
void SetView(View_t view)
Set the signal view (for TPCGeo).
void UpdateView()
Updates the stored view.
static std::string OrientationName(Orient_t orientation)
Returns the name of the specified orientation.
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
PlaneGeo(TGeoNode const *node, TransformationMatrix &&trans, WireCollection_t &&wires)
Construct a representation of a single plane of the detector.
Encapsulate the geometry of a wire .
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthProjection_t
constexpr Vector Zaxis()
Returns a z axis vector of the specified type.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Range_t depth
Range along depth direction.
Tag for plane frame base vectors.
void SetOrigin(Point_t const &point)
Change the 3D point of the reference frame origin.
Vector_t const & SecondaryDir() const
Returns the plane secondary axis direction.
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 ...
Data_t delta(Data_t v, Data_t margin=0.0) const
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 ...
WireID ClosestWireID(WireID::WireID_t wireNo) const
Returns the closest valid wire ID to the specified wire.
Vector3DBase_t< PlaneGeoCoordinatesTag > LocalVector_t
Type of displacement vectors in the local GDML wire plane frame.
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
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.
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.
auto WirePtr(unsigned int iwire) const
Returns the wire number iwire from this plane.
constexpr bool nonNegative(Value_t value) const
Returns whether value is larger than or equal() to zero.
Vector_t const & WidthDir() const
Return the direction of plane width.
WireGeo const & LastWire() const
Return the last wire in the plane.
unsigned int Nwires() const
Number of wires in this plane.
bool WireIDincreasesWithZ() const
Returns whether the higher z wires have higher wire ID.
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 .
Data_t upper
Ending coordinate.
Vector_t const & GetIncreasingWireDirection() const
Returns the direction of increasing wires.
Exception thrown on invalid wire number.
Vector_t const & GetNormalDirection() const
Returns the direction normal to the plane.
static double WirePitch(WireGeo const &w1, WireGeo const &w2)
Returns the pitch (distance on y/z plane) between two wires, in cm.
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
unsigned int WireID_t
Type for the ID number.
void UpdateWirePlaneCenter()
Updates the stored wire plane center.
bool shouldFlipWire(WireGeo const &wire) const
Whether the specified wire should have start and end swapped.
WireDecomposer_t fDecompWire
void UpdateDecompWireOrigin()
Updates the position of the wire coordinate decomposition.
void UpdateActiveArea()
Updates the internally used active area.
Collection of Physical constants used in LArSoft.
Point_t MovePointOverPlane(Point_t const &point) const
Returns the point, moved so that its projection is over the plane.
Data_t lower
Starting coordinate.
Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
PlaneID const & ID() const
Returns the identifier of this plane.
Orient_t fOrientation
Is the plane vertical or horizontal?
void UpdateWireDir()
Updates the cached direction to wire.
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.
cet::coded_exception< error, detail::translate > exception
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
void SetMainDir(Vector_t const &dir)
Change the main direction of the projection base.