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