All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PmaSegment3D.cxx
Go to the documentation of this file.
1 /**
2  * @file PmaSegment3D.cxx
3  *
4  * @author D.Stefan and R.Sulej
5  *
6  * @brief Implementation of the Projection Matching Algorithm
7  *
8  * 3D track segment. See PmaTrack3D.h file for details.
9  */
10 
11 #include <math.h>
12 
13 #include "Math/GenVector/DisplacementVector2D.h"
17 
18 #include "messagefacility/MessageLogger/MessageLogger.h"
19 
21  SortedObjectBase(vstart, vstop),
22  fParent(trk)
23 {
24  if (vstart->TPC() == vstop->TPC()) fTPC = vstart->TPC();
25  if (vstart->Cryo() == vstop->Cryo()) fCryo = vstart->Cryo();
26 }
27 
28 double pma::Segment3D::GetDistance2To(const TVector3& p3d) const
29 {
30  pma::Node3D* v0 = static_cast< pma::Node3D* >(prev);
31  pma::Node3D* v1 = static_cast< pma::Node3D* >(next);
32  return GetDist2(p3d, v0->Point3D(), v1->Point3D());
33 }
34 
35 double pma::Segment3D::GetDistance2To(const TVector2& p2d, unsigned int view) const
36 {
37  pma::Node3D* v0 = static_cast< pma::Node3D* >(prev);
38  pma::Node3D* v1 = static_cast< pma::Node3D* >(next);
39  return GetDist2(p2d, v0->Projection2D(view), v1->Projection2D(view));
40 }
41 
42 double pma::Segment3D::SumDist2Hits(void) const
43 {
44  pma::Node3D* v0 = static_cast< pma::Node3D* >(prev);
45  pma::Node3D* v1 = static_cast< pma::Node3D* >(next);
46 
47  double sum = 0.0F;
48  for (auto h : fAssignedHits)
49  {
50  if (h->IsEnabled())
51  {
52  unsigned int view = h->View2D();
53 
54  sum += OptFactor(view) * h->GetSigmaFactor() // alpha_i * (hit_amp / hit_max_amp)
55  * GetDist2(h->Point2D(), v0->Projection2D(view), v1->Projection2D(view));
56  }
57  }
58  return sum;
59 }
60 
62 {
63  pma::Node3D* v0 = static_cast< pma::Node3D* >(prev);
64  pma::Node3D* v1 = static_cast< pma::Node3D* >(next);
66  v1->Point3D().X() - v0->Point3D().X(),
67  v1->Point3D().Y() - v0->Point3D().Y(),
68  v1->Point3D().Z() - v0->Point3D().Z());
69  return dir.Unit();
70 }
71 
72 TVector3 pma::Segment3D::GetProjection(const TVector2& p, unsigned int view) const
73 {
74  pma::Node3D* vStart = static_cast< pma::Node3D* >(prev);
75  pma::Node3D* vStop = static_cast< pma::Node3D* >(next);
76 
77  TVector2 v0(p);
78  v0 -= vStart->Projection2D(view);
79 
80  TVector2 v1(vStop->Projection2D(view));
81  v1 -= vStart->Projection2D(view);
82 
83  TVector3 v3d(vStop->Point3D());
84  v3d -= vStart->Point3D();
85 
86  TVector3 v3dStart(vStart->Point3D());
87  TVector3 v3dStop(vStop->Point3D());
88 
89  double v0Norm = v0.Mod();
90  double v1Norm = v1.Mod();
91 
92  TVector3 result(0, 0, 0);
93  if (v1Norm > 1.0E-6)// 0.01mm
94  {
95  double mag = v0Norm * v1Norm;
96  double cosine = 0.0;
97  if (mag != 0.0) cosine = v0 * v1 / mag;
98  double b = v0Norm * cosine / v1Norm;
99 
100  if (b < 1.0)
101  {
102  result = v3dStart;
103  if (b > 0.0) result += (v3d * b);
104  }
105  else result = v3dStop;
106  }
107  else // segment 2D projection is almost a point
108  {
109  mf::LogWarning("pma::Segment3D") << "Short segment projection.";
110 
111  result = v3dStart;
112  result += v3dStop;
113  result *= 0.5;
114  }
115  return result;
116 }
117 
118 TVector3 pma::Segment3D::GetUnconstrainedProj3D(const TVector2& p2d, unsigned int view) const
119 {
120  pma::Node3D* vStart = static_cast< pma::Node3D* >(prev);
121  pma::Node3D* vStop = static_cast< pma::Node3D* >(next);
122 
123  TVector2 v0(p2d);
124  v0 -= vStart->Projection2D(view);
125 
126  TVector2 v1(vStop->Projection2D(view));
127  v1 -= vStart->Projection2D(view);
128 
129  TVector3 v3d(vStop->Point3D());
130  v3d -= vStart->Point3D();
131 
132  double v0Norm = v0.Mod();
133  double v1Norm = v1.Mod();
134  if (v1Norm > 1.0E-6) // 0.01mm
135  {
136  double mag = v0Norm * v1Norm;
137  double cosine = 0.0;
138  if (mag != 0.0) cosine = v0 * v1 / mag;
139  double b = v0Norm * cosine / v1Norm;
140 
141  return vStart->Point3D() + (v3d * b);
142  }
143  else // segment 2D projection is almost a point
144  {
145  v3d = vStart->Point3D();
146  v3d += vStop->Point3D();
147  v3d *= 0.5;
148 
149  return v3d;
150  }
151 }
152 
154 {
155  pma::Node3D* vStart = static_cast< pma::Node3D* >(prev);
156  pma::Node3D* vStop = static_cast< pma::Node3D* >(next);
157 
158  auto const & pointStart = vStart->Point3D();
159  auto const & pointStop = vStop->Point3D();
160 
161  auto const & projStart = vStart->Projection2D(h.View2D());
162  auto const & projStop = vStop->Projection2D(h.View2D());
163 
164  pma::Vector2D v0(
165  h.Point2D().X() - projStart.X(),
166  h.Point2D().Y() - projStart.Y());
167 
168  pma::Vector2D v1(
169  projStop.X() - projStart.X(),
170  projStop.Y() - projStart.Y());
171 
172  pma::Vector3D v3d(
173  pointStop.X() - pointStart.X(),
174  pointStop.Y() - pointStart.Y(),
175  pointStop.Z() - pointStart.Z());
176 
177  double v0Norm = sqrt(v0.Mag2());
178  double v1Norm = sqrt(v1.Mag2());
179  if (v1Norm > 1.0E-6) // 0.01mm
180  {
181  double mag = v0Norm * v1Norm;
182  double cosine = 0.0;
183  if (mag != 0.0) cosine = v0.Dot(v1) / mag;
184  double b = v0Norm * cosine / v1Norm;
185 
186  pma::Vector2D p(projStart.X(), projStart.Y());
187  p += (v1 * b);
188  v3d *= b;
189 
190  h.SetProjection(p.X(), p.Y(), (float)b);
191  h.SetPoint3D(
192  pointStart.X() + v3d.X(),
193  pointStart.Y() + v3d.Y(),
194  pointStart.Z() + v3d.Z());
195  }
196  else // segment 2D projection is almost a point
197  {
198  h.SetProjection(
199  0.5 * (projStart.X() + projStop.X()),
200  0.5 * (projStart.Y() + projStop.Y()), 0.0F);
201 
202  h.SetPoint3D(
203  0.5 * (pointStart.X() + pointStop.X()),
204  0.5 * (pointStart.Y() + pointStop.Y()),
205  0.5 * (pointStart.Z() + pointStop.Z()));
206  }
207 }
208 
209 double pma::Segment3D::Length2(void) const
210 {
211  if (prev && next)
212  return pma::Dist2( ((pma::Node3D*)prev)->Point3D(), ((pma::Node3D*)next)->Point3D() );
213  else
214  {
215  mf::LogError("pma::Segment3D") << "Segment endpoints not set.";
216  return 0.0;
217  }
218 }
219 
220 
221 double pma::Segment3D::GetDist2(const TVector3& psrc, const TVector3& p0, const TVector3& p1)
222 {
223  pma::Vector3D v0(psrc.X() - p0.X(), psrc.Y() - p0.Y(), psrc.Z() - p0.Z());
224  pma::Vector3D v1(p1.X() - p0.X(), p1.Y() - p0.Y(), p1.Z() - p0.Z());
225  pma::Vector3D v2(psrc.X() - p1.X(), psrc.Y() - p1.Y(), psrc.Z() - p1.Z());
226 
227  double v1Norm2 = v1.Mag2();
228  if (v1Norm2 >= 1.0E-6) // >= 0.01mm
229  {
230  double v0v1 = v0.Dot(v1);
231  double v2v1 = v2.Dot(v1);
232  double v0Norm2 = v0.Mag2();
233  double v2Norm2 = v2.Mag2();
234 
235  double result = 0.0;
236  if ((v0v1 > 0.0) && (v2v1 < 0.0))
237  {
238  double cosine01_square = 0.0;
239  double mag01_square = v0Norm2 * v1Norm2;
240  if (mag01_square != 0.0) cosine01_square = v0v1 * v0v1 / mag01_square;
241 
242  result = (1.0 - cosine01_square) * v0Norm2;
243  }
244  else // increase distance to prefer hit assigned to the vertex, not segment
245  {
246  if (v0v1 <= 0.0) result = 1.0001 * v0Norm2;
247  else result = 1.0001 * v2Norm2;
248  }
249 
250  if (result >= 0.0) return result;
251  else return 0.0;
252  }
253  else // short segment or its projection
254  {
255  double dx = 0.5 * (p0.X() + p1.X()) - psrc.X();
256  double dy = 0.5 * (p0.Y() + p1.Y()) - psrc.Y();
257  double dz = 0.5 * (p0.Z() + p1.Z()) - psrc.Z();
258  return dx * dx + dy * dy + dz * dz;
259  }
260 }
261 
262 double pma::Segment3D::GetDist2(const TVector2& psrc, const TVector2& p0, const TVector2& p1)
263 {
264  pma::Vector2D v0(psrc.X() - p0.X(), psrc.Y() - p0.Y());
265  pma::Vector2D v1(p1.X() - p0.X(), p1.Y() - p0.Y());
266  pma::Vector2D v2(psrc.X() - p1.X(), psrc.Y() - p1.Y());
267 
268  double v1Norm2 = v1.Mag2();
269  if (v1Norm2 >= 1.0E-6) // >= 0.01mm
270  {
271  double v0v1 = v0.Dot(v1);
272  double v2v1 = v2.Dot(v1);
273  double v0Norm2 = v0.Mag2();
274  double v2Norm2 = v2.Mag2();
275 
276  double result = 0.0;
277  if ((v0v1 > 0.0) && (v2v1 < 0.0))
278  {
279  double cosine01_square = 0.0;
280  double mag01_square = v0Norm2 * v1Norm2;
281  if (mag01_square != 0.0) cosine01_square = v0v1 * v0v1 / mag01_square;
282 
283  result = (1.0 - cosine01_square) * v0Norm2;
284  }
285  else // increase distance to prefer hit assigned to the vertex, not segment
286  {
287  if (v0v1 <= 0.0) result = 1.0001 * v0Norm2;
288  else result = 1.0001 * v2Norm2;
289  }
290  if (result >= 0.0) return result;
291  else return 0.0;
292  }
293  else // short segment or its projection
294  {
295  double dx = 0.5 * (p0.X() + p1.X()) - psrc.X();
296  double dy = 0.5 * (p0.Y() + p1.Y()) - psrc.Y();
297  return dx * dx + dy * dy;
298  }
299 }
TVector3 const & Point3D() const
Definition: PmaNode3D.h:45
TVector2 const & Projection2D(unsigned int view) const
Definition: PmaNode3D.h:55
double Dist2(const TVector2 &v1, const TVector2 &v2)
double GetDistance2To(const TVector3 &p3d) const override
Distance [cm] from the 3D segment to the point 3D.
Implementation of the Projection Matching Algorithm.
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
pdgs p
Definition: selectors.fcl:22
process_name E
double SumDist2Hits(void) const override
recob::tracking::Vector_t Vector3D
int TPC(void) const
TPC index or -1 if out of any TPC.
Definition: PmaElement3D.h:35
while getopts h
double Length2(void) const override
TVector3 GetProjection(const TVector2 &p, unsigned int view) const
Get 3D projection of a 2D point from the view.
unsigned int View2D() const noexcept
Definition: PmaHit3D.h:93
void SetProjection(pma::Hit3D &h) const override
Set hit 3D position and its 2D projection to the vertex.
Implementation of the Projection Matching Algorithm.
void SetProjection(const TVector2 &p, float b)
Definition: PmaHit3D.h:148
tuple dir
Definition: dropbox.py:28
TVector3 GetUnconstrainedProj3D(const TVector2 &p2d, unsigned int view) const override
TVector2 const & Point2D() const noexcept
Definition: PmaHit3D.h:72
int Cryo(void) const
Cryostat index or -1 if out of any cryostat.
Definition: PmaElement3D.h:37
void SetPoint3D(const TVector3 &p3d)
Definition: PmaHit3D.h:61
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double > > Vector2D
physics associatedGroupsWithLeft p1
pma::Vector3D GetDirection3D(void) const override
Get 3D direction cosines of this segment.
static double GetDist2(const TVector3 &psrc, const TVector3 &p0, const TVector3 &p1)