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.