20 #include "art/Framework/Services/Registry/ServiceHandle.h"
21 #include "messagefacility/MessageLogger/MessageLogger.h"
29 : fTpcGeo(art::ServiceHandle<geo::Geometry
const>()->
TPC(0, 0))
54 : fTpcGeo(art::ServiceHandle<geo::Geometry
const>()->
TPC(tpc, cryo))
55 , fDriftOffset(xshift)
61 unsigned int lastPlane =
geo::kZ;
84 double d, dmin = fPoint3D.X() - fMinX;
85 d = fMaxX - fPoint3D.X();
86 if (d < dmin) dmin = d;
88 d = fPoint3D.Y() - fMinY;
89 if (d < dmin) dmin = d;
90 d = fMaxY - fPoint3D.Y();
91 if (d < dmin) dmin = d;
93 d = fPoint3D.Z() - fMinZ;
94 if (d < dmin) dmin = d;
95 d = fMaxZ - fPoint3D.Z();
96 if (d < dmin) dmin = d;
104 if (((fMinX - margin) <= p3d.X()) && (p3d.X() <= (fMaxX + margin)) &&
105 ((fMinY - margin) <= p3d.Y()) && (p3d.Y() <= (fMaxY + margin)) &&
106 ((fMinZ - margin) <= p3d.Z()) && (p3d.Z() <= (fMaxZ + margin)))
115 if (((fMinX - margin) <= p3d.X()) && (p3d.X() <= (fMaxX + margin)) &&
116 ((fMinY - margin) <= p3d.Y()) && (p3d.Y() <= (fMaxY + margin)) &&
117 ((fMinZ - margin) <= p3d.Z()) && (p3d.Z() <= (fMaxZ + margin)))
126 bool trimmed =
false;
128 if (fPoint3D.X() < fMinX - fMargin) {
129 fPoint3D.SetX(fMinX - fMargin);
132 if (fPoint3D.X() > fMaxX + fMargin) {
133 fPoint3D.SetX(fMaxX + fMargin);
137 if (fPoint3D.Y() < fMinY - fMargin) {
138 fPoint3D.SetY(fMinY - fMargin);
141 if (fPoint3D.Y() > fMaxY + fMargin) {
142 fPoint3D.SetY(fMaxY + fMargin);
146 if (fPoint3D.Z() < fMinZ - fMargin) {
147 fPoint3D.SetZ(fMinZ - fMargin);
150 if (fPoint3D.Z() > fMaxZ + fMargin) {
151 fPoint3D.SetZ(fMaxZ + fMargin);
161 for (
size_t i = 0; i < fTpcGeo.Nplanes(); ++i) {
162 fProj2D[i].Set(fTpcGeo.Plane(i).PlaneCoordinate(fPoint3D), fPoint3D.X() - fDriftOffset);
171 bool accepted = !LimitPoint3D();
193 for (
auto h : fAssignedHits) {
194 if (
h->IsEnabled()) {
195 unsigned int view =
h->View2D();
197 sum += OptFactor(view) *
198 h->GetSigmaFactor() *
214 throw cet::exception(
"Node3D") <<
"Isolated vertex." << std::endl;
219 throw cet::exception(
"Node3D") <<
"Corrupted vertex." << std::endl;
231 if (!next) g3d = vtx->
Point3D();
235 gstart = Projection2D(h.
View2D());
239 g3d -= vtx->
Point3D() - fPoint3D;
243 mf::LogError(
"pma::Node3D") <<
"Isolated vertex.";
244 TVector2
p(Projection2D(h.
View2D()));
251 v0 -= Projection2D(h.
View2D());
254 v1 -= Projection2D(h.
View2D());
256 double v0Norm = v0.Mod();
257 double v1Norm = v1.Mod();
258 double mag = v0Norm * v1Norm;
260 if (mag != 0.0) cosine = v0 * v1 / mag;
262 TVector2
p(Projection2D(h.
View2D()));
267 vN -= Projection2D(h.
View2D());
269 mag = v0Norm * vN.Mod();
270 double cosineN = 0.0;
271 if (mag != 0.0) cosineN = v0 * vN / mag;
282 float b = (float)(v0Norm * cosine / v1Norm);
315 auto const& vStop1 =
static_cast<pma::Node3D*
>(prev->Prev())->fPoint3D;
316 auto const& vStop2 =
static_cast<pma::Node3D*
>(next->Next())->fPoint3D;
318 vStop1.X() - fPoint3D.X(), vStop1.Y() - fPoint3D.Y(), vStop1.Z() - fPoint3D.Z());
320 vStop2.X() - fPoint3D.X(), vStop2.Y() - fPoint3D.Y(), vStop2.Z() - fPoint3D.Z());
321 double mag = sqrt(v1.Mag2() * v2.Mag2());
323 if (mag != 0.0) cosine = v1.Dot(v2) / mag;
327 mf::LogError(
"pma::Node3D") <<
"pma::Node3D::SegmentCos(): neighbours not initialized.";
336 auto const& vStop1 =
static_cast<pma::Node3D*
>(prev->Prev())->fPoint3D;
337 auto const& vStop2 =
static_cast<pma::Node3D*
>(next->Next())->fPoint3D;
338 pma::Vector2D v1(vStop1.Y() - fPoint3D.Y(), vStop1.Z() - fPoint3D.Z());
339 pma::Vector2D v2(vStop2.Y() - fPoint3D.Y(), vStop2.Z() - fPoint3D.Z());
340 double mag = sqrt(v1.Mag2() * v2.Mag2());
342 if (mag != 0.0) cosine = v1.Dot(v2) / mag;
346 mf::LogError(
"pma::Node3D") <<
"pma::Node3D::SegmentCosZX(): neighbours not initialized.";
355 auto const& vStop1 =
static_cast<pma::Node3D*
>(prev->Prev())->fPoint3D;
356 auto const& vStop2 =
static_cast<pma::Node3D*
>(next->Next())->fPoint3D;
357 pma::Vector2D v1(vStop1.X() - fPoint3D.X(), vStop1.Z() - fPoint3D.Z());
358 pma::Vector2D v2(vStop2.X() - fPoint3D.X(), vStop2.Z() - fPoint3D.Z());
359 double mag = sqrt(v1.Mag2() * v2.Mag2());
361 if (mag != 0.0) cosine = v1.Dot(v2) / mag;
365 mf::LogError(
"pma::Node3D") <<
"pma::Node3D::SegmentCosZY(): neighbours not initialized.";
375 auto const& vStart =
static_cast<pma::Node3D*
>(prev->Prev())->fPoint3D;
376 auto const& vStop =
static_cast<pma::Node3D*
>(next->Next())->fPoint3D;
378 double dy = vStop.X() - vStart.X();
379 double dz = vStop.Z() - vStart.Z();
380 double len2 = dy * dy + dz * dz;
381 double cosine2 = 0.0;
382 if (len2 > 0.0) cosine2 = dz * dz / len2;
392 if (prev && NextCount()) {
397 if (fHitsRadius > 0.0
F)
398 return (1.0 + SegmentCosWirePlane()) * fHitsRadius * fHitsRadius / (4 * nInd1 + 1.0);
400 return (1.0 + SegmentCosWirePlane()) * Length2() / (4 * nInd1 + 1.0);
414 if (fIsVertex)
return 0.0;
416 unsigned int nseg = 1;
417 double penalty = PiInWirePlane();
430 return pow(EndPtCos2Transverse(), 10) * penalty / nseg;
438 size_t nnext = NextCount();
439 if (nnext > 1)
return true;
453 if (prev && (NextCount() == 1)) {
457 if ((segPrev->
TPC() < 0) || (segNext->
TPC() < 0))
return true;
462 std::vector<pma::Track3D*>
465 std::vector<pma::Track3D*> branches;
467 branches.reserve(NextCount());
468 for (
size_t i = 0; i < NextCount(); ++i) {
470 branches.push_back(seg->
Parent());
479 if (fIsVertex)
return 0.0;
481 if (prev && NextCount()) {
486 if ((segPrev->
TPC() < 0) || (segNext->
TPC() < 0))
489 double segCos = SegmentCos();
491 double lAsymmFactor = 0.0;
493 double lPrev = segPrev->
Length();
494 double lNext = segNext->
Length();
495 double lSum = lPrev + lNext;
497 double lAsymm = (1.0 - segCos) * (lPrev - lNext) / lSum;
498 lAsymmFactor = 0.05 * lAsymm * lAsymm;
502 if (fHitsRadius > 0.0
F)
503 return scale * (1.0 + segCos + lAsymmFactor) * fHitsRadius * fHitsRadius;
505 return scale * (1.0 + segCos + lAsymmFactor) * Length2();
508 double pi_result = 0.0;
509 unsigned int nSeg = 0;
515 if (prevVtx->
Prev()) nSeg++;
525 mf::LogWarning(
"pma::Node3D") <<
"pma::Node3D::Pi(): an isolated vertex?";
528 if (nSeg == 1) pi_result = endSegWeight * seg->
Length2();
536 unsigned int nseg = 1;
537 double penalty = Pi(endSegWeight,
true);
540 for (
unsigned int i = 0; i < NextCount(); i++) {
542 penalty += v->
Pi(endSegWeight,
false);
547 penalty += v->
Pi(endSegWeight,
false);
550 return penalty / nseg;
556 unsigned int nhits = NPrecalcEnabledHits();
557 double mse = SumDist2();
560 for (
unsigned int i = 0; i < NextCount(); i++) {
579 return Mse() + penaltyValue * (Penalty(endSegWeight) + PenaltyInWirePlane());
585 double l1 = 0.0, l2 = 0.0, minLength2 = 0.0;
586 TVector3 tmp(fPoint3D), gpoint(fPoint3D);
597 if ((l1 > 0.01) && (l1 < l2))
599 else if ((l2 > 0.01) && (l2 < l1))
604 double dxi = 0.001 * sqrt(minLength2);
606 if (dxi < 6.0
E-37)
return 0.0;
609 gz = g0 = GetObjFunction(penaltyValue, endSegWeight);
615 gpoint[0] = tmp[0] + dxi;
617 gi = GetObjFunction(penaltyValue, endSegWeight);
618 fGradient[0] = (g0 - gi) / dxi;
620 gpoint[0] = tmp[0] - dxi;
622 gi = GetObjFunction(penaltyValue, endSegWeight);
623 fGradient[0] = 0.5 * (fGradient[0] + (gi - g0) / dxi);
630 gpoint[1] = tmp[1] + dxi;
632 gi = GetObjFunction(penaltyValue, endSegWeight);
633 fGradient[1] = (g0 - gi) / dxi;
635 gpoint[1] = tmp[1] - dxi;
637 gi = GetObjFunction(penaltyValue, endSegWeight);
638 fGradient[1] = 0.5 * (fGradient[1] + (gi - g0) / dxi);
645 gpoint[2] = tmp[2] + dxi;
647 gi = GetObjFunction(penaltyValue, endSegWeight);
649 fGradient[2] = (gz - gi) / dxi;
651 gpoint[2] = tmp[2] - dxi;
653 gi = GetObjFunction(penaltyValue, endSegWeight);
655 fGradient[2] = 0.5 * (fGradient[2] + (gi - gz) / dxi);
661 if (fGradient.Mag2() < 6.0E-37)
return 0.0;
669 unsigned int steps = 0;
670 double t, t1, t2, t3,
g, g0, g1, g2, g3,
p1, p2;
671 double eps = 6.0E-37, zero_tol = 1.0E-15;
672 TVector3 tmp(fPoint3D), gpoint(fPoint3D);
674 g = MakeGradient(penalty, weight);
675 if (g < zero_tol)
return 0.0;
693 gpoint += (fGradient * t3);
694 if (!SetPoint3D(gpoint))
697 g3 = GetObjFunction(penalty, weight);
699 return (g0 - g3) / g3;
706 g3 = GetObjFunction(penalty, weight);
708 if (g3 < zero_tol)
return 0.0;
710 if (++steps > 1000) {
725 t2 = (t1 * g3 + t3 * g1) / (g1 + g3);
728 t2 = 0.05 * t3 + 0.95 * t2;
734 if (fabs(t2 - t1) <
tol) {
740 gpoint += (fGradient * t2);
741 if (!SetPoint3D(gpoint))
744 g2 = GetObjFunction(penalty, weight);
746 return (g0 - g2) / g2;
749 gpoint += (fGradient * t1);
750 return (g0 - g1) / g1;
754 gpoint += (fGradient * t3);
755 return (g0 - g3) / g3;
762 g2 = GetObjFunction(penalty, weight);
764 if (g2 < zero_tol)
return 0.0;
771 while (fabs(t1 - t3) > tol) {
773 if ((fabs(t2 - t1) < eps) || (fabs(t2 - t3) < eps))
break;
774 if ((fabs(g2 - g1) < eps) && (fabs(g2 - g3) < eps))
break;
776 p1 = (t2 - t1) * (g2 - g3);
777 p2 = (t2 - t3) * (g2 - g1);
778 if (fabs(p1 - p2) < eps)
break;
780 t = t2 + ((t2 - t1) * p1 - (t2 - t3) * p2) / (2 * (p2 - p1));
781 if ((t <= t1) || (t >= t3)) t = (t1 * g3 + t3 * g1) / (g1 + g3);
784 gpoint += (fGradient * t);
785 if (!SetPoint3D(gpoint))
788 g = GetObjFunction(penalty, weight);
789 if ((g < g0) && (g < g1) && (g < g3))
791 else if ((g1 < g0) && (g1 < g3)) {
793 gpoint += (fGradient * t1);
794 return (g0 - g1) / g1;
798 gpoint += (fGradient * t3);
799 return (g0 - g3) / g3;
807 g = GetObjFunction(penalty, weight);
808 if (g < zero_tol)
return 0.0;
813 if (fabs(t - t2) < 0.2 * tol)
break;
846 double dg = StepWithGradient(0.1
F, 0.002
F, penaltyValue, endSegWeight);
847 if (dg > 0.01) dg = StepWithGradient(0.03
F, 0.0001
F, penaltyValue, endSegWeight);
848 if (dg > 0.0) dg = StepWithGradient(0.03
F, 0.0001
F, penaltyValue, endSegWeight);
857 fAssignedPoints.clear();
858 fAssignedHits.clear();
861 std::vector<pma::Track3D*> to_check;
865 if (seg->
Parent() != trk) to_check.push_back(seg->
Parent());
867 for (
unsigned int i = 0; i < NextCount(); i++) {
869 if (seg->
Parent() != trk) to_check.push_back(seg->
Parent());
873 while (p < fAssignedPoints.size()) {
875 for (
size_t t = 0; t < to_check.size(); t++)
876 if (to_check[t]->HasRefPoint(fAssignedPoints[p])) {
882 fAssignedPoints.erase(fAssignedPoints.begin() +
p);
888 while (h < fAssignedHits.size()) {
892 for (
size_t t = 0; (t < to_check.size()) && !found; t++)
893 for (
size_t i = 0; i < to_check[t]->size(); i++) {
902 fAssignedHits.erase(fAssignedHits.begin() +
h);
size_t NPrecalcEnabledHits(void) const
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
TVector3 const & Point3D() const
TVector2 const & Projection2D(unsigned int view) const
double Penalty(float endSegWeight) const
Implementation of the Projection Matching Algorithm.
double Dist2(const TVector2 &v1, const TVector2 &v2)
void ClearAssigned(pma::Track3D *trk=0) override
Implementation of the Projection Matching Algorithm.
bool LimitPoint3D()
Returns true if node position was trimmed to its TPC volume + fMargin.
std::vector< pma::Track3D * > GetBranches() const
void Optimize(float penaltyValue, float endSegWeight)
Planes which measure Z direction.
bool IsTPCEdge() const
Is the first/last in this TPC?
recob::tracking::Vector_t Vector3D
static bool fGradFixed[3]
double SegmentCosWirePlane() const
int TPC(void) const
TPC index or -1 if out of any TPC.
double PenaltyInWirePlane() const
double Length2() const override
double GetDistToWall() const
double SumDist2Hits() const override
virtual unsigned int NextCount(void) const
double PiInWirePlane() const
double Length2(void) const override
unsigned int View2D() const noexcept
double SegmentCos() const
Cosine of 3D angle between connected segments.
bool SetPoint3D(const TVector3 &p3d)
double MinZ() const
Returns the world z coordinate of the start of the box.
double StepWithGradient(float alfa, float tol, float penalty, float weight)
double SegmentCosTransverse() const
unsigned int NumberTimeSamples() const
void SetProjection(pma::Hit3D &h) const override
Set hit 3D position and its 2D projection to the vertex.
double EndPtCos2Transverse() const
bool SameTPC(const TVector3 &p3d, float margin=0.0F) const
Check if p3d is in the same TPC as the node.
virtual pma::Vector3D GetDirection3D(void) const =0
Get 3D direction cosines corresponding to this element.
void SetProjection(const TVector2 &p, float b)
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D point to the point 3D.
double SumDist2(void) const
double MaxY() const
Returns the world y coordinate of the end of the box.
double ConvertTicksToX(double ticks, int p, int t, int c) const
double MakeGradient(float penaltyValue, float endSegWeight)
TVector2 const & Point2D() const noexcept
Encapsulate the construction of a single detector plane.
double GetObjFunction(float penaltyValue, float endSegWeight) const
Objective function minimized during oprimization.
double MaxZ() const
Returns the world z coordinate of the end of the box.
void SetPoint3D(const TVector3 &p3d)
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double > > Vector2D
bool IsBranching() const
Belongs to more than one track?
geo::TPCGeo const & fTpcGeo
virtual pma::SortedObjectBase * Prev(void) const
pma::Vector3D GetDirection3D() const override
double MinY() const
Returns the world y coordinate of the start of the box.
pma::Track3D * Parent(void) const
double Pi(float endSegWeight, bool doAsymm) const
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
double Length(void) const
physics associatedGroupsWithLeft p1
art framework interface to geometry description
Encapsulate the construction of a single detector plane.