PmaNode3D.cxx
Go to the documentation of this file.
1 /**
2  * @file PmaNode3D.cxx
3  *
4  * @author D.Stefan and R.Sulej
5  *
6  * @brief Implementation of the Projection Matching Algorithm
7  *
8  * 3D track node. See PmaTrack3D.h file for details.
9  */
10 
14 
19 
22 
23 // Fixed optimization directions: X Y Z
24 bool pma::Node3D::fGradFixed[3] = {false, false, false};
25 
26 double pma::Node3D::fMargin = 3.0;
27 
29  : fTpcGeo(art::ServiceHandle<geo::Geometry const>()->TPC(0, 0))
30  , fMinX(0)
31  , fMaxX(0)
32  , fMinY(0)
33  , fMaxY(0)
34  , fMinZ(0)
35  , fMaxZ(0)
36  , fPoint3D(0, 0, 0)
37  , fDriftOffset(0)
38  , fIsVertex(false)
39 {
40  fTPC = 0;
41  fCryo = 0;
42 
43  fProj2D[0].Set(0);
44  fProj2D[1].Set(0);
45  fProj2D[2].Set(0);
46 }
47 
49  const TVector3& p3d,
50  unsigned int tpc,
51  unsigned int cryo,
52  bool vtx,
53  double xshift)
54  : fTpcGeo(art::ServiceHandle<geo::Geometry const>()->TPC(tpc, cryo))
55  , fDriftOffset(xshift)
56  , fIsVertex(vtx)
57 {
58  fTPC = tpc;
59  fCryo = cryo;
60 
61  unsigned int lastPlane = geo::kZ;
62  while ((lastPlane > 0) && !fTpcGeo.HasPlane(lastPlane))
63  lastPlane--;
64 
65  fMinX = detProp.ConvertTicksToX(0, lastPlane, tpc, cryo);
66  fMaxX = detProp.ConvertTicksToX(detProp.NumberTimeSamples() - 1, lastPlane, tpc, cryo);
67  if (fMaxX < fMinX) {
68  double tmp = fMaxX;
69  fMaxX = fMinX;
70  fMinX = tmp;
71  }
72 
73  fMinY = fTpcGeo.MinY();
74  fMaxY = fTpcGeo.MaxY();
75  fMinZ = fTpcGeo.MinZ();
76  fMaxZ = fTpcGeo.MaxZ();
77 
78  SetPoint3D(p3d);
79 }
80 
81 double
83 {
84  double d, dmin = fPoint3D.X() - fMinX;
85  d = fMaxX - fPoint3D.X();
86  if (d < dmin) dmin = d;
87 
88  d = fPoint3D.Y() - fMinY;
89  if (d < dmin) dmin = d;
90  d = fMaxY - fPoint3D.Y();
91  if (d < dmin) dmin = d;
92 
93  d = fPoint3D.Z() - fMinZ;
94  if (d < dmin) dmin = d;
95  d = fMaxZ - fPoint3D.Z();
96  if (d < dmin) dmin = d;
97 
98  return dmin;
99 }
100 
101 bool
102 pma::Node3D::SameTPC(const TVector3& p3d, float margin) const
103 {
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)))
107  return true;
108  else
109  return false;
110 }
111 
112 bool
113 pma::Node3D::SameTPC(const pma::Vector3D& p3d, float margin) const
114 {
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)))
118  return true;
119  else
120  return false;
121 }
122 
123 bool
125 {
126  bool trimmed = false;
127 
128  if (fPoint3D.X() < fMinX - fMargin) {
129  fPoint3D.SetX(fMinX - fMargin);
130  trimmed = true;
131  }
132  if (fPoint3D.X() > fMaxX + fMargin) {
133  fPoint3D.SetX(fMaxX + fMargin);
134  trimmed = true;
135  }
136 
137  if (fPoint3D.Y() < fMinY - fMargin) {
138  fPoint3D.SetY(fMinY - fMargin);
139  trimmed = true;
140  }
141  if (fPoint3D.Y() > fMaxY + fMargin) {
142  fPoint3D.SetY(fMaxY + fMargin);
143  trimmed = true;
144  }
145 
146  if (fPoint3D.Z() < fMinZ - fMargin) {
147  fPoint3D.SetZ(fMinZ - fMargin);
148  trimmed = true;
149  }
150  if (fPoint3D.Z() > fMaxZ + fMargin) {
151  fPoint3D.SetZ(fMaxZ + fMargin);
152  trimmed = true;
153  }
154 
155  return trimmed;
156 }
157 
158 void
160 {
161  for (size_t i = 0; i < fTpcGeo.Nplanes(); ++i) {
163  }
164 }
165 
166 bool
167 pma::Node3D::SetPoint3D(const TVector3& p3d)
168 {
169  fPoint3D = p3d;
170 
171  bool accepted = !LimitPoint3D();
172  UpdateProj2D();
173 
174  return accepted;
175 }
176 
177 double
178 pma::Node3D::GetDistance2To(const TVector3& p3d) const
179 {
180  return pma::Dist2(fPoint3D, p3d);
181 }
182 
183 double
184 pma::Node3D::GetDistance2To(const TVector2& p2d, unsigned int view) const
185 {
186  return pma::Dist2(fProj2D[view], p2d);
187 }
188 
189 double
191 {
192  double sum = 0.0F;
193  for (auto h : fAssignedHits) {
194  if (h->IsEnabled()) {
195  unsigned int view = h->View2D();
196 
197  sum += OptFactor(view) * // alpha_i
198  h->GetSigmaFactor() * // hit_amp / hit_max_amp
199  pma::Dist2(h->Point2D(), fProj2D[view]);
200  }
201  }
202  return sum;
203 }
204 
207 {
208  pma::Element3D* seg = 0;
209  if (next) { seg = dynamic_cast<pma::Element3D*>(next); }
210  else if (prev) {
211  seg = dynamic_cast<pma::Element3D*>(prev);
212  }
213  else {
214  throw cet::exception("Node3D") << "Isolated vertex." << std::endl;
215  }
216 
217  if (seg) { return seg->GetDirection3D(); }
218  else {
219  throw cet::exception("Node3D") << "Corrupted vertex." << std::endl;
220  }
221 }
222 
223 void
225 {
226  TVector2 gstart;
227  TVector3 g3d;
228  if (prev) {
229  pma::Node3D* vtx = static_cast<pma::Node3D*>(prev->Prev());
230  gstart = vtx->Projection2D(h.View2D());
231  if (!next) g3d = vtx->Point3D();
232  }
233  else if (next) {
234  pma::Node3D* vtx = static_cast<pma::Node3D*>(next->Next());
235  gstart = Projection2D(h.View2D());
236  gstart -= vtx->Projection2D(h.View2D()) - Projection2D(h.View2D());
237  if (!prev) {
238  g3d = fPoint3D;
239  g3d -= vtx->Point3D() - fPoint3D;
240  }
241  }
242  else {
243  mf::LogError("pma::Node3D") << "Isolated vertex.";
244  TVector2 p(Projection2D(h.View2D()));
245  h.SetProjection(p, 0.0F);
246  h.SetPoint3D(fPoint3D);
247  return;
248  }
249 
250  TVector2 v0(h.Point2D());
251  v0 -= Projection2D(h.View2D());
252 
253  TVector2 v1(gstart);
254  v1 -= Projection2D(h.View2D());
255 
256  double v0Norm = v0.Mod();
257  double v1Norm = v1.Mod();
258  double mag = v0Norm * v1Norm;
259  double cosine = 0.0;
260  if (mag != 0.0) cosine = v0 * v1 / mag;
261 
262  TVector2 p(Projection2D(h.View2D()));
263 
264  if (prev && next) {
265  pma::Node3D* vNext = static_cast<pma::Node3D*>(next->Next());
266  TVector2 vN(vNext->Projection2D(h.View2D()));
267  vN -= Projection2D(h.View2D());
268 
269  mag = v0Norm * vN.Mod();
270  double cosineN = 0.0;
271  if (mag != 0.0) cosineN = v0 * vN / mag;
272 
273  // hit on the previous segment side, sorting on the -cosine(prev_seg, point) /max.val. = 1/
274  if (cosineN <= cosine) h.SetProjection(p, -(float)cosine);
275  // hit on the next segment side, sorting on the 1+cosine(next_seg, point) /min.val. = 1/
276  else
277  h.SetProjection(p, 2.0F + (float)cosineN);
278 
279  h.SetPoint3D(fPoint3D);
280  }
281  else {
282  float b = (float)(v0Norm * cosine / v1Norm);
283  if (fFrozen) // limit 3D positions to outermose node if frozen
284  {
285  h.SetPoint3D(fPoint3D);
286  }
287  else // or set 3D positions along the line of outermost segment
288  {
289  g3d -= fPoint3D;
290  h.SetPoint3D(fPoint3D + (g3d * b));
291 
292  p += (v1 * b);
293  }
294  h.SetProjection(p, -b);
295  }
296 }
297 
298 double
300 {
301  double l = 0.0;
302  if (next) l += (static_cast<pma::Segment3D*>(next))->Length();
303  if (prev) l += (static_cast<pma::Segment3D*>(prev))->Length();
304 
305  if (next && prev)
306  return 0.25 * l * l;
307  else
308  return l * l;
309 }
310 
311 double
313 {
314  if (prev && next) {
315  auto const& vStop1 = static_cast<pma::Node3D*>(prev->Prev())->fPoint3D;
316  auto const& vStop2 = static_cast<pma::Node3D*>(next->Next())->fPoint3D;
317  pma::Vector3D v1(
318  vStop1.X() - fPoint3D.X(), vStop1.Y() - fPoint3D.Y(), vStop1.Z() - fPoint3D.Z());
319  pma::Vector3D v2(
320  vStop2.X() - fPoint3D.X(), vStop2.Y() - fPoint3D.Y(), vStop2.Z() - fPoint3D.Z());
321  double mag = sqrt(v1.Mag2() * v2.Mag2());
322  double cosine = 0.0;
323  if (mag != 0.0) cosine = v1.Dot(v2) / mag;
324  return cosine;
325  }
326  else {
327  mf::LogError("pma::Node3D") << "pma::Node3D::SegmentCos(): neighbours not initialized.";
328  return -1.0;
329  }
330 }
331 
332 double
334 {
335  if (prev && next) {
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());
341  double cosine = 0.0;
342  if (mag != 0.0) cosine = v1.Dot(v2) / mag;
343  return cosine;
344  }
345  else {
346  mf::LogError("pma::Node3D") << "pma::Node3D::SegmentCosZX(): neighbours not initialized.";
347  return -1.0;
348  }
349 }
350 
351 double
353 {
354  if (prev && next) {
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());
360  double cosine = 0.0;
361  if (mag != 0.0) cosine = v1.Dot(v2) / mag;
362  return cosine;
363  }
364  else {
365  mf::LogError("pma::Node3D") << "pma::Node3D::SegmentCosZY(): neighbours not initialized.";
366  return -1.0;
367  }
368 }
369 
370 // *** Note: should be changed / generalized for horizontal wire planes (e.g. 2-phase LAr). ***
371 double
373 {
374  if (prev && next) {
375  auto const& vStart = static_cast<pma::Node3D*>(prev->Prev())->fPoint3D;
376  auto const& vStop = static_cast<pma::Node3D*>(next->Next())->fPoint3D;
377 
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;
383  return cosine2;
384  }
385  else
386  return 0.0;
387 }
388 
389 double
391 {
392  if (prev && NextCount()) {
393  pma::Segment3D* seg0 = dynamic_cast<pma::Segment3D*>(prev);
394  pma::Segment3D* seg1 = dynamic_cast<pma::Segment3D*>(Next(0));
395  unsigned int nInd1 = NHits(geo::kU) + seg0->NHits(geo::kU) + seg1->NHits(geo::kU);
396 
397  if (fHitsRadius > 0.0F)
398  return (1.0 + SegmentCosWirePlane()) * fHitsRadius * fHitsRadius / (4 * nInd1 + 1.0);
399  else
400  return (1.0 + SegmentCosWirePlane()) * Length2() / (4 * nInd1 + 1.0);
401  }
402  else
403  return 0.0;
404 }
405 
406 // Constraint on two segments angle in projection to plane parallel to wire plane, suppressed by
407 // the orientation in the plane transverse to wire plane (only sections with low variation of
408 // drift time are penalized with this constraint); PiInWirePlane() components are reduced if
409 // there are Ind1 / geo::kU hits which add information to the object shape.
410 // *** Note: should be changed / generalized for horizontal wire planes (e.g. 2-phase LAr). ***
411 double
413 {
414  if (fIsVertex) return 0.0;
415 
416  unsigned int nseg = 1;
417  double penalty = PiInWirePlane();
418  pma::Node3D* v;
419  if (next) {
420  v = static_cast<pma::Node3D*>(next->Next());
421  penalty += v->PiInWirePlane();
422  nseg++;
423  }
424  if (prev) {
425  v = static_cast<pma::Node3D*>(prev->Prev());
426  penalty += v->PiInWirePlane();
427  nseg++;
428  }
429  if (penalty > 0.0)
430  return pow(EndPtCos2Transverse(), 10) * penalty / nseg;
431  else
432  return 0.0;
433 }
434 
435 bool
437 {
438  size_t nnext = NextCount();
439  if (nnext > 1) return true; // 1 trk -> vtx -> n*trk
440 
441  if (prev && nnext) {
442  pma::Segment3D* segPrev = static_cast<pma::Segment3D*>(prev);
443  pma::Segment3D* segNext = static_cast<pma::Segment3D*>(Next(0));
444  if (segNext->Parent() != segPrev->Parent()) // 1 trk -> vtx -> 1 trk
445  return true;
446  }
447  return false;
448 }
449 
450 bool
452 {
453  if (prev && (NextCount() == 1)) {
454  pma::Segment3D* segPrev = static_cast<pma::Segment3D*>(prev);
455  pma::Segment3D* segNext = static_cast<pma::Segment3D*>(Next(0));
456 
457  if ((segPrev->TPC() < 0) || (segNext->TPC() < 0)) return true;
458  }
459  return false;
460 }
461 
462 std::vector<pma::Track3D*>
464 {
465  std::vector<pma::Track3D*> branches;
466  if (NextCount()) {
467  branches.reserve(NextCount());
468  for (size_t i = 0; i < NextCount(); ++i) {
469  pma::Segment3D* seg = static_cast<pma::Segment3D*>(Next(i));
470  branches.push_back(seg->Parent());
471  }
472  }
473  return branches;
474 }
475 
476 double
477 pma::Node3D::Pi(float endSegWeight, bool doAsymm) const
478 {
479  if (fIsVertex) return 0.0;
480 
481  if (prev && NextCount()) {
482  pma::Segment3D* segPrev = static_cast<pma::Segment3D*>(prev);
483  pma::Segment3D* segNext = static_cast<pma::Segment3D*>(Next(0));
484 
485  double scale = 1.0;
486  if ((segPrev->TPC() < 0) || (segNext->TPC() < 0))
487  scale = 0.5; // lower penalty on segments between tpc's
488 
489  double segCos = SegmentCos();
490 
491  double lAsymmFactor = 0.0;
492  if (doAsymm) {
493  double lPrev = segPrev->Length();
494  double lNext = segNext->Length();
495  double lSum = lPrev + lNext;
496  if (lSum > 0.1) {
497  double lAsymm = (1.0 - segCos) * (lPrev - lNext) / lSum;
498  lAsymmFactor = 0.05 * lAsymm * lAsymm;
499  }
500  }
501 
502  if (fHitsRadius > 0.0F)
503  return scale * (1.0 + segCos + lAsymmFactor) * fHitsRadius * fHitsRadius;
504  else
505  return scale * (1.0 + segCos + lAsymmFactor) * Length2();
506  }
507  else {
508  double pi_result = 0.0;
509  unsigned int nSeg = 0;
510  pma::Segment3D* seg = 0;
511  if (prev) {
512  seg = static_cast<pma::Segment3D*>(prev);
513 
514  SortedObjectBase* prevVtx = seg->Prev();
515  if (prevVtx->Prev()) nSeg++;
516  nSeg += prevVtx->NextCount();
517  }
518  else if (next) {
519  seg = static_cast<pma::Segment3D*>(next);
520 
521  SortedObjectBase* nextVtx = seg->Next(0);
522  nSeg += nextVtx->NextCount() + 1;
523  }
524  else {
525  mf::LogWarning("pma::Node3D") << "pma::Node3D::Pi(): an isolated vertex?";
526  return 0.0;
527  }
528  if (nSeg == 1) pi_result = endSegWeight * seg->Length2();
529  return pi_result;
530  }
531 }
532 
533 double
534 pma::Node3D::Penalty(float endSegWeight) const
535 {
536  unsigned int nseg = 1;
537  double penalty = Pi(endSegWeight, true);
538 
539  pma::Node3D* v;
540  for (unsigned int i = 0; i < NextCount(); i++) {
541  v = static_cast<pma::Node3D*>(Next(i)->Next());
542  penalty += v->Pi(endSegWeight, false);
543  nseg++;
544  }
545  if (prev) {
546  v = static_cast<pma::Node3D*>(prev->Prev());
547  penalty += v->Pi(endSegWeight, false);
548  nseg++;
549  }
550  return penalty / nseg;
551 }
552 
553 double
555 {
556  unsigned int nhits = NPrecalcEnabledHits(); //NEnabledHits();
557  double mse = SumDist2();
558 
559  pma::Segment3D* seg;
560  for (unsigned int i = 0; i < NextCount(); i++) {
561  seg = static_cast<pma::Segment3D*>(Next(i));
562  nhits += seg->NPrecalcEnabledHits(); //NEnabledHits();
563  mse += seg->SumDist2();
564  }
565  if (prev) {
566  seg = static_cast<pma::Segment3D*>(prev);
567  nhits += seg->NPrecalcEnabledHits(); //NEnabledHits();
568  mse += seg->SumDist2();
569  }
570  if (!nhits)
571  return 0.0;
572  else
573  return mse / nhits;
574 }
575 
576 double
577 pma::Node3D::GetObjFunction(float penaltyValue, float endSegWeight) const
578 {
579  return Mse() + penaltyValue * (Penalty(endSegWeight) + PenaltyInWirePlane());
580 }
581 
582 double
583 pma::Node3D::MakeGradient(float penaltyValue, float endSegWeight)
584 {
585  double l1 = 0.0, l2 = 0.0, minLength2 = 0.0;
586  TVector3 tmp(fPoint3D), gpoint(fPoint3D);
587 
588  pma::Segment3D* seg;
589  if (prev) {
590  seg = static_cast<pma::Segment3D*>(prev);
591  l1 = seg->Length2();
592  }
593  if (next) {
594  seg = static_cast<pma::Segment3D*>(next);
595  l2 = seg->Length2();
596  }
597  if ((l1 > 0.01) && (l1 < l2))
598  minLength2 = l1;
599  else if ((l2 > 0.01) && (l2 < l1))
600  minLength2 = l2;
601  else
602  minLength2 = 0.01;
603 
604  double dxi = 0.001 * sqrt(minLength2);
605 
606  if (dxi < 6.0E-37) return 0.0;
607 
608  double gi, g0, gz;
609  gz = g0 = GetObjFunction(penaltyValue, endSegWeight);
610 
611  //if (fQPenaltyFactor > 0.0F) gz += fQPenaltyFactor * QPenalty(); <----------------------- maybe later..
612 
613  if (!fGradFixed[0]) // gradX
614  {
615  gpoint[0] = tmp[0] + dxi;
616  SetPoint3D(gpoint);
617  gi = GetObjFunction(penaltyValue, endSegWeight);
618  fGradient[0] = (g0 - gi) / dxi;
619 
620  gpoint[0] = tmp[0] - dxi;
621  SetPoint3D(gpoint);
622  gi = GetObjFunction(penaltyValue, endSegWeight);
623  fGradient[0] = 0.5 * (fGradient[0] + (gi - g0) / dxi);
624 
625  gpoint[0] = tmp[0];
626  }
627 
628  if (!fGradFixed[1]) // gradY
629  {
630  gpoint[1] = tmp[1] + dxi;
631  SetPoint3D(gpoint);
632  gi = GetObjFunction(penaltyValue, endSegWeight);
633  fGradient[1] = (g0 - gi) / dxi;
634 
635  gpoint[1] = tmp[1] - dxi;
636  SetPoint3D(gpoint);
637  gi = GetObjFunction(penaltyValue, endSegWeight);
638  fGradient[1] = 0.5 * (fGradient[1] + (gi - g0) / dxi);
639 
640  gpoint[1] = tmp[1];
641  }
642 
643  if (!fGradFixed[2]) // gradZ
644  {
645  gpoint[2] = tmp[2] + dxi;
646  SetPoint3D(gpoint);
647  gi = GetObjFunction(penaltyValue, endSegWeight);
648  //if (fQPenaltyFactor > 0.0F) gi += fQPenaltyFactor * QPenalty();
649  fGradient[2] = (gz - gi) / dxi;
650 
651  gpoint[2] = tmp[2] - dxi;
652  SetPoint3D(gpoint);
653  gi = GetObjFunction(penaltyValue, endSegWeight);
654  //if (fQPenaltyFactor > 0.0F) gi += fQPenaltyFactor * QPenalty();
655  fGradient[2] = 0.5 * (fGradient[2] + (gi - gz) / dxi);
656 
657  gpoint[2] = tmp[2];
658  }
659 
660  SetPoint3D(tmp);
661  if (fGradient.Mag2() < 6.0E-37) return 0.0;
662 
663  return g0;
664 }
665 
666 double
667 pma::Node3D::StepWithGradient(float alfa, float tol, float penalty, float weight)
668 {
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);
673 
674  g = MakeGradient(penalty, weight);
675  if (g < zero_tol) return 0.0;
676  g0 = g;
677 
678  //**** first three points ****//
679  alfa *= 0.8F;
680  t2 = 0.0;
681  g2 = g;
682  t3 = 0.0;
683  g3 = g;
684  do {
685  t1 = t2;
686  g1 = g2;
687  t2 = t3;
688  g2 = g3;
689 
690  alfa *= 1.25F;
691  t3 += alfa;
692  gpoint = tmp;
693  gpoint += (fGradient * t3);
694  if (!SetPoint3D(gpoint)) // stepped out of allowed volume
695  {
696  //std::cout << "**** SetPoint trimmed 1 ****" << std::endl;
697  g3 = GetObjFunction(penalty, weight);
698  if (g3 < g2)
699  return (g0 - g3) / g3; // exit with the node at the border
700  else {
701  SetPoint3D(tmp);
702  return 0.0;
703  } // exit with restored original position
704  }
705 
706  g3 = GetObjFunction(penalty, weight);
707 
708  if (g3 < zero_tol) return 0.0;
709 
710  if (++steps > 1000) {
711  SetPoint3D(tmp);
712  return 0.0;
713  }
714 
715  } while (g3 < g2);
716  //****************************//
717 
718  //*** first step overshoot ***//
719  if (steps == 1) {
720  t2 = t3;
721  g2 = g3;
722  do {
723  t3 = t2;
724  g3 = g2;
725  t2 = (t1 * g3 + t3 * g1) / (g1 + g3);
726 
727  // small shift...
728  t2 = 0.05 * t3 + 0.95 * t2;
729 
730  // break: starting point is at the minimum
731  //if (t2 == t1) { SetPoint3D(tmp); return 0.0F; }
732 
733  // break: starting point is very close to the minimum
734  if (fabs(t2 - t1) < tol) {
735  SetPoint3D(tmp);
736  return 0.0;
737  }
738 
739  gpoint = tmp;
740  gpoint += (fGradient * t2);
741  if (!SetPoint3D(gpoint)) // select the best point to exit
742  {
743  //std::cout << "**** SetPoint trimmed 2 ****" << std::endl;
744  g2 = GetObjFunction(penalty, weight);
745  if (g2 < g0)
746  return (g0 - g2) / g2; // exit with the node at the border
747  else if (g1 < g0) {
748  gpoint = tmp;
749  gpoint += (fGradient * t1);
750  return (g0 - g1) / g1;
751  }
752  else if (g3 < g0) {
753  gpoint = tmp;
754  gpoint += (fGradient * t3);
755  return (g0 - g3) / g3;
756  }
757  else {
758  SetPoint3D(tmp);
759  return 0.0;
760  }
761  }
762  g2 = GetObjFunction(penalty, weight);
763 
764  if (g2 < zero_tol) return 0.0;
765  steps++;
766 
767  } while (g2 >= g1);
768  }
769  //****************************//
770 
771  while (fabs(t1 - t3) > tol) {
772  //*** 3-point minimization ***//
773  if ((fabs(t2 - t1) < eps) || (fabs(t2 - t3) < eps)) break; // minimum on the edge
774  if ((fabs(g2 - g1) < eps) && (fabs(g2 - g3) < eps)) break; // ~singularity
775 
776  p1 = (t2 - t1) * (g2 - g3);
777  p2 = (t2 - t3) * (g2 - g1);
778  if (fabs(p1 - p2) < eps) break; // ~linearity
779 
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);
782 
783  gpoint = tmp;
784  gpoint += (fGradient * t);
785  if (!SetPoint3D(gpoint)) // select the best point to exit
786  {
787  //std::cout << "**** SetPoint trimmed 3 ****" << std::endl;
788  g = GetObjFunction(penalty, weight);
789  if ((g < g0) && (g < g1) && (g < g3))
790  return (g0 - g) / g; // exit with the node at the border
791  else if ((g1 < g0) && (g1 < g3)) {
792  gpoint = tmp;
793  gpoint += (fGradient * t1);
794  return (g0 - g1) / g1;
795  }
796  else if (g3 < g0) {
797  gpoint = tmp;
798  gpoint += (fGradient * t3);
799  return (g0 - g3) / g3;
800  }
801  else {
802  SetPoint3D(tmp);
803  return 0.0;
804  }
805  }
806 
807  g = GetObjFunction(penalty, weight);
808  if (g < zero_tol) return 0.0;
809  steps++;
810  //****************************//
811 
812  //*** select next 3 points ***//
813  if (fabs(t - t2) < 0.2 * tol) break; // start in a new direction
814  if (g < g2) {
815  if (t < t2) {
816  t3 = t2;
817  g3 = g2;
818  }
819  else {
820  t1 = t2;
821  g1 = g2;
822  }
823  t2 = t;
824  g2 = g;
825  }
826  else {
827  if (t < t2) {
828  t1 = t;
829  g1 = g;
830  }
831  else {
832  t3 = t;
833  g3 = g;
834  }
835  }
836  //****************************//
837  }
838 
839  return (g0 - g) / g;
840 }
841 
842 void
843 pma::Node3D::Optimize(float penaltyValue, float endSegWeight)
844 {
845  if (!fFrozen) {
846  double dg = StepWithGradient(0.1F, 0.002F, penaltyValue, endSegWeight);
847  if (dg > 0.01) dg = StepWithGradient(0.03F, 0.0001F, penaltyValue, endSegWeight);
848  if (dg > 0.0) dg = StepWithGradient(0.03F, 0.0001F, penaltyValue, endSegWeight);
849  }
850 }
851 
852 void
854 {
855  if (!trk) {
856  // like in the base class:
857  fAssignedPoints.clear();
858  fAssignedHits.clear();
859  }
860  else {
861  std::vector<pma::Track3D*> to_check;
862  pma::Segment3D* seg;
863  if (Prev()) {
864  seg = static_cast<pma::Segment3D*>(Prev());
865  if (seg->Parent() != trk) to_check.push_back(seg->Parent());
866  }
867  for (unsigned int i = 0; i < NextCount(); i++) {
868  seg = static_cast<pma::Segment3D*>(Next(i));
869  if (seg->Parent() != trk) to_check.push_back(seg->Parent());
870  }
871 
872  unsigned int p = 0;
873  while (p < fAssignedPoints.size()) {
874  bool found = false;
875  for (size_t t = 0; t < to_check.size(); t++)
876  if (to_check[t]->HasRefPoint(fAssignedPoints[p])) {
877  found = true;
878  break;
879  }
880 
881  if (!found)
882  fAssignedPoints.erase(fAssignedPoints.begin() + p);
883  else
884  p++;
885  }
886 
887  unsigned int h = 0;
888  while (h < fAssignedHits.size()) {
889  bool found = false;
891 
892  for (size_t t = 0; (t < to_check.size()) && !found; t++)
893  for (size_t i = 0; i < to_check[t]->size(); i++) {
894  pma::Hit3D* pmaHit = static_cast<pma::Hit3D*>((*(to_check[t]))[i]);
895  if (hit == pmaHit) {
896  found = true;
897  break;
898  }
899  }
900 
901  if (!found)
902  fAssignedHits.erase(fAssignedHits.begin() + h);
903  else
904  h++;
905  }
906  }
907 
908  fHitsRadius = 0.0F;
909 }
size_t NPrecalcEnabledHits(void) const
Definition: PmaElement3D.h:76
bool HasPlane(unsigned int iplane) const
Returns whether a plane with index iplane is present in this TPC.
Definition: TPCGeo.h:175
TVector3 const & Point3D() const
Definition: PmaNode3D.h:45
TVector2 const & Projection2D(unsigned int view) const
Definition: PmaNode3D.h:55
double Length2() const override
Definition: PmaNode3D.cxx:299
static constexpr double g
Definition: Units.h:144
double Penalty(float endSegWeight) const
Definition: PmaNode3D.cxx:534
Implementation of the Projection Matching Algorithm.
TVector2 const & Point2D() const noexcept
Definition: PmaHit3D.h:72
double fMinZ
Definition: PmaNode3D.h:176
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:37
auto const tol
Definition: SurfXYZTest.cc:16
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
void ClearAssigned(pma::Track3D *trk=0) override
Definition: PmaNode3D.cxx:853
Implementation of the Projection Matching Algorithm.
double fDriftOffset
Definition: PmaNode3D.h:182
constexpr T pow(T x)
Definition: pow.h:72
pma::SortedObjectBase * prev
Definition: SortedObjects.h:54
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D point to the point 3D.
Definition: PmaNode3D.cxx:178
pma::Vector3D GetDirection3D() const override
Definition: PmaNode3D.cxx:206
bool LimitPoint3D()
Returns true if node position was trimmed to its TPC volume + fMargin.
Definition: PmaNode3D.cxx:124
virtual unsigned int NextCount(void) const
Definition: SortedObjects.h:84
std::vector< pma::Track3D * > GetBranches() const
Definition: PmaNode3D.cxx:463
void Optimize(float penaltyValue, float endSegWeight)
Definition: PmaNode3D.cxx:843
Planes which measure Z direction.
Definition: geo_types.h:132
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double Length2(void) const override
bool IsTPCEdge() const
Is the first/last in this TPC?
Definition: PmaNode3D.cxx:451
static QStrList * l
Definition: config.cpp:1044
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:31
weight
Definition: test.py:257
static bool fGradFixed[3]
Definition: PmaNode3D.h:187
art framework interface to geometry description
virtual pma::Vector3D GetDirection3D(void) const =0
Get 3D direction cosines corresponding to this element.
double SegmentCosWirePlane() const
Definition: PmaNode3D.cxx:333
int TPC(void) const
TPC index or -1 if out of any TPC.
Definition: PmaElement3D.h:34
double PenaltyInWirePlane() const
Definition: PmaNode3D.cxx:412
TVector2 fProj2D[3]
Definition: PmaNode3D.h:180
double Mse() const
Definition: PmaNode3D.cxx:554
Planes which measure U.
Definition: geo_types.h:129
double GetDistToWall() const
Definition: PmaNode3D.cxx:82
virtual unsigned int NextCount(void) const
Definition: SortedObjects.h:46
double fMaxX
Definition: PmaNode3D.h:176
double PiInWirePlane() const
Definition: PmaNode3D.cxx:390
std::vector< TVector3 * > fAssignedPoints
Definition: PmaElement3D.h:117
void UpdateProj2D()
Definition: PmaNode3D.cxx:159
double SegmentCos() const
Cosine of 3D angle between connected segments.
Definition: PmaNode3D.cxx:312
bool SetPoint3D(const TVector3 &p3d)
Definition: PmaNode3D.cxx:167
double MinZ() const
Returns the world z coordinate of the start of the box.
double StepWithGradient(float alfa, float tol, float penalty, float weight)
Definition: PmaNode3D.cxx:667
p
Definition: test.py:223
double SegmentCosTransverse() const
Definition: PmaNode3D.cxx:352
std::vector< pma::Hit3D * > fAssignedHits
Definition: PmaElement3D.h:116
string tmp
Definition: languages.py:63
double EndPtCos2Transverse() const
Definition: PmaNode3D.cxx:372
bool SameTPC(const TVector3 &p3d, float margin=0.0F) const
Check if p3d is in the same TPC as the node.
Definition: PmaNode3D.cxx:102
double fMaxY
Definition: PmaNode3D.h:176
void SetProjection(const TVector2 &p, float b)
Definition: PmaHit3D.h:148
double SumDist2(void) const
Detector simulation of raw signals on wires.
double fMaxZ
Definition: PmaNode3D.h:176
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)
Definition: PmaNode3D.cxx:583
double fMinY
Definition: PmaNode3D.h:176
unsigned int View2D() const noexcept
Definition: PmaHit3D.h:93
Implementation of the Projection Matching Algorithm.
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
Definition: SortedObjects.h:79
Encapsulate the construction of a single detector plane.
double GetObjFunction(float penaltyValue, float endSegWeight) const
Objective function minimized during oprimization.
Definition: PmaNode3D.cxx:577
double MaxZ() const
Returns the world z coordinate of the end of the box.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void SetPoint3D(const TVector3 &p3d)
Definition: PmaHit3D.h:61
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double > > Vector2D
Definition: Utilities.h:30
double fHitsRadius
Definition: PmaElement3D.h:122
bool IsBranching() const
Belongs to more than one track?
Definition: PmaNode3D.cxx:436
pma::SortedObjectBase * next
Definition: SortedObjects.h:53
static bool * b
Definition: config.cpp:1043
double SumDist2Hits() const override
Definition: PmaNode3D.cxx:190
geo::TPCGeo const & fTpcGeo
Definition: PmaNode3D.h:174
TVector3 fPoint3D
Definition: PmaNode3D.h:179
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
virtual pma::SortedObjectBase * Prev(void) const
Definition: SortedObjects.h:44
static double fMargin
Definition: PmaNode3D.h:188
LArSoft geometry interface.
Definition: ChannelGeo.h:16
void SetProjection(pma::Hit3D &h) const override
Set hit 3D position and its 2D projection to the vertex.
Definition: PmaNode3D.cxx:224
double MinY() const
Returns the world y coordinate of the start of the box.
pma::Track3D * Parent(void) const
Definition: PmaSegment3D.h:68
size_t NHits(void) const
Definition: PmaElement3D.h:74
double Pi(float endSegWeight, bool doAsymm) const
Definition: PmaNode3D.cxx:477
virtual pma::SortedObjectBase * Next(unsigned int index=0) const
Definition: SortedObjects.h:45
double PlaneCoordinate(geo::Point_t const &point) const
Returns the coordinate of the point on the plane.
Definition: PlaneGeo.h:861
bool fIsVertex
Definition: PmaNode3D.h:185
double Length(void) const
Definition: PmaElement3D.h:52
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
static float OptFactor(unsigned int view)
Definition: PmaElement3D.h:106
double fMinX
Definition: PmaNode3D.h:176
Encapsulate the construction of a single detector plane.
TVector3 fGradient
Definition: PmaNode3D.h:184