20 #include "cetlib/pow.h" 32 fNPlanes = wireReadoutGeom.Nplanes();
34 for (
unsigned int ip = 0; ip <
fNPlanes; ip++) {
36 vertangle[ip] = wireReadoutGeom.Wire(wid).ThetaZ(
false) - TMath::Pi() / 2.;
63 double ln(0), mn(0), nn(0);
64 double phis(0), thetan(0);
69 unsigned int Cplane = 0, Iplane = 1;
73 double angleC, angleI, slopeC, slopeI, omegaC, omegaI;
79 if (omega0 == 0 || omega1 == 0) {
88 double alt_backwards = 0;
90 if (std::fabs(omega0) > (TMath::Pi() / 2.0) || std::fabs(omega1) > (TMath::Pi() / 2.0)) {
128 slopeC = std::tan(omegaC);
129 slopeI = std::tan(omegaI);
137 if (omegaC < TMath::Pi() && omegaC > 0)
143 mn = (ln / (2 * std::sin(angleI))) *
144 ((std::cos(angleI) / (slopeC * std::cos(angleC))) - (1 / slopeI) +
145 nfact * (std::cos(angleI) / (std::cos(angleC) * slopeC) - 1 / slopeI));
147 nn = (ln / (2 * std::cos(angleC))) *
148 ((1 / slopeC) + (1 / slopeI) + nfact * ((1 / slopeC) - (1 / slopeI)));
151 if (std::fabs(omegaC) > 0.01)
154 phis = std::asin(ln / TMath::Sqrt(ln * ln + nn * nn));
156 if (std::fabs(slopeC + slopeI) < 0.001)
158 else if (std::fabs(omegaI) > 0.01 &&
159 (omegaI / std::fabs(omegaI) == -omegaC / std::fabs(omegaC)) &&
160 (std::fabs(omegaC) < 1 * TMath::Pi() / 180 ||
161 std::fabs(omegaC) > 179 * TMath::Pi() / 180))
162 phis = (std::fabs(omegaC) > TMath::Pi() / 2) ? TMath::Pi() : 0;
164 if (nn < 0 && phis > 0 &&
168 phis = (TMath::Pi()) - phis;
169 else if (nn < 0 && phis < 0 && !(!alt_backwards && std::fabs(phis) < TMath::Pi() / 4))
170 phis = (-TMath::Pi()) - phis;
172 phi = phis * 180 / TMath::Pi();
180 thetan = -std::asin(mn / std::hypot(ln, mn, nn));
181 theta = thetan * 180 / TMath::Pi();
196 double splane, lplane;
199 if (dw0 == 0 && dw1 == 0)
return -1;
218 double tantheta = top / bottom;
232 mf::LogError(Form(
"Warning : no Pitch foreseen for view %d", plane.View()));
236 double const pi = TMath::Pi();
237 double const fTheta = pi / 2 - theta;
238 double const fPhi = -(phi + pi / 2);
240 double wirePitch = plane.WirePitch();
243 double cosgamma =
std::abs(std::sin(angleToVert) * std::cos(fTheta) +
244 std::cos(angleToVert) * std::sin(fTheta) * std::sin(fPhi));
246 return cosgamma > 0 ? wirePitch / cosgamma : -1.;
257 mf::LogError(Form(
"Warning : no Pitch foreseen for view %d", plane.View()));
261 double const fTheta = theta;
262 double const fPhi = phi;
264 double wirePitch = plane.WirePitch();
267 double cosgamma =
std::abs(std::sin(angleToVert) * std::cos(fTheta) +
268 std::cos(angleToVert) * std::sin(fTheta) * std::sin(fPhi));
270 return cosgamma > 0 ? wirePitch / cosgamma : -1.;
280 double timestart)
const 293 return Get2Dslope(endpoint->
w - startpoint->
w, endpoint->
t - startpoint->
t);
313 double timestart)
const 325 return Get2Dangle(endpoint->
w - startpoint->
w, endpoint->
t - startpoint->
t);
337 BC = ((double)dwire);
338 AC = ((double)dtime);
339 omega = std::asin(AC / std::hypot(AC, BC));
343 omega = TMath::Pi() -
std::abs(omega);
346 omega = -TMath::Pi() +
std::abs(omega);
360 TVector3 dummyvector(std::cos(theta * TMath::Pi() / 180.) * std::sin(phi * TMath::Pi() / 180.),
361 std::sin(theta * TMath::Pi() / 180.),
362 std::cos(theta * TMath::Pi() / 180.) * std::cos(phi * TMath::Pi() / 180.));
378 auto const& tpc =
fGeom.
TPC(planeid.parentID());
379 TVector3 start(tpc.HalfWidth(), 0., tpc.Length() / 2.);
380 TVector3
end = start + dir_vector;
384 (tpc.HalfHeight() * std::sin(std::fabs(alpha)) + start[2] * std::cos(alpha) -
385 start[1] * std::sin(alpha)),
389 (tpc.HalfHeight() * std::sin(std::fabs(alpha)) + end[2] * std::cos(alpha) -
390 end[1] * std::sin(alpha)),
411 return std::hypot(point1->
w - point2->
w, point1->
t - point2->
t);
419 double radangle = TMath::Pi() * angle / 180;
420 if (std::cos(radangle) == 0)
return 9999;
439 double& timeout)
const 443 if (slope) { invslope = -1. / slope; }
445 double ort_intercept = time1 - invslope * (double)wire1;
447 if ((slope - invslope) != 0)
448 wireout = (ort_intercept - intercept) / (slope - invslope);
451 timeout = slope * wireout + intercept;
466 double intercept = startpoint->
t - slope * startpoint->
w;
482 if (slope) { invslope = -1. / slope; }
484 double ort_intercept = point1->
t - invslope * point1->
w;
486 if ((slope - invslope) != 0)
487 pointout.
w = (ort_intercept - intercept) / (slope - invslope);
489 pointout.
w = point1->
w;
491 pointout.
t = slope * pointout.
w + intercept;
505 double& timeout)
const 507 double intercept = timestart - slope * (double)wirestart;
509 return GetPointOnLine(slope, intercept, wire1, time1, wireout, timeout);
517 double ort_intercept,
519 double& timeout)
const 523 if (slope) { invslope = -1. / slope; }
527 wireout = (ort_intercept - intercept) / (slope - invslope);
528 timeout = slope * wireout + intercept;
542 double ort_intercept,
547 if (slope) invslope = -1. / slope;
549 pointonline.
w = (ort_intercept - intercept) / (slope - invslope);
550 pointonline.
t = slope * pointonline.
w + intercept;
558 for (
unsigned int i = 0; i <
fNPlanes; ++i) {
559 if (i == p0->
plane || i == p1->
plane)
continue;
572 if (!intersection)
return -1;
574 pos.SetCoordinates(x, intersection->y, intersection->z);
593 std::cout <<
"\033[93mWarning\033[00m " 594 "\033[95m<<GeometryUtilities::GetYZ>>\033[00m" 596 <<
" 2D wire position " << p0->
w <<
" [cm] corresponds to negative wire number." 598 <<
" Forcing it to wire=0..." << std::endl
599 <<
"\033[93mWarning ends...\033[00m" << std::endl;
603 std::cout <<
"\033[93mWarning\033[00m " 604 "\033[95m<<GeometryUtilities::GetYZ>>\033[00m" 606 <<
" 2D wire position " << p0->
w <<
" [cm] exceeds max wire number " 608 <<
" Forcing it to the max wire number..." << std::endl
609 <<
"\033[93mWarning ends...\033[00m" << std::endl;
613 std::cout <<
"\033[93mWarning\033[00m " 614 "\033[95m<<GeometryUtilities::GetYZ>>\033[00m" 616 <<
" 2D wire position " << p1->
w <<
" [cm] corresponds to negative wire number." 618 <<
" Forcing it to wire=0..." << std::endl
619 <<
"\033[93mWarning ends...\033[00m" << std::endl;
623 std::cout <<
"\033[93mWarning\033[00m " 624 "\033[95m<<GeometryUtilities::GetYZ>>\033[00m" 626 <<
" 2D wire position " << p1->
w <<
" [cm] exceeds max wire number " 628 <<
" Forcing it to the max wire number..." << std::endl
629 <<
"\033[93mWarning ends...\033[00m" << std::endl;
637 if (!intersection)
return -1;
639 yz[0] = intersection->y;
640 yz[1] = intersection->z;
691 auto const x = point.X();
711 double dirs[3] = {0.};
716 double wirePitch = 0.;
717 double angleToVert = 0.;
727 double cosgamma =
std::abs(std::sin(angleToVert) * dirs[1] + std::cos(angleToVert) * dirs[2]);
729 if (cosgamma < 1.
e-5)
732 std::cout <<
" returning 100" << std::endl;
736 return wirePitch / cosgamma;
742 theta *= (TMath::Pi() / 180);
743 phi *= (TMath::Pi() / 180);
744 dirs[0] = std::cos(theta) * std::sin(phi);
745 dirs[1] = std::sin(theta);
746 dirs[2] = std::cos(theta) * std::cos(phi);
750 std::vector<const PxHit*>& hitlistlocal,
754 double& lineslopetest)
const 758 hitlist, hitlistlocal, startHit, linearlimit, ortlimit, lineslopetest, testHit);
766 std::vector<const PxHit*>& hitlistlocal,
770 double& lineslopetest,
771 PxHit& averageHit)
const 773 hitlistlocal.clear();
774 std::vector<unsigned int> hitlistlocal_index;
776 hitlistlocal_index.clear();
779 hitlist, hitlistlocal_index, startHit, linearlimit, ortlimit, lineslopetest);
783 for (
size_t i = 0; i < hitlistlocal_index.size(); ++i) {
785 hitlistlocal.push_back((
const PxHit*)(&(hitlist.at(hitlistlocal_index.at(i)))));
786 timesum += hitlist.at(hitlistlocal_index.at(i)).t;
787 wiresum += hitlist.at(hitlistlocal_index.at(i)).
w;
791 if (hitlistlocal.size()) {
792 averageHit.
w = wiresum / (double)hitlistlocal.size();
793 averageHit.
t = timesum / ((double)hitlistlocal.size());
798 std::vector<unsigned int>& hitlistlocal_index,
802 double& lineslopetest)
const 804 hitlistlocal_index.clear();
805 double locintercept = startHit.
t - startHit.
w * lineslopetest;
807 for (
size_t i = 0; i < hitlist.size(); ++i) {
810 GetPointOnLine(lineslopetest, locintercept, &hitlist.at(i), hitonline);
816 if (lindist < linearlimit && ortdist < ortlimit) { hitlistlocal_index.push_back(i); }
824 std::vector<PxHit const*>& hitlistlocal)
const 828 hitlistlocal.clear();
829 unsigned char plane = hitlist.front().plane;
832 std::map<double, const PxHit*> hitmap;
834 for (
auto const& h : hitlist) {
835 hitmap.try_emplace(h.charge, &h);
838 double qintegral = 0;
839 std::vector<const PxHit*> ordered_hits;
840 ordered_hits.reserve(hitlist.size());
841 for (
auto hiter = hitmap.rbegin(); qintegral < qtotal * 0.95 && hiter != hitmap.rend();
844 qintegral += (*hiter).first;
845 ordered_hits.push_back((*hiter).second);
849 std::vector<size_t> hit_index(8, 0);
850 std::vector<double> hit_distance(8, 1e9);
854 std::vector<PxPoint> edges(4,
PxPoint(plane, 0, 0));
858 for (
size_t index = 0; index < ordered_hits.size(); ++index) {
860 if (ordered_hits.at(index)->t < 0 || ordered_hits.at(index)->w < 0 ||
861 ordered_hits.at(index)->t > time_max || ordered_hits.at(index)->w > wire_max) {
863 throw UtilException(Form(
"Invalid wire/time (%g,%g) ... range is (0=>%g,0=>%g)",
864 ordered_hits.at(index)->w,
865 ordered_hits.at(index)->t,
873 dist = ordered_hits.at(index)->t;
874 if (dist < hit_distance.at(1)) {
875 hit_distance.at(1) =
dist;
876 hit_index.at(1) = index;
877 edges.at(0).t = ordered_hits.at(index)->t;
878 edges.at(1).t = ordered_hits.at(index)->t;
882 dist = wire_max - ordered_hits.at(index)->w;
883 if (dist < hit_distance.at(3)) {
884 hit_distance.at(3) =
dist;
885 hit_index.at(3) = index;
886 edges.at(1).w = ordered_hits.at(index)->w;
887 edges.at(2).w = ordered_hits.at(index)->w;
891 dist = time_max - ordered_hits.at(index)->t;
892 if (dist < hit_distance.at(5)) {
893 hit_distance.at(5) =
dist;
894 hit_index.at(5) = index;
895 edges.at(2).t = ordered_hits.at(index)->t;
896 edges.at(3).t = ordered_hits.at(index)->t;
900 dist = ordered_hits.at(index)->w;
901 if (dist < hit_distance.at(7)) {
902 hit_distance.at(7) =
dist;
903 hit_index.at(7) = index;
904 edges.at(0).w = ordered_hits.at(index)->w;
905 edges.at(3).w = ordered_hits.at(index)->w;
908 for (
size_t index = 0; index < ordered_hits.size(); ++index) {
912 dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(0).t,
913 ordered_hits.at(index)->w - edges.at(0).w);
914 if (dist < hit_distance.at(0)) {
915 hit_distance.at(0) =
dist;
916 hit_index.at(0) = index;
920 dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(1).t,
921 ordered_hits.at(index)->w - edges.at(1).w);
922 if (dist < hit_distance.at(2)) {
923 hit_distance.at(2) =
dist;
924 hit_index.at(2) = index;
928 dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(2).t,
929 ordered_hits.at(index)->w - edges.at(2).w);
930 if (dist < hit_distance.at(4)) {
931 hit_distance.at(4) =
dist;
932 hit_index.at(4) = index;
936 dist = cet::sum_of_squares(ordered_hits.at(index)->t - edges.at(3).t,
937 ordered_hits.at(index)->w - edges.at(3).w);
938 if (dist < hit_distance.at(6)) {
939 hit_distance.at(6) =
dist;
940 hit_index.at(6) = index;
946 std::set<size_t> unique_index;
947 std::vector<size_t> candidate_polygon;
948 candidate_polygon.reserve(9);
949 for (
auto& index : hit_index) {
950 if (unique_index.find(index) == unique_index.end()) {
951 unique_index.insert(index);
952 candidate_polygon.push_back(index);
955 for (
auto& index : hit_index) {
956 candidate_polygon.push_back(index);
960 if (unique_index.size() > 8)
throw UtilException(
"Size of the polygon > 8!");
963 candidate_polygon =
PolyOverlap(ordered_hits, candidate_polygon);
965 hitlistlocal.clear();
966 for (
unsigned int i = 0; i < (candidate_polygon.size() - 1); i++) {
967 hitlistlocal.push_back((
const PxHit*)(ordered_hits.at(candidate_polygon.at(i))));
970 if (unique_index.size() > 8)
throw UtilException(
"Size of the polygon > 8!");
974 std::vector<size_t> candidate_polygon)
const 977 for (
unsigned int i = 0; i < (candidate_polygon.size() - 1); i++) {
978 double Ax = ordered_hits.at(candidate_polygon.at(i))->
w;
979 double Ay = ordered_hits.at(candidate_polygon.at(i))->t;
980 double Bx = ordered_hits.at(candidate_polygon.at(i + 1))->
w;
981 double By = ordered_hits.at(candidate_polygon.at(i + 1))->t;
984 for (
unsigned int j = i + 2; j < (candidate_polygon.size() - 1); j++) {
986 if (candidate_polygon.at(i) == candidate_polygon.at(j + 1))
989 double Cx = ordered_hits.at(candidate_polygon.at(j))->
w;
990 double Cy = ordered_hits.at(candidate_polygon.at(j))->t;
991 double Dx = ordered_hits.at(candidate_polygon.at(j + 1))->
w;
992 double Dy = ordered_hits.at(candidate_polygon.at(j + 1))->t;
994 if ((
Clockwise(Ax, Ay, Cx, Cy, Dx, Dy) !=
Clockwise(Bx, By, Cx, Cy, Dx, Dy)) and
995 (
Clockwise(Ax, Ay, Bx, By, Cx, Cy) !=
Clockwise(Ax, Ay, Bx, By, Dx, Dy))) {
996 size_t tmp = candidate_polygon.at(i + 1);
997 candidate_polygon.at(i + 1) = candidate_polygon.at(j);
998 candidate_polygon.at(j) =
tmp;
1000 candidate_polygon.at(candidate_polygon.size() - 1) = candidate_polygon.at(0);
1002 return PolyOverlap(ordered_hits, candidate_polygon);
1007 return candidate_polygon;
1015 double const Cy)
const 1017 return (Cy - Ay) * (Bx - Ax) > (By - Ay) * (Cx - Ax);
1021 unsigned int const wirein,
1022 double const timein)
const 1028 unsigned int const wirein,
1029 double const timein)
const 1031 double min_length_from_start = 99999;
1032 unsigned int ret_ind = 0;
1034 for (
unsigned int ii = 0; ii < hitlist.size(); ii++) {
1037 if (dist_mod < min_length_from_start) {
1038 min_length_from_start = dist_mod;
double Get2Dslope(double deltawire, double deltatime) const
double Get2DDistance(double wire1, double time1, double wire2, double time2) const
detinfo::DetectorClocksData const & fClocks
Namespace for general, non-LArSoft-specific utilities.
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
GeometryUtilities(geo::GeometryCore const &geom, geo::WireReadoutGeom const &wireReadoutGeom, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &propData)
Class def header for exception classes used in GeometryUtilities.
std::vector< double > vertangle
double PitchInView(unsigned int plane, double phi, double theta) const
WireID NearestWireID(Point_t const &pos) const
Returns the ID of wire closest to the specified position.
The data type to uniquely identify a Plane.
double Temperature() const
In kelvin.
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.
void GetDirectionCosines(double phi, double theta, double *dirs) const
double WireAngleToVertical(View_t view, TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
PxPoint Get2DPointProjectionCM(geo::Point_t xyz, geo::PlaneID const &planeID) const
WireID_t Wire
Index of the wire within its plane.
int GetPointOnLine(double slope, double intercept, double wire1, double time1, double &wireout, double &timeout) const
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::optional< WireIDIntersection > ChannelsIntersect(raw::ChannelID_t c1, raw::ChannelID_t c2) const
Returns an intersection point of two channels.
double Efield(unsigned int planegap=0) const
kV/cm
detinfo::DetectorPropertiesData const & fDetProp
3-dimensional objects, potentially hits, clusters, prongs, etc.
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Access the description of the physical detector geometry.
int GetYZ(const PxPoint *p0, const PxPoint *p1, double *yz) const
View_t View() const
Which coordinate does this plane measure.
geo::WireReadoutGeom const & fWireReadoutGeom
void SelectLocalHitlistIndex(const std::vector< PxHit > &hitlist, std::vector< unsigned int > &hitlistlocal_index, PxPoint &startHit, double &linearlimit, double &ortlimit, double &lineslopetest) const
int GetProjectedPoint(const PxPoint *p0, const PxPoint *p1, PxPoint &pN) const
Interface for a class providing readout channel mapping to geometry.
double Get2DPitchDistance(double angle, double inwire, double wire) const
int Get3DaxisN(int iplane0, int iplane1, double omega0, double omega1, double &phi, double &theta) const
geo::GeometryCore const & fGeom
std::vector< size_t > PolyOverlap(std::vector< const PxHit * > ordered_hits, std::vector< size_t > candidate_polygon) const
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
unsigned int NumberTimeSamples() const
double GetTimeTicks(double x, unsigned int plane) const
void SelectLocalHitlist(const std::vector< PxHit > &hitlist, std::vector< const PxHit * > &hitlistlocal, PxPoint &startHit, double &linearlimit, double &ortlimit, double &lineslopetest) const
int GetPointOnLineWSlopes(double slope, double intercept, double ort_intercept, double &wireout, double &timeout) const
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
The data type to uniquely identify a TPC.
PlaneID_t Plane
Index of the plane within its TPC.
Description of the physical geometry of one entire detector.
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire .
bool Clockwise(double Ax, double Ay, double Bx, double By, double Cx, double Cy) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
void SelectPolygonHitList(const std::vector< PxHit > &hitlist, std::vector< const PxHit * > &hitlistlocal) const
int GetXYZ(const PxPoint *p0, const PxPoint *p1, double *xyz) const
double CalculatePitch(unsigned int iplane0, double phi, double theta) const
Encapsulate the construction of a single detector plane .
double dist(const TReal *x, const TReal *y, const unsigned int dimension)
Contains all timing reference information for the detector.
PxHit FindClosestHit(std::vector< PxHit > const &hitlist, unsigned int wirein, double timein) const
double Get2DangleFrom3D(unsigned int plane, double phi, double theta) const
double CalculatePitchPolar(unsigned int iplane0, double phi, double theta) const
double Get3DSpecialCaseTheta(int iplane0, int iplane1, double dw0, double dw1) const
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
int trigger_offset(DetectorClocksData const &data)
unsigned int FindClosestHitIndex(std::vector< PxHit > const &hitlist, unsigned int wirein, double timein) const
constexpr double kINVALID_DOUBLE
double Get2DPitchDistanceWSlope(double slope, double inwire, double wire) const
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
double Get2Dangle(double deltawire, double deltatime) const
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
PxPoint Get2DPointProjection(geo::Point_t const &xyz, geo::PlaneID const &planeID) const
Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
Interface to geometry for wire readouts .
constexpr Point origin()
Returns a origin position with a point of the specified type.
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.