LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Utilities.cxx
Go to the documentation of this file.
1 
13 
15 #include "cetlib/pow.h"
17 
18 #include "TMatrixT.h"
19 #include "TVector2.h"
20 #include "TVector3.h"
21 #include "TVectorT.h"
22 
23 #include <cmath>
24 #include <utility>
25 #include <vector>
26 
34 
35 #include "range/v3/algorithm.hpp"
36 #include "range/v3/numeric.hpp"
37 #include "range/v3/view.hpp"
38 
39 double pma::Dist2(const TVector2& v1, const TVector2& v2)
40 {
41  double const dx = v1.X() - v2.X(), dy = v1.Y() - v2.Y();
42  return cet::sum_of_squares(dx, dy);
43 }
44 double pma::Dist2(const Vector2D& v1, const Vector2D& v2)
45 {
46  double const dx = v1.X() - v2.X(), dy = v1.Y() - v2.Y();
47  return cet::sum_of_squares(dx, dy);
48 }
49 
50 size_t pma::GetHitsCount(const std::vector<pma::Hit3D*>& hits, unsigned int view)
51 {
52  if (view == geo::kUnknown) { return hits.size(); }
53  return ranges::count_if(hits, [view](auto hit) { return view == hit->View2D(); });
54 }
55 
56 double pma::GetSummedADC(const std::vector<pma::Hit3D*>& hits, unsigned int view)
57 {
58  using namespace ranges;
59  auto to_summed_adc = [](auto hit) { return hit->SummedADC(); };
60  if (view == geo::kUnknown) { return accumulate(hits | views::transform(to_summed_adc), 0.); }
61  return accumulate(hits | views::filter([view](auto hit) { return view == hit->View2D(); }) |
62  views::transform(to_summed_adc),
63  0.);
64 }
65 
66 double pma::GetSummedAmpl(const std::vector<pma::Hit3D*>& hits, unsigned int view)
67 {
68  using namespace ranges;
69  auto to_amplitude = [](auto hit) { return hit->GetAmplitude(); };
70  if (view == geo::kUnknown) { return accumulate(hits | views::transform(to_amplitude), 0.); }
71  return accumulate(hits | views::filter([view](auto hit) { return view == hit->View2D(); }) |
72  views::transform(to_amplitude),
73  0.);
74 }
75 
76 double pma::GetHitsRadius3D(const std::vector<pma::Hit3D*>& hits, bool exact)
77 {
78  if (hits.empty()) return 0.0;
79 
80  if (!exact && (hits.size() < 5)) return 0.0;
81 
82  using namespace ranges;
83  auto to_3d_point = [](auto hit) -> decltype(auto) { return hit->Point3D(); };
84  auto const mean_point =
85  accumulate(hits | views::transform(to_3d_point), TVector3{}) * (1. / hits.size());
86 
87  auto to_dist2_from_mean = [&mean_point](auto hit) {
88  return pma::Dist2(hit->Point3D(), mean_point);
89  };
90  auto const max_r2 = max(hits | views::transform(to_dist2_from_mean));
91  return sqrt(max_r2);
92 }
93 
94 double pma::GetHitsRadius2D(const std::vector<pma::Hit3D*>& hits, bool exact)
95 {
96  if (hits.empty()) return 0.0;
97 
98  if (!exact && (hits.size() < 5)) return 0.0;
99 
100  using namespace ranges;
101  auto to_2d_point = [](auto hit) -> decltype(auto) { return hit->Point2D(); };
102  auto const mean_point =
103  accumulate(hits | views::transform(to_2d_point), TVector2{}) * (1. / hits.size());
104 
105  auto to_dist2_from_mean = [&mean_point](auto hit) {
106  return pma::Dist2(hit->Point2D(), mean_point);
107  };
108  auto const max_r2 = max(hits | views::transform(to_dist2_from_mean));
109  return sqrt(max_r2);
110 }
111 
112 double pma::GetSegmentProjVector(const TVector2& p, const TVector2& p0, const TVector2& p1)
113 {
114  TVector2 const v0(p - p0);
115  TVector2 const v1(p1 - p0);
116  return v0 * v1 / v1.Mod2();
117 }
118 
120  const pma::Vector2D& p0,
121  const pma::Vector2D& p1)
122 {
123  pma::Vector2D const v0(p - p0);
124  pma::Vector2D const v1(p1 - p0);
125  return v0.Dot(v1) / v1.Mag2();
126 }
127 
128 double pma::GetSegmentProjVector(const TVector3& p, const TVector3& p0, const TVector3& p1)
129 {
130  TVector3 const v0(p - p0);
131  TVector3 const v1(p1 - p0);
132  return v0.Dot(v1) / v1.Mag2();
133 }
134 
136  const pma::Vector3D& p0,
137  const pma::Vector3D& p1)
138 {
139  pma::Vector3D const v0(p - p0);
140  pma::Vector3D const v1(p1 - p0);
141  return v0.Dot(v1) / v1.Mag2();
142 }
143 
144 TVector2 pma::GetProjectionToSegment(const TVector2& p, const TVector2& p0, const TVector2& p1)
145 {
146  TVector2 const v1(p1 - p0);
147  double const b = GetSegmentProjVector(p, p0, p1);
148  return p0 + v1 * b;
149 }
150 
151 TVector3 pma::GetProjectionToSegment(const TVector3& p, const TVector3& p0, const TVector3& p1)
152 {
153  TVector3 const v1(p1 - p0);
154  double const b = GetSegmentProjVector(p, p0, p1);
155  return p0 + v1 * b;
156 }
157 
158 double pma::SolveLeastSquares3D(const std::vector<std::pair<TVector3, TVector3>>& lines,
159  TVector3& result)
160 {
161  // RS: please, ask me if you need examples/explanation of formulas as they
162  // are not easy to derive from the code solely; I have Mathcad sources that
163  // were used to test the solving method, weighting, etc.
164 
165  result.SetXYZ(0., 0., 0.);
166  if (lines.size() < 2) {
167  mf::LogError("pma::SolveLeastSquares3D") << "Need min. two lines.";
168  return -1.0;
169  }
170 
171  double m;
172  std::vector<TVectorT<double>> U, P;
173  for (size_t v = 0; v < lines.size(); v++) {
174  TVector3 point = lines[v].first;
175  TVector3 dir = lines[v].second;
176  dir -= point;
177  m = dir.Mag();
178  if (m > 0.0) {
179  dir *= 1.0 / m;
180 
181  P.push_back(TVectorT<double>(3));
182  P.back()[0] = point.X();
183  P.back()[1] = point.Y();
184  P.back()[2] = point.Z();
185 
186  U.push_back(TVectorT<double>(3));
187  U.back()[0] = dir.X();
188  U.back()[1] = dir.Y();
189  U.back()[2] = dir.Z();
190  }
191  else
192  mf::LogWarning("pma::SolveLeastSquares3D") << "Line undefined.";
193  }
194  if (P.size() < 2) {
195  mf::LogError("pma::SolveLeastSquares3D") << "Need min. two lines.";
196  return -1.0;
197  }
198 
199  TVectorT<double> x(3), y(3), w(3);
200  TMatrixT<double> A(3, 3);
201  double ur, uc, pc;
202  double s_uc2[3], s_ur_uc[3];
203  double s_p_uc2[3], s_p_ur_uc[3];
204 
205  w[0] = 1.0;
206  w[1] = 1.0;
207  w[2] = 1.0;
208  for (size_t r = 0; r < 3; r++) {
209  y[r] = 0.0;
210  for (size_t c = 0; c < 3; c++) {
211  s_uc2[c] = 0.0;
212  s_ur_uc[c] = 0.0;
213  s_p_uc2[c] = 0.0;
214  s_p_ur_uc[c] = 0.0;
215 
216  for (size_t v = 0; v < P.size(); v++) {
217  //w[1] = fWeights[v]; // to remember that individual coordinates can be supressed...
218  //w[2] = fWeights[v];
219 
220  ur = U[v][r];
221  uc = U[v][c];
222  pc = P[v][c];
223 
224  s_uc2[c] += w[r] * w[c] * (1 - uc * uc);
225  s_p_uc2[c] += w[r] * w[r] * pc * (1 - uc * uc);
226 
227  s_ur_uc[c] += w[r] * w[c] * ur * uc;
228  s_p_ur_uc[c] += w[r] * w[r] * pc * ur * uc;
229  }
230 
231  if (r == c) {
232  y[r] += s_p_uc2[c];
233  A(r, c) = s_uc2[c];
234  }
235  else {
236  y[r] -= s_p_ur_uc[c];
237  A(r, c) = -s_ur_uc[c];
238  }
239  }
240  }
241  try {
242  x = A.InvertFast() * y;
243  }
244  catch (...) {
245  result.SetXYZ(0., 0., 0.);
246  return 1.0e12;
247  }
248 
249  result.SetXYZ(x[0], x[1], x[2]);
250 
251  double mse = 0.0;
252  for (size_t v = 0; v < lines.size(); v++) {
253  TVector3 const pproj = pma::GetProjectionToSegment(result, lines[v].first, lines[v].second);
254 
255  double const dx = result.X() - pproj.X(); // dx, dy, dz and the result point can be weighted
256  double const dy = result.Y() - pproj.Y(); // here (linearly) by each line uncertainty
257  double const dz = result.Z() - pproj.Z();
258  mse += cet::sum_of_squares(dx, dy, dz);
259  }
260  return mse / lines.size();
261 }
262 
263 TVector2 pma::GetProjectionToPlane(const TVector3& p,
264  unsigned int plane,
265  unsigned int tpc,
266  unsigned int cryo)
267 {
269 
270  return TVector2(
271  geom->Plane(geo::PlaneID(cryo, tpc, plane)).PlaneCoordinate(geo::vect::toPoint(p)), p.X());
272 }
273 
274 TVector2 pma::GetVectorProjectionToPlane(const TVector3& v,
275  unsigned int plane,
276  unsigned int tpc,
277  unsigned int cryo)
278 {
279  TVector3 v0_3d(0., 0., 0.);
280  TVector2 v0_2d = GetProjectionToPlane(v0_3d, plane, tpc, cryo);
281  TVector2 v1_2d = GetProjectionToPlane(v, plane, tpc, cryo);
282 
283  return v1_2d - v0_2d;
284 }
285 
287  unsigned int wire,
288  float drift,
289  unsigned int plane,
290  unsigned int tpc,
291  unsigned int cryo)
292 {
294  geo::PlaneID const id{cryo, tpc, plane};
295  return TVector2(geom->Plane(id).WirePitch() * wire, detProp.ConvertTicksToX(drift, id));
296 }
297 
299  float xw,
300  float yd,
301  unsigned int plane,
302  unsigned int tpc,
303  unsigned int cryo)
304 {
306  geo::PlaneID const id{cryo, tpc, plane};
307  return TVector2(xw / geom->Plane(id).WirePitch(), detProp.ConvertXToTicks(yd, id));
308 }
309 
311 {
312  if (h1 && h2) return h1->fSegFraction < h2->fSegFraction;
313  return false;
314 }
315 
317 {
318  if (h1 && h2) return h1->GetDist2ToProj() < h2->GetDist2ToProj();
319  return false;
320 }
321 
323 {
324  pma::Track3D* trk1 = t1.Track();
325  pma::Track3D* trk2 = t2.Track();
326  if (trk1 && trk2) {
327  double l1 = pma::Dist2(trk1->front()->Point3D(), trk1->back()->Point3D());
328  double l2 = pma::Dist2(trk2->front()->Point3D(), trk2->back()->Point3D());
329  return l1 > l2;
330  }
331  return false;
332 }
333 
334 pma::bSegmentProjLess::bSegmentProjLess(const TVector3& s0, const TVector3& s1)
335  : segStart(s0), segStop(s1)
336 {
337  if (s0 == s1) mf::LogError("pma::bSegmentProjLess") << "Vectors equal!";
338 }
Float_t x
Definition: compare.C:6
TRandom r
Definition: spectrum.C:23
double SolveLeastSquares3D(const std::vector< std::pair< TVector3, TVector3 >> &lines, TVector3 &result)
Definition: Utilities.cxx:158
double GetSummedAmpl(const std::vector< pma::Hit3D * > &hits, unsigned int view=geo::kUnknown)
Definition: Utilities.cxx:66
TTree * t1
Definition: plottest35.C:26
double GetHitsRadius2D(const std::vector< pma::Hit3D * > &hits, bool exact=false)
Definition: Utilities.cxx:94
Implementation of the Projection Matching Algorithm.
double Dist2(const TVector2 &v1, const TVector2 &v2)
Definition: Utilities.cxx:39
Unknown view.
Definition: geo_types.h:142
Float_t y
Definition: compare.C:6
pma::Hit3D const * front() const
Definition: PmaTrack3D.h:87
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
float fSegFraction
Definition: PmaHit3D.h:101
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
TVector3 const & Point3D() const
Definition: PmaHit3D.h:50
TVector2 WireDriftToCm(detinfo::DetectorPropertiesData const &detProp, unsigned int wire, float drift, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:286
bool operator()(pma::Hit3D *h1, pma::Hit3D *h2) const
Definition: Utilities.cxx:310
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double GetHitsRadius3D(const std::vector< pma::Hit3D * > &hits, bool exact=false)
Definition: Utilities.cxx:76
recob::tracking::Vector_t Vector3D
Definition: Utilities.h:34
double GetDist2ToProj() const
Definition: PmaHit3D.cxx:109
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
bSegmentProjLess(const TVector3 &s0, const TVector3 &s1)
Definition: Utilities.cxx:334
PlaneGeo const & Plane(PlaneID const &planeid) const
Returns the specified wire.
void hits()
Definition: readHits.C:15
size_t GetHitsCount(const std::vector< pma::Hit3D * > &hits, unsigned int view)
Definition: Utilities.cxx:50
TVector2 GetProjectionToSegment(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
Definition: Utilities.cxx:144
double ConvertXToTicks(double X, int p, int t, int c) const
Implementation of the Projection Matching Algorithm.
TVector2 GetVectorProjectionToPlane(const TVector3 &v, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:274
Detector simulation of raw signals on wires.
TTree * t2
Definition: plottest35.C:36
TH1F * h2
Definition: plot.C:44
double ConvertTicksToX(double ticks, int p, int t, int c) const
Track finding helper for the Projection Matching Algorithm.
Implementation of the Projection Matching Algorithm.
Encapsulate the construction of a single detector plane.
TDirectory * dir
Definition: macro.C:5
double GetSegmentProjVector(const TVector2 &p, const TVector2 &p0, const TVector2 &p1)
Definition: Utilities.cxx:112
TVector2 GetProjectionToPlane(const TVector3 &p, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:263
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
ROOT::Math::DisplacementVector2D< ROOT::Math::Cartesian2D< double > > Vector2D
Definition: Utilities.h:33
pma::Hit3D const * back() const
Definition: PmaTrack3D.h:88
TVector2 CmToWireDrift(detinfo::DetectorPropertiesData const &detProp, float xw, float yd, unsigned int plane, unsigned int tpc, unsigned int cryo)
Definition: Utilities.cxx:298
TH1F * h1
Definition: plot.C:41
double GetSummedADC(const std::vector< pma::Hit3D * > &hits, unsigned int view=geo::kUnknown)
Definition: Utilities.cxx:56
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
bool operator()(const pma::TrkCandidate &t1, const pma::TrkCandidate &t2) const
Definition: Utilities.cxx:322
pma::Track3D * Track() const
Float_t w
Definition: plot.C:20
double PlaneCoordinate(geo::Point_t const &point) const
Returns the coordinate of the point on the plane.
Definition: PlaneGeo.h:777
art framework interface to geometry description
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h:378
Encapsulate the construction of a single detector plane.
bool operator()(pma::Hit3D *h1, pma::Hit3D *h2) const
Definition: Utilities.cxx:316