ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtPatternLine.cxx
Go to the documentation of this file.
1 #include "AtPatternLine.h"
2 // IWYU pragma: no_include <ext/alloc_traits.h>
3 #include <FairLogger.h>
4 
5 #include <Math/Vector3D.h> // for DisplacementVector3D, operator*
6 #include <TEveLine.h>
7 #include <TMath.h>
8 
9 #include <algorithm> // for min
10 #include <cmath> // for cos, sin, pow, sqrt, acos, atan, fabs
11 
12 class TEveElement;
13 
14 using namespace AtPatterns;
15 
17 
19 
20 TEveElement *AtPatternLine::GetEveElement() const
21 {
22  return AtPatternLine::GetEveLine(250);
23 }
24 
32 double AtPatternLine::parameterAtPoint(const XYZPoint &compPoint) const
33 {
34  return (compPoint - GetPoint()).Dot(GetDirection()) / GetDirection().Mag2();
35 }
36 
38 {
39  auto t = parameterAtPoint(point);
40  return GetPoint() + t * GetDirection();
41 }
42 
43 Double_t AtPatternLine::DistanceToPattern(const XYZPoint &point) const
44 {
45  // Use this rather than parameterAtPoint because it is faster
46  auto vec = GetPoint() - point;
47  auto nD = GetDirection().Cross(vec);
48  double dist2 = nD.Mag2() / GetDirection().Mag2();
49 
50  return std::sqrt(dist2);
51 }
52 
53 void AtPatternLine::DefinePattern(const std::vector<XYZPoint> &points)
54 {
55  if (points.size() != fNumPoints)
56  LOG(error) << "Trying to create pattern with wrong number of points " << points.size();
57 
58  auto fPoint = points[0];
59  auto fDirection = points[1] - points[0];
60  if (fDirection.Z() != 0)
61  fDirection /= fabs(fDirection.Z());
62 
63  fPatternPar = {fPoint.X(), fPoint.Y(), fPoint.Z(), fDirection.X(), fDirection.Y(), fDirection.Z()};
64 }
65 
75 {
76  return GetPoint() + z * GetDirection();
77 }
78 
79 void AtPatternLine::FitPattern(const std::vector<XYZPoint> &points, const std::vector<double> &charge)
80 {
81  //------3D Line Regression
82  //----- adapted from: http://fr.scribd.com/doc/31477970/Regressions-et-trajectoires-3D
83  int R, C;
84  double Q;
85  double Xm, Ym, Zm;
86  double Xh, Yh, Zh;
87  double a, b;
88  double Sxx, Sxy, Syy, Sxz, Szz, Syz;
89  double theta;
90  double K11, K22, K12, K10, K01, K00;
91  double c0, c1, c2;
92  double p, q, r, dm2;
93  double rho, phi;
94 
95  Q = Xm = Ym = Zm = 0.;
96  double total_charge = 0;
97  Sxx = Syy = Szz = Sxy = Sxz = Syz = 0.;
98  bool doChargeWeight = points.size() == charge.size();
99 
100  for (int i = 0; i < points.size(); ++i) {
101  const auto hitQ = doChargeWeight ? charge[i] : 1;
102  const auto &pos = points[i];
103  fTotCharge += hitQ;
104  Q += hitQ / 10.;
105  Xm += pos.X() * hitQ / 10.;
106  Ym += pos.Y() * hitQ / 10.;
107  Zm += pos.Z() * hitQ / 10.;
108  Sxx += pos.X() * pos.X() * hitQ / 10.;
109  Syy += pos.Y() * pos.Y() * hitQ / 10.;
110  Szz += pos.Z() * pos.Z() * hitQ / 10.;
111  Sxy += pos.X() * pos.Y() * hitQ / 10.;
112  Sxz += pos.X() * pos.Z() * hitQ / 10.;
113  Syz += pos.Y() * pos.Z() * hitQ / 10.;
114  }
115 
116  Xm /= Q;
117  Ym /= Q;
118  Zm /= Q;
119  Sxx /= Q;
120  Syy /= Q;
121  Szz /= Q;
122  Sxy /= Q;
123  Sxz /= Q;
124  Syz /= Q;
125  Sxx -= (Xm * Xm);
126  Syy -= (Ym * Ym);
127  Szz -= (Zm * Zm);
128  Sxy -= (Xm * Ym);
129  Sxz -= (Xm * Zm);
130  Syz -= (Ym * Zm);
131 
132  theta = 0.5 * atan((2. * Sxy) / (Sxx - Syy));
133 
134  K11 = (Syy + Szz) * pow(cos(theta), 2) + (Sxx + Szz) * pow(sin(theta), 2) - 2. * Sxy * cos(theta) * sin(theta);
135  K22 = (Syy + Szz) * pow(sin(theta), 2) + (Sxx + Szz) * pow(cos(theta), 2) + 2. * Sxy * cos(theta) * sin(theta);
136  // K12 = -Sxy * (pow(cos(theta), 2) - pow(sin(theta), 2)) + (Sxx - Syy) * cos(theta) * sin(theta);
137  K10 = Sxz * cos(theta) + Syz * sin(theta);
138  K01 = -Sxz * sin(theta) + Syz * cos(theta);
139  K00 = Sxx + Syy;
140 
141  c2 = -K00 - K11 - K22;
142  c1 = K00 * K11 + K00 * K22 + K11 * K22 - K01 * K01 - K10 * K10;
143  c0 = K01 * K01 * K11 + K10 * K10 * K22 - K00 * K11 * K22;
144 
145  p = c1 - pow(c2, 2) / 3.;
146  q = 2. * pow(c2, 3) / 27. - c1 * c2 / 3. + c0;
147  r = pow(q / 2., 2) + pow(p, 3) / 27.;
148 
149  if (r > 0)
150  dm2 = -c2 / 3. + pow(-q / 2. + sqrt(r), 1. / 3.) + pow(-q / 2. - sqrt(r), 1. / 3.);
151  else {
152  rho = sqrt(-pow(p, 3) / 27.);
153  phi = acos(-q / (2. * rho));
154  dm2 = std::min(-c2 / 3. + 2. * pow(rho, 1. / 3.) * cos(phi / 3.),
155  std::min(-c2 / 3. + 2. * pow(rho, 1. / 3.) * cos((phi + 2. * TMath::Pi()) / 3.),
156  -c2 / 3. + 2. * pow(rho, 1. / 3.) * cos((phi + 4. * TMath::Pi()) / 3.)));
157  }
158 
159  a = -K10 * cos(theta) / (K11 - dm2) + K01 * sin(theta) / (K22 - dm2);
160  b = -K10 * sin(theta) / (K11 - dm2) - K01 * cos(theta) / (K22 - dm2);
161 
162  Xh = ((1. + b * b) * Xm - a * b * Ym + a * Zm) / (1. + a * a + b * b);
163  Yh = ((1. + a * a) * Ym - a * b * Xm + b * Zm) / (1. + a * a + b * b);
164  Zh = ((a * a + b * b) * Zm + a * Xm + b * Ym) / (1. + a * a + b * b);
165 
166  // First 3 are point1. Second 3 are point 2
167  XYZPoint p1 = {Xm, Ym, Zm};
168  XYZPoint p2 = {Xh, Yh, Zh};
169  DefinePattern({p1, p2});
170  fChi2 = (fabs(dm2 / Q));
171  fNFree = points.size() - 6;
172  fTotCharge = Q * 10.;
173 }
174 
175 TEveLine *AtPatternLine::GetEveLine(Double_t rMax) const
176 {
177  auto retLine = new TEveLine(); // NOLINT these will be owned by TEve classes
178  Double_t tMin = -10, tMax = 10, deltaPar = 0.05;
179  std::vector<Double_t> tminmax;
180  tminmax = lineIntersecR(rMax, tMin, tMax); // ex: rMax=250 is the max. radius where the lines are stopped
181  if (tminmax.size() == 2) {
182  tMin = tminmax.at(0);
183  tMax = tminmax.at(1);
184  }
185  if (tMin > tMax) {
186  Double_t tBuff = tMax;
187  tMax = tMin;
188  tMin = tBuff;
189  }
190  for (int i = 0; i <= (Int_t)((tMax - tMin) / deltaPar); i++) {
191  auto t = tMin + i * deltaPar;
192  auto pos = GetPointAt(t) / 10.; // TEve is all in units cm
193  retLine->SetNextPoint(pos.X(), pos.Y(), pos.Z());
194  }
195  return retLine;
196 }
197 
198 std::vector<Double_t> AtPatternLine::lineIntersecR(Double_t rMax, Double_t tMin, Double_t tMax) const
199 {
200  std::vector<Double_t> result;
201  Double_t a = 0, b = 0, c = 0, sol1 = 0, sol2 = 0;
202  a = pow(fPatternPar[3], 2) + pow(fPatternPar[4], 2);
203  b = 2 * (fPatternPar[0] * fPatternPar[3] + fPatternPar[1] * fPatternPar[4]);
204  c = pow(fPatternPar[0], 2) + pow(fPatternPar[1], 2) - pow(rMax, 2);
205  if (b * b - 4 * a * c >= 0) {
206  sol1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
207  sol2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
208  result.push_back(sol1);
209  result.push_back(sol2);
210  }
211  return result;
212 }
AtPatterns::AtPatternLine::DistanceToPattern
virtual Double_t DistanceToPattern(const XYZPoint &point) const override
Closest distance to pattern.
Definition: AtPatternLine.cxx:43
AtPatterns::AtPatternLine::AtPatternLine
AtPatternLine()
Definition: AtPatternLine.cxx:18
ClassImp
ClassImp(AtPatternLine)
AtPatterns::AtPatternLine::GetPoint
XYZPoint GetPoint() const
Definition: AtPatternLine.h:34
AtPatterns::AtPatternLine::XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPatternLine.h:30
c2
constexpr auto c2
Definition: AtRadialChargeModel.cxx:21
AtPatterns::AtPattern::fNFree
Int_t fNFree
Definition: AtPattern.h:47
AtPatterns::AtPatternLine
Describes a linear track.
Definition: AtPatternLine.h:28
AtPatterns::AtPatternLine::ClosestPointOnPattern
virtual XYZPoint ClosestPointOnPattern(const XYZPoint &point) const override
Closest point on pattern.
Definition: AtPatternLine.cxx:37
AtPatterns::AtPatternLine::FitPattern
virtual void FitPattern(const std::vector< XYZPoint > &points, const std::vector< double > &charge) override
Definition: AtPatternLine.cxx:79
AtPatterns::AtPatternLine::parameterAtPoint
double parameterAtPoint(const XYZPoint &point) const
Get the parameter closes to compPoint.
Definition: AtPatternLine.cxx:32
AtPatterns::AtPattern
Describes a shape in 3D space.
Definition: AtPattern.h:40
AtPatternLine.h
AtPatterns::AtPatternLine::GetEveLine
TEveLine * GetEveLine(Double_t rMax=250) const
Definition: AtPatternLine.cxx:175
AtPatterns::AtPatternLine::GetPointAt
virtual XYZPoint GetPointAt(double z) const override
Get point on line at z.
Definition: AtPatternLine.cxx:74
AtPatterns::AtPatternLine::GetEveElement
virtual TEveElement * GetEveElement() const override
Get visual representation of pattern.
Definition: AtPatternLine.cxx:20
AtPatterns::AtPattern::fChi2
Double_t fChi2
Definition: AtPattern.h:46
AtPatterns
Definition: AtFissionEvent.h:21
AtPatterns::AtPattern::fPatternPar
std::vector< Double_t > fPatternPar
Definition: AtPattern.h:45
AtPatterns::AtPatternLine::lineIntersecR
std::vector< Double_t > lineIntersecR(Double_t rMax, Double_t tMin, Double_t tMax) const
Definition: AtPatternLine.cxx:198
AtPatterns::AtPattern::fTotCharge
Double_t fTotCharge
Definition: AtPattern.h:49
AtPatterns::AtPattern::fNumPoints
const Int_t fNumPoints
Definition: AtPattern.h:48
AtPatterns::AtPatternLine::GetDirection
XYZVector GetDirection() const
Definition: AtPatternLine.h:35
c
constexpr auto c
Definition: AtRadialChargeModel.cxx:20
AtPatterns::AtPatternLine::DefinePattern
virtual void DefinePattern(const std::vector< XYZPoint > &points) override
Define based on points.
Definition: AtPatternLine.cxx:53
AtPatterns::AtPattern::XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPattern.h:42