ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtPatternY.cxx
Go to the documentation of this file.
1 #include "AtPatternY.h"
2 // IWYU pragma: no_include <ext/alloc_traits.h>
3 #include "AtPatternLine.h" // for AtPatternLine::XYZPoint, AtPatter...
4 
5 #include <FairLogger.h>
6 
7 #include <Math/Functor.h>
8 #include <Math/Point3D.h> // for DisplacementVector3D, operator*
9 #include <Math/Vector3D.h> // for DisplacementVector3D, operator*
10 #include <TEveCompound.h>
11 #include <TEveElement.h>
12 #include <TEveLine.h>
13 #include <TEvePointSet.h>
14 #include <TString.h> // for Form
15 
16 #include <Fit/FitConfig.h> // for FitConfig
17 #include <Fit/FitResult.h> // for FitResult
18 #include <Fit/Fitter.h>
19 #include <Fit/ParameterSettings.h> // for ParameterSettings
20 #include <algorithm> // for max, min_element, sort
21 #include <cmath> // for cos, sin, pow, sqrt, acos, atan, fabs
22 #include <set> // for set, _Rb_tree_const_iterator
23 #include <utility> // for swap
24 
25 using namespace AtPatterns;
26 
28 
30 
31 TEveElement *AtPatternY::GetEveElement() const
32 {
33  auto shape = new TEveCompound(); // NOLINT
34 
35  // Any element added with this color will be changed when the color of shape is changed later
36  shape->SetMainColor(kGreen);
37  shape->CSCApplyMainColorToMatchingChildren();
38  shape->OpenCompound();
39 
40  // Add lines to shape
41  auto beam = fBeam.GetEveElement();
42  dynamic_cast<TEveLine *>(beam)->SetName("beam");
43  beam->SetMainColor(kRed);
44  shape->AddElement(beam);
45 
46  for (int i = 0; i < 2; ++i) {
47  auto elem = fFragments[i].GetEveElement();
48  dynamic_cast<TEveLine *>(elem)->SetName(Form("frag_%d", i));
49  elem->SetMainColor(kGreen);
50  shape->AddElement(elem);
51  }
52 
53  // Add vertex to shape
54  auto vertex = new TEvePointSet("vertex", 1); // NOLINT
55  vertex->SetOwnIds(true);
56  vertex->SetMarkerSize(2);
57  vertex->SetMainColor(kGreen);
58  vertex->SetNextPoint(fBeam.GetPoint().X() / 10, fBeam.GetPoint().Y() / 10, fBeam.GetPoint().Z() / 10);
59  shape->AddElement(vertex);
60 
61  shape->CloseCompound();
62  return shape;
63 }
64 
66 {
67  // create a set of pairs with points and distance to pattern sorted by distance
68  auto comp = [](const std::pair<XYZPoint, double> &a, const std::pair<XYZPoint, double> &b) {
69  return a.second < b.second;
70  };
71  auto points = std::set<std::pair<XYZPoint, double>, decltype(comp)>(comp);
72 
73  points.insert({fBeam.ClosestPointOnPattern(point), fBeam.DistanceToPattern(point)});
74  for (const auto &ray : fFragments)
75  points.insert({ray.ClosestPointOnPattern(point), ray.DistanceToPattern(point)});
76 
77  // Get the closest point to the pattern
78  return points.begin()->first;
79 }
80 
81 Double_t AtPatternY::DistanceToPattern(const XYZPoint &point) const
82 {
83  std::vector<double> distances;
84  distances.push_back(fBeam.DistanceToPattern(point));
85  for (const auto &ray : fFragments)
86  distances.push_back(ray.DistanceToPattern(point));
87  return *std::min_element(distances.begin(), distances.end());
88 }
89 
91 {
92  auto comp = [](const std::pair<int, double> &a, const std::pair<int, double> &b) { return a.second < b.second; };
93  auto points = std::set<std::pair<int, double>, decltype(comp)>(comp);
94 
95  for (int i = 0; i < fFragments.size(); ++i)
96  points.insert({i, fFragments[i].DistanceToPattern(point)});
97  points.insert({fFragments.size(), fBeam.DistanceToPattern(point)});
98 
99  return points.begin()->first;
100 }
101 
102 std::vector<double> AtPatternY::GetPatternPar() const
103 {
104  std::vector<double> ret;
105  ret.resize(12);
106  ret[0] = GetVertex().X();
107  ret[1] = GetVertex().Y();
108  ret[2] = GetVertex().Z();
109  ret[3] = GetBeamDirection().X();
110  ret[4] = GetBeamDirection().Y();
111  ret[5] = GetBeamDirection().Z();
112  for (int i = 0; i < 2; ++i) {
113  ret[6 + 3 * i] = GetFragmentDirection(i).X();
114  ret[7 + 3 * i] = GetFragmentDirection(i).Y();
115  ret[8 + 3 * i] = GetFragmentDirection(i).Z();
116  }
117  return ret;
118 }
119 
127 void AtPatternY::DefinePattern(std::vector<double> par)
128 {
129  if (par.size() != 12) {
130  LOG(error) << "Defining a Y pattern requires 12 parameters!";
131  return;
132  }
133 
134  XYZPoint vertex(par[0], par[1], par[2]);
135  XYZVector beamDir(par[3], par[4], par[5]);
136  std::array<XYZVector, 2> fragDir;
137  for (int i = 0; i < 2; ++i)
138  fragDir[i] = {par[6 + i * 3], par[7 + i * 3], par[8 + i * 3]};
139  DefinePattern(vertex, beamDir, fragDir);
140 }
141 
142 void AtPatternY::DefinePattern(const XYZPoint &vertex, const XYZVector &beamDir,
143  const std::array<XYZVector, 2> &fragDir)
144 {
145  fBeam.DefinePattern(vertex, beamDir);
146  for (int i = 0; i < 2; ++i)
147  fFragments[i].DefinePattern(vertex, fragDir[i]);
148 }
149 
150 void AtPatternY::DefinePattern(const std::vector<XYZPoint> &points)
151 {
152  if (points.size() != fNumPoints)
153  LOG(fatal) << "Trying to create model with wrong number of points " << points.size();
154 
155  // Sort points by z location in decreasing order
156  auto sortedPoints = points;
157  std::sort(sortedPoints.begin(), sortedPoints.end(),
158  [](const ROOT::Math::XYZPoint &a, const ROOT::Math::XYZPoint &b) { return a.Z() > b.Z(); });
159 
160  // Vertex point is defined to be the one at second largest z
161  auto fVertex = points[1];
162  // Get the vector pointing from the vertex to the next other beam point
163  auto dir = points[0] - fVertex;
164  if (dir.Z() < 0)
165  dir.SetZ(-dir.Z());
166  fBeam.DefinePattern(fVertex, dir);
167 
168  for (int i = 0; i < 2; ++i) {
169  fFragments[i].DefinePattern({fVertex, points[i + 2]});
170  }
171 }
172 
181 {
182  return dynamic_cast<const AtPatternLine *>(&fBeam)->GetPointAt(z);
183 }
184 
185 // charge may be empty, if so do not do a charge weighted fit.
186 void AtPatternY::FitPattern(const std::vector<XYZPoint> &points, const std::vector<double> &charge)
187 {
188  // Based on the example from ROOT documentation https://root.cern.ch/doc/master/line3Dfit_8C_source.html
189 
190  bool weighted = points.size() == charge.size();
191  LOG(debug) << "Fitting with" << (weighted ? " " : "out ") << "charge weighting";
192 
193  // This functor is what we are minimizing. It takes in the model parameters and defines an example
194  // of this pattern based on the model parameters. It then loops through every hit associated with
195  // pattern and calculates the chi2.
196  auto func = [&points, &charge, weighted](const double *par) {
197  AtPatternY pat;
198  pat.DefinePattern(std::vector<double>(par, par + 12));
199  double chi2 = 0;
200  double qTot = 0;
201  for (int i = 0; i < points.size(); ++i) {
202  auto q = weighted ? charge[i] : 1;
203  chi2 += pat.DistanceToPattern(points[i]) * pat.DistanceToPattern(points[i]) * q;
204  qTot += q;
205  }
206 
207  return fabs(chi2 / qTot);
208  };
209 
210  auto functor = ROOT::Math::Functor(func, 12);
211 
212  ROOT::Fit::Fitter fitter;
213  auto iniPar = GetPatternPar();
214 
215  LOG(debug) << "Initial parameters";
216  for (int i = 0; i < iniPar.size(); ++i)
217  LOG(debug) << Form("Par_%d", i) << "\t = " << iniPar[i];
218 
219  fitter.SetFCN(functor, iniPar.data());
220 
221  // Constrain the Z direction to be the same
222  for (int i = 0; i < 3; ++i)
223  fitter.Config().ParSettings(5 + i * 3).Fix();
224 
225  for (int i = 0; i < 12; ++i)
226  fitter.Config().ParSettings(i).SetStepSize(.01);
227 
228  bool ok = fitter.FitFCN();
229  if (!ok) {
230  LOG(error) << "Failed to fit the pattern, using result of SAC";
231  DefinePattern(iniPar);
232  return;
233  }
234 
235  auto &result = fitter.Result();
236  DefinePattern(result.Parameters());
237  fChi2 = result.MinFcnValue();
238  fNFree = points.size() - result.NPar();
239 }
AtPatterns::AtPatternLine::GetPoint
XYZPoint GetPoint() const
Definition: AtPatternLine.h:34
AtPatterns::AtPatternY::GetPatternPar
virtual std::vector< double > GetPatternPar() const override
Get list or parameters that describe the pattern.
Definition: AtPatternY.cxx:102
AtPatterns::AtPatternY::AtPatternY
AtPatternY()
Definition: AtPatternY.cxx:29
AtPatterns::AtPatternY::GetEveElement
virtual TEveElement * GetEveElement() const override
Get visual representation of pattern.
Definition: AtPatternY.cxx:31
AtPatterns::AtPattern::fNFree
Int_t fNFree
Definition: AtPattern.h:47
AtPatterns::AtPatternLine
Describes a linear track.
Definition: AtPatternLine.h:28
AtPatterns::AtPatternY::GetPointAssignment
int GetPointAssignment(const XYZPoint &point) const
Definition: AtPatternY.cxx:90
AtPatterns::AtPatternRay::DistanceToPattern
virtual Double_t DistanceToPattern(const XYZPoint &point) const override
Closest distance to pattern.
Definition: AtPatternRay.cxx:30
AtPatterns::AtPatternY::ClosestPointOnPattern
virtual XYZPoint ClosestPointOnPattern(const XYZPoint &point) const override
Closest point on pattern.
Definition: AtPatternY.cxx:65
XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPatternCircle2D.h:18
AtPatterns::AtPattern
Describes a shape in 3D space.
Definition: AtPattern.h:40
AtPatternLine.h
AtPatterns::AtPatternY::GetFragmentDirection
XYZVector GetFragmentDirection(int frag) const
Get the direction of the fragment rays.
Definition: AtPatternY.h:55
AtPatterns::AtPatternRay::GetEveElement
virtual TEveElement * GetEveElement() const override
Get visual representation of pattern.
Definition: AtPatternRay.cxx:19
AtPatterns::AtPattern::fChi2
Double_t fChi2
Definition: AtPattern.h:46
AtPatterns::AtPatternRay::DefinePattern
void DefinePattern(XYZPoint point, XYZVector direction)
Definition: AtPatternRay.cxx:43
ClassImp
ClassImp(AtPatternY)
AtPatterns::AtPatternY::fBeam
AtPatternRay fBeam
Definition: AtPatternY.h:31
AtPatternY.h
AtPatterns::AtPatternY::GetPointAt
virtual XYZPoint GetPointAt(double z) const override
Get point along the beam axis at z.
Definition: AtPatternY.cxx:180
AtPatterns::AtPatternY::DefinePattern
virtual void DefinePattern(const std::vector< XYZPoint > &points) override
Define based on points.
Definition: AtPatternY.cxx:150
AtPatterns::AtPatternY::XYZVector
ROOT::Math::XYZVector XYZVector
Definition: AtPatternY.h:36
AtPatterns
Definition: AtFissionEvent.h:21
AtPatterns::AtPatternY::fFragments
std::array< AtPatternRay, 2 > fFragments
Definition: AtPatternY.h:32
AtPatterns::AtPatternY::DistanceToPattern
virtual Double_t DistanceToPattern(const XYZPoint &point) const override
Closest distance to pattern.
Definition: AtPatternY.cxx:81
AtPatterns::AtPatternY::FitPattern
virtual void FitPattern(const std::vector< XYZPoint > &points, const std::vector< double > &charge) override
Definition: AtPatternY.cxx:186
AtPatterns::AtPatternY::XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPatternY.h:35
AtPatterns::AtPatternY::GetBeamDirection
XYZVector GetBeamDirection() const
Get the direction of the beam ray.
Definition: AtPatternY.h:48
AtPatterns::AtPattern::fNumPoints
const Int_t fNumPoints
Definition: AtPattern.h:48
AtPatterns::AtPatternRay::ClosestPointOnPattern
virtual XYZPoint ClosestPointOnPattern(const XYZPoint &point) const override
Closest point on pattern.
Definition: AtPatternRay.cxx:24
AtPatterns::AtPatternY
Describes a Y track.
Definition: AtPatternY.h:29
AtPatterns::AtPatternY::GetVertex
XYZPoint GetVertex() const
Get the vertex of the Y shape.
Definition: AtPatternY.h:42
AtPatterns::AtPattern::XYZPoint
ROOT::Math::XYZPoint XYZPoint
Definition: AtPattern.h:42