20 #include "cetlib_except/exception.h" 25 #include "TGeoManager.h" 28 #include "TGeoMatrix.h" 35 #include <type_traits> 43 T symmetricCapDelta(T
value, T limit) {
45 return (value < -limit)
57 T symmetricCap(T value, T limit) {
59 return value + symmetricCapDelta(value, limit);
108 "Necessary maintenance: remove the now optional conversions" 117 double const wMargin = 0.0;
118 double const dMargin = 0.0;
140 if (wireEnds[kFirstWireStart].
X() > wireEnds[kFirstWireEnd].
X())
141 std::swap(wireEnds[kFirstWireStart], wireEnds[kFirstWireEnd]);
146 if (wireEnds[kLastWireStart].
X() > wireEnds[kLastWireEnd].
X())
147 std::swap(wireEnds[kLastWireStart], wireEnds[kLastWireEnd]);
157 for (
auto const& aWireEnd: wireEnds) {
171 Vector_t const widthDir = { 1.0, 0.0 };
172 Vector_t const depthDir = { 0.0, 1.0 };
175 double const hp = plane.
WirePitch() / 2.0;
193 double const cosAngleWidth =
geo::vect::dot(wireCoordDir, widthDir);
194 double const cosAngleDepth =
geo::vect::dot(wireCoordDir, depthDir);
196 bool const bPositiveAngle
197 =
none_or_both((wireCoordDir.X() >= 0), (wireCoordDir.Y() >= 0));
202 if (cosAngleWidth < 0) wireCoordDir = -wireCoordDir;
205 assert(wireEnds[kFirstWireEnd].
X() >= wireEnds[kFirstWireStart].
X());
206 bool const bAlongWidth
209 bool const bAlongDepth = !bAlongWidth &&
212 assert(!(bAlongWidth && bAlongDepth));
224 std::size_t
const iUpperWire
225 = (cosAngleDepth > 0)? kLastWireStart: kFirstWireStart;
227 double const maxUpperDistance = activeArea.
depth.
upper 229 (wireEnds[iUpperWire].
Y(), wireEnds[iUpperWire ^ 0
x1].
Y())
233 activeArea.
depth.
upper += (hp - maxUpperDistance);
239 std::size_t
const iLowerWire
240 = (cosAngleDepth > 0)? kFirstWireStart: kLastWireStart;
242 double const maxLowerDistance
244 (wireEnds[iLowerWire].
Y(), wireEnds[iLowerWire ^ 0
x1].
Y())
248 activeArea.
depth.
lower -= (hp - maxLowerDistance);
251 else if (bAlongDepth) {
264 std::size_t
const iUpperWire
265 = (cosAngleWidth > 0)? kLastWireStart: kFirstWireStart;
267 double const maxUpperDistance = activeArea.
width.
upper 269 (wireEnds[iUpperWire].
X(), wireEnds[iUpperWire ^ 0
x1].
X())
272 activeArea.
width.
upper += (hp - maxUpperDistance);
281 std::size_t
const iLowerWire
282 = (cosAngleWidth > 0)? kFirstWireStart: kLastWireStart;
284 double const maxLowerDistance
286 (wireEnds[iLowerWire].
X(), wireEnds[iLowerWire ^ 0
x1].
X())
290 activeArea.
width.
lower -= (hp - maxLowerDistance);
293 else if (bPositiveAngle) {
302 std::size_t
const iUpperWire
303 = (cosAngleWidth > 0)? kLastWireStart: kFirstWireStart;
310 auto const upperDelta = (hp - upperDistance) * wireCoordDir;
320 std::size_t
const iLowerWire
321 = (cosAngleWidth > 0)? kFirstWireEnd: kLastWireEnd;
328 auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
342 std::size_t
const iUpperWire
343 = (cosAngleWidth > 0)? kLastWireStart: kFirstWireStart;
350 auto const upperDelta = (hp - upperDistance) * wireCoordDir;
360 std::size_t
const iLowerWire
361 = (cosAngleWidth > 0)? kFirstWireEnd: kLastWireEnd;
368 auto const lowerDelta = (hp - lowerDistance) * wireCoordDir;
379 if (wMargin != 0.0) {
383 if (dMargin != 0.0) {
421 template <
typename T>
422 static bool equal(T a, T b, T tol = T(1
e-5))
423 {
return std::abs(a - b) <= tol; }
436 : fTrans(path, depth)
437 , fVolume(path[depth]->GetVolume())
447 assert(depth < path.size());
450 TGeoNode
const* pNode = path[depth];
452 <<
"Plane geometry node " << pNode->IsA()->GetName()
453 <<
"[" << pNode->GetName() <<
", #" << pNode->GetNumber()
454 <<
"] has no volume!\n";
475 TGeoBBox
const* pShape =
dynamic_cast<TGeoBBox const*
>(
fVolume->GetShape());
478 <<
"BoundingBox(): volume " <<
fVolume->IsA()->GetName()
479 <<
"['" <<
fVolume->GetName() <<
"'] has a shape which is a " 480 << pShape->IsA()->GetName()
481 <<
", not a TGeoBBox!";
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()) }) {
510 <<
"Request for non-existant wire " << iwire <<
"\n";
520 const char* wireLabel =
"volTPCWire";
521 auto const labelLength = strlen(wireLabel);
522 if(strncmp(path[depth]->GetName(), wireLabel, labelLength) == 0){
528 unsigned int deeper = depth+1;
529 if (deeper>=path.size()) {
530 throw cet::exception(
"ExceededMaxDepth") <<
"Exceeded maximum depth\n";
532 const TGeoVolume* v = path[depth]->GetVolume();
533 int nd = v->GetNdaughters();
534 for (
int i=0; i<nd; ++i) {
535 path[deeper] = v->GetNode(i);
544 fWire.emplace_back(path, depth);
569 std::array<double, 3> A,
B;
574 return { A.data(), B.data() };
610 return (deltaProj.X() == 0.) && (deltaProj.Y() == 0.);
667 return point + deltaProj.X() * WidthDir<geo::Vector_t>() + deltaProj.Y() * DepthDir<geo::Vector_t>();
686 if ((nearestWireNo < 0) || ((
unsigned int) nearestWireNo >=
Nwires())) {
688 auto wireNo = nearestWireNo;
690 if (nearestWireNo < 0 ) wireNo = 0;
691 else wireNo =
Nwires() - 1;
694 <<
"Can't find nearest wire for position " << pos
695 <<
" in plane " << std::string(
ID()) <<
" approx wire number # " 696 << wireNo <<
" (capped from " << nearestWireNo <<
")\n";
715 if (wireID)
return Wire(wireID);
720 <<
"Can't find nearest wire for position " << point
721 <<
" in plane " << std::string(
ID()) <<
" approx wire number # " 722 << closestID.
Wire <<
" (capped from " << wireID.
Wire <<
")\n";
746 for (
auto& wire:
fWire) {
781 switch (orientation) {
784 default:
return "unexpected";
break;
809 TGeoBBox
const* pShape =
dynamic_cast<TGeoBBox const*
>(
fVolume->GetShape());
812 <<
"Volume " <<
fVolume->IsA()->GetName() <<
"['" <<
fVolume->GetName()
813 <<
"'] has a shape which is a " << pShape->IsA()->GetName()
814 <<
", not a TGeoBBox! Dimensions won't be available.";
823 std::array<geo::Vector_t, 3U> sides;
824 size_t iSmallest = 3;
835 if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
839 if (sides[iSide].Mag2() < sides[iSmallest].Mag2()) iSmallest = iSide;
850 for (
size_t i = 0; i < 3; ++i)
if (i != iSmallest) kept[iKept++] = i;
858 size_t const iiWidth =
859 std::abs(sides[kept[0]].Unit().
Z()) > std::abs(sides[kept[1]].Unit().
Z())
861 size_t const iWidth = kept[iiWidth];
862 size_t const iDepth = kept[1 - iiWidth];
874 const unsigned int NWires =
Nwires();
875 if (NWires < 2)
return {};
901 if (
fWire.size() < 2) {
904 <<
"PlaneGeo::UpdateOrientation(): only " <<
fWire.size()
908 auto normal = GetNormalDirection<geo::Vector_t>();
910 if (std::abs(std::abs(normal.X()) - 1.) < 1
e-3)
912 else if (std::abs(std::abs(normal.Y()) - 1.) < 1
e-3)
919 <<
"Plane with unsupported orientation (normal: " << normal <<
")\n";
980 auto const& normalDir = GetNormalDirection<geo::Vector_t>();
981 auto const& wireDir = GetWireDirection<geo::Vector_t>();
984 if (std::abs(normalDir.Y()) != 1.0) {
995 if (std::abs(yw) < 1.0
e-4) {
996 double const closeToX
998 double const closeToZ
1002 else if (std::abs(ynw) < 1.0
e-4) {
1023 if (std::abs(zw) < 1.0
e-4) {
1027 else if (std::abs(znw) < 1.0
e-4) {
1051 auto const towardCenter
1092 auto refWireNo =
Nwires() / 2;
1093 if (refWireNo ==
Nwires() - 1) --refWireNo;
1094 auto const& refWire =
Wire(refWireNo);
1100 auto wireCoordDir = GetNormalDirection<geo::Vector_t>().Cross(WireDir).Unit();
1107 if (wireCoordDir.Dot(toNextWire) < 0) {
1108 wireCoordDir = -wireCoordDir;
1139 auto firstWire =
fWire.cbegin(), wire = firstWire, wend =
fWire.cend();
1142 while (++wire != wend) {
1144 if (wirePitch < 1
e-4)
continue;
1195 fCenter = GetBoxCenter<geo::Point_t>();
static std::string OrientationName(geo::Orient_t orientation)
Returns the name of the specified orientation.
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
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
void initializeWireEnds()
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
void SetView(geo::View_t view)
Set the signal view (for TPCGeo).
WidthDepthProjection_t VectorWidthDepthProjection(geo::Vector_t const &v) const
Returns the projection of the specified vector on the plane.
geo::Point_t fCenter
Center of the plane, lying on the wire plane.
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.
void UpdateIncreasingWireDir()
Updates the cached direction to increasing wires.
double fWirePitch
Pitch of wires in this plane.
void SetSecondaryDir(Vector_t const &dir)
Change the secondary direction of the projection base.
void UpdateWirePitch()
Updates the stored wire pitch.
void UpdateWidthDepthDir()
Updates the cached depth and width direction.
double const dMargin
Margin subtracted from each side of depth.
static bool none_or_both(bool a, bool b)
Returns true if a and b are both true or both false (exclusive nor).
lar::util::simple_geo::Rectangle< double > Rect
Type for description of rectangles.
Vector_t const & NormalDir() const
Returns the plane normal axis direction.
WireGeo const & Wire(unsigned int iwire) const
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
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]
void MakeWire(GeoNodePath_t &path, size_t depth)
void UpdateOrientation()
Updates plane orientation.
geo::PlaneID fID
ID of this plane.
Planes which measure X direction.
The data type to uniquely identify a Plane.
Silly utility to sort vectors indirectly.
void extendToInclude(Data_t)
Extends the range to include the specified point.
Volume delimited by two points.
constexpr Vector Yaxis()
Returns a y axis vector of the specified type.
geo::PlaneGeo::WidthDepthDisplacement_t Vector_t
::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.
bool isProjectionOnPlane(geo::Point_t const &point) const
Returns if the projection of specified point is within the plane.
::geo::Vector_t toVector(Vector const &v)
Convert the specified vector into a geo::Vector_t.
static constexpr std::size_t kLastWireStart
WidthDepthProjection_t PointWidthDepthProjection(geo::Point_t const &point) const
Returns the projection of the specified point on the plane.
static constexpr std::size_t kFirstWireStart
Planes which measure Z direction.
geo::WireGeo const & NearestWire(geo::Point_t const &pos) const
Returns the wire closest to the specified position.
WireID_t Wire
Index of the wire within its plane.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool shouldFlipWire(geo::WireGeo const &wire) const
Whether the specified wire should have start and end swapped.
Vector GetNormalDirection() const
Returns the direction normal to the plane.
static double WirePitch(geo::WireGeo const &w1, geo::WireGeo const &w2)
Returns the pitch (distance on y/z plane) between two wires, in cm.
PlaneGeo const & plane
Plane to work on.
void FindWire(GeoNodePath_t &path, size_t depth)
WidthDepthProjection_t MoveProjectionToPlane(WidthDepthProjection_t const &proj) const
Returns the projection, moved onto the plane if necessary.
Vector GetIncreasingWireDirection() const
Returns the direction of increasing wires.
double ThetaZ() const
Returns angle of wire with respect to z axis in the Y-Z plane in radians.
geo::BoxBoundedGeo BoundingBox() const
Class for approximate comparisons.
Planes which measure Y direction.
void DetectGeometryDirections()
Sets the geometry directions.
Projection_t wireEnds[4]
Cache: wire end projections.
void DriftPoint(geo::Point_t &position, double distance) const
Shifts the position of an electron drifted by a distance.
Rect fActiveArea
Area covered by wires in frame base.
geo::PlaneGeo::Rect recomputeArea()
3-dimensional objects, potentially hits, clusters, prongs, etc.
double ThetaZ() const
Angle of the wires from positive z axis; .
void UpdatePlaneNormal(geo::BoxBoundedGeo const &TPCbox)
Updates the cached normal to plane versor; needs the TPC box coordinates.
TGeoVolume const * fVolume
Plane volume description.
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthProjection_t
Planes that are in the horizontal plane.
Collection of exceptions for Geometry system.
lar::util::simple_geo::Volume Coverage() const
Returns a volume including all the wires in the plane.
void SortByPointers(Coll &coll, Sorter sorter)
Applies sorting indirectly, minimizing data copy.
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.
WidthDepthDecomposer_t fDecompFrame
void UpdatePhiZ()
Updates the stored .
Planes that are in the vertical plane (e.g. ArgoNeuT).
geo::Point_t toWorldCoords(LocalPoint_t const &local) const
Transform point from local plane frame to world frame.
WireCollection_t fWire
List of wires in this plane.
geo::Point_t MovePointOverPlane(geo::Point_t const &point) const
Returns the point, moved so that its projection is over the plane.
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
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.
constexpr Vector Xaxis()
Returns a x axis vector of the specified type.
Range_t width
Range along width direction.
void UpdateWirePitchSlow()
Updates the stored wire pitch with a slower, more robust algorithm.
const WireGeo & FirstWire() const
Return the first wire in the plane.
void UpdateAfterSorting(geo::PlaneID planeid, geo::BoxBoundedGeo const &TPCbox)
Performs all needed updates after the TPC has sorted the planes.
virtual void SortWires(std::vector< geo::WireGeo * > &wgeo) const =0
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double >, WidthDepthReferenceTag > WidthDepthDisplacement_t
Type for vector projections in the plane frame base representation.
static constexpr std::size_t kLastWireEnd
std::vector< TGeoNode const * > GeoNodePath_t
void UpdateView()
Updates the stored view.
Vector Direction() const
Returns the wire direction as a norm-one vector.
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
Encapsulate the geometry of a wire.
Vector DepthDir() const
Return the direction of plane depth.
constexpr Vector Zaxis()
Returns a z axis vector of the specified type.
unsigned int WireID_t
Type for the ID number.
Range_t depth
Range along depth direction.
Tag for plane frame base vectors.
ActiveAreaCalculator(geo::PlaneGeo const &plane, double margin=0.0)
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.
std::string value(boost::any const &)
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 ...
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
geo::Vector_t GetNormalAxis() const
Returns a direction normal to the plane (pointing is not defined).
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Encapsulate the construction of a single detector plane.
double DistanceFromPlane(geo::Point_t const &point) const
Returns the distance of the specified point from the wire 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.
void GetEnd(double *xyz) const
geo::PlaneID const & ID() const
Returns the identifier of this plane.
double const wMargin
Margin subtracted from each side of width.
WireGeo const * WirePtr(unsigned int iwire) const
Returns the wire number iwire from this plane.
ActiveAreaCalculator(geo::PlaneGeo const &plane, double wMargin, double dMargin)
unsigned int Nwires() const
Number of wires in this plane.
geo::WireID ClosestWireID(geo::WireID::WireID_t wireNo) const
Returns the closest valid wire ID to the specified wire.
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 WidthDir() const
Return the direction of plane width.
Exception thrown on invalid wire number.
static constexpr std::size_t kFirstWireEnd
void UpdateWirePlaneCenter()
Updates the stored wire plane center.
WireDecomposer_t fDecompWire
static bool equal(T a, T b, T tol=T(1e-5))
Returns whether the two numbers are the same, lest a tolerance.
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
double WireCoordinate(Point const &point) const
Returns the coordinate of the point on the plane, in wire units.
void UpdateDecompWireOrigin()
Updates the position of the wire coordinate decomposition.
Class computing the active area of the plane.
void UpdateActiveArea()
Updates the internally used active area.
void includeAllWireEnds()
geo::Vector3DBase_t< PlaneGeoCoordinatesTag > LocalVector_t
Type of displacement vectors in the local GDML wire plane frame.
Data_t lower
Starting coordinate.
const WireGeo & LastWire() const
Return the last wire in the plane.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Namespace collecting geometry-related classes utilities.
void SortWires(geo::GeoObjectSorter const &sorter)
Apply sorting to WireGeo objects.
PlaneGeo(GeoNodePath_t &path, size_t depth)
Construct a representation of a single plane of the detector.
Orient_t fOrientation
Is the plane vertical or horizontal?
ROOT::Math::PositionVector2D< ROOT::Math::Cartesian2D< double >, geo::PlaneGeo::WidthDepthReferenceTag > Projection_t
void UpdateWireDir()
Updates the cached direction to wire.
geo::Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
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.
geo::PlaneGeo::Rect activeArea
Result.
void SetMainDir(Vector_t const &dir)
Change the main direction of the projection base.
geo::Point_t Center() const
Returns the center point of the box.