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