ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
AtFindVertex.cxx
Go to the documentation of this file.
1 /*
2 Move this to Fitter folder, the vertex determination will go with the fitter
3 */
4 #include "AtFindVertex.h"
5 // IWYU pragma: no_include <ext/alloc_traits.h>
6 
7 #include "AtPattern.h" // for AtPattern
8 #include "AtPatternLine.h"
9 #include "AtTrack.h"
10 
11 #include <FairLogger.h>
12 
13 #include <Math/Vector3D.h> // for DisplacemenXYZVectorD
14 
15 #include <algorithm>
16 #include <cmath> // for sqrt
17 #include <iostream> // for operator<<, basic_ostream::operator<<
18 #include <iterator> // for back_insert_iterator, back_inserter
19 #include <memory> // for shared_ptr, __shared_ptr_access, __sha...
20 #include <utility> // for pair
21 
22 constexpr auto cRED = "\033[1;31m";
23 constexpr auto cYELLOW = "\033[1;33m";
24 constexpr auto cNORMAL = "\033[0m";
25 constexpr auto cGREEN = "\033[1;32m";
26 
27 AtFindVertex::AtFindVertex(Double_t lineDistThreshold) : fLineDistThreshold(lineDistThreshold), fTracksFromVertex(0)
28 {
29  fBeamPoint.SetXYZ(0, 0, 500);
30  fBeamDir.SetXYZ(0, 0, 1);
31  fBeamLine.resize(6);
32  fBeamLine[0] = fBeamPoint.X();
33  fBeamLine[1] = fBeamPoint.Y();
34  fBeamLine[2] = fBeamPoint.Z();
35  fBeamLine[3] = fBeamDir.X();
36  fBeamLine[4] = fBeamDir.Y();
37  fBeamLine[5] = fBeamDir.Z();
38 }
39 
40 AtFindVertex::~AtFindVertex() = default;
41 
42 void AtFindVertex::FindVertex(std::vector<AtTrack> tracks, Int_t nbTracksPerVtx)
43 {
44  if (tracks.size() < nbTracksPerVtx)
45  return;
46  switch (nbTracksPerVtx) {
47  case 1: FindVertexSingleLine(tracks); break;
48  default: FindVertexMultipleLines(tracks, nbTracksPerVtx);
49  }
50 }
51 
52 void AtFindVertex::FindVertexSingleLine(std::vector<AtTrack> tracks)
53 {
54  std::vector<std::vector<Double_t>> lines;
55  std::vector<Int_t> itracks;
56  Int_t it = -1;
57  for (auto track : tracks) {
58  it++;
59  auto ransacLine = dynamic_cast<const AtPatterns::AtPatternLine *>(track.GetPattern());
60  std::vector<Double_t> patternPar;
61  patternPar = ransacLine->GetPatternPar();
62  if (patternPar.size() == 0)
63  continue;
64  lines.push_back(patternPar);
65  itracks.push_back(it);
66  }
67  std::vector<std::pair<Int_t, XYZVector>> cogVtx;
68  cogVtx = CoGVtxSingleTrack(lines, itracks);
69  // for(Int_t i =0; i<cogVtx.size(); i++)std::cout<<cogVtx.size()<<" check cogVtx size "<<cogVtx.at(i).second.X()<<"
70  // "<<cogVtx.at(i).second.Y()<<" "<<cogVtx.at(i).second.Z()<<std::endl;
71 
72  for (auto &[num, pos] : cogVtx) {
73  if (pos.Z() <= 0 || pos.Z() >= 1000 || sqrt(pos.Perp2()) > 30)
74  continue;
75  std::vector<AtTrack> tracksVtx;
76  tracksVtx.push_back(tracks.at(num));
78  tv.vertex = pos;
79  tv.tracks = tracksVtx;
80  SetTracksVertex(tv);
81  }
82 }
83 
84 void AtFindVertex::FindVertexMultipleLines(std::vector<AtTrack> tracks, Int_t nbTracksPerVtx)
85 {
86  std::vector<std::vector<Double_t>> lines;
87  std::vector<Double_t> wlines; // weights for CoG (ex: Chi2, chargeTot, nbInliners...)
88  for (auto track : tracks) {
89  auto ransacLine = dynamic_cast<const AtPatterns::AtPatternLine *>(track.GetPattern());
90  std::vector<Double_t> patternPar;
91  patternPar = ransacLine->GetPatternPar();
92  if (patternPar.size() == 0)
93  continue;
94  lines.push_back(patternPar);
95  wlines.push_back(ransacLine->GetChi2());
96  // wlines.push_back(ransacLine->GetNumPoints());
97  // wlines.push_back(1.);
98  }
99 
100  std::vector<AtTrack> tracksFromSameVtx; // save tracks coming from a common vertex
101  std::vector<std::vector<Int_t>> vtxCand; // save track ID of tracks coming from a common vertex
102  vtxCand = SortTrackSameVtx(lines);
103  for (Int_t i = 0; i < vtxCand.size(); i++)
104  std::cout << vtxCand.size() << " check vtxCand size " << vtxCand.at(i).size() << std::endl;
105 
106  std::vector<XYZVector> cogVtx;
107  cogVtx = CoGVtx(vtxCand, lines, wlines);
108  // for(Int_t i =0; i<cogVtx.size(); i++)std::cout<<cogVtx.size()<<" check cogVtx size "<<cogVtx.at(i).X()<<"
109  // "<<cogVtx.at(i).Y()<<" "<<cogVtx.at(i).Z()<<std::endl;
110 
111  if (vtxCand.size() != cogVtx.size())
112  LOG(WARNING) << cYELLOW << "AtFindVertex : vtxCand.size() != cogVtx.size()" << cNORMAL << std::endl;
113 
114  for (Int_t i = 0; i < vtxCand.size(); i++) {
115  if (cogVtx.at(i).X() != cogVtx.at(i).X() || cogVtx.at(i).Y() != cogVtx.at(i).Y() ||
116  cogVtx.at(i).Z() != cogVtx.at(i).Z())
117  continue;
118  if (cogVtx.at(i).Z() <= 0 || cogVtx.at(i).Z() >= 1000 || sqrt(cogVtx.at(i).Perp2()) > 30)
119  continue;
120  if (vtxCand.at(i).size() > nbTracksPerVtx)
121  std::cout << cYELLOW << " vtx with more than " << nbTracksPerVtx << " tracks(" << vtxCand.at(i).size() << ")"
122  << cNORMAL << std::endl;
123  std::vector<AtTrack> tracksVtx;
124  for (auto vtxInd : vtxCand.at(i)) {
125  tracksVtx.push_back(tracks.at(vtxInd));
126  }
127  tracksFromVertex tv;
128  tv.vertex = cogVtx.at(i);
129  tv.tracks = tracksVtx;
130  SetTracksVertex(tv);
131  }
132 }
133 
134 std::vector<std::vector<Int_t>> AtFindVertex::SortTrackSameVtx(std::vector<std::vector<Double_t>> lines)
135 {
136  std::vector<std::vector<Int_t>> result;
137  std::vector<Int_t> paired;
138  std::vector<XYZVector> vtx;
139 
140  // Test lines against each others
141  for (Int_t i = 0; i < lines.size() - 1; i++) {
142  if (std::find(paired.begin(), paired.end(), i) != paired.end())
143  continue;
144  std::vector<Double_t> line = lines.at(i);
145 
146  for (Int_t j = i + 1; j < lines.size(); j++) {
147  if (std::find(paired.begin(), paired.end(), j) != paired.end())
148  continue;
149 
150  XYZVector buffVtx(0., 0., 9999.);
151  std::vector<Double_t> line_f = lines.at(j);
152 
153  if (vtx.size() == 0) { // if no vertex found
154  Double_t angle = angLines(line, line_f);
155  Double_t dist = distLines(line, line_f);
156 
157  if (dist < fLineDistThreshold) { // lines.at(i) and lines.at(j) close enough to make a new vertex
158  if (angle < 10 || angle > 170) {
159  XYZVector vtxLines1 = ClosestPoint2Lines(line, fBeamLine);
160  XYZVector vtxLines2 = ClosestPoint2Lines(line_f, fBeamLine);
161  buffVtx = 0.5 * (vtxLines1 + vtxLines2);
162  } else {
163  buffVtx = ClosestPoint2Lines(line, line_f);
164  }
165  // std::cout<<" paired size "<<paired.size()<<" "<<i<<" "<<j<<" "<<std::endl;
166  paired.push_back(i);
167  paired.push_back(j);
168  vtx.push_back(buffVtx);
169  }
170  } else { // if already a vertex
171  // std::cout<<" paired size "<<paired.size()<<" "<<i<<" "<<j<<" "<<std::endl;
172  XYZVector projVtx;
173  projVtx = ptOnLine(
174  line_f, vtx.back()); // vtx.back() assumes one only wants events with one vertex, but it can be modified
175  Double_t dist1 =
176  sqrt((vtx.back() - projVtx).Mag2()); // distance between saved vtx and its projection on the new line
177  Double_t radProjVtx = sqrt((0.5 * (vtx.back() + projVtx)).Perp2());
178  // std::cout<<radProjVtx<<" distlines "<<dist1<<" vtxBack "<<vtx.back().X()<<" "<<vtx.back().Y()<<"
179  // "<<vtx.back().Z()<<" "<<projVtx.X()<<" "<<projVtx.Y()<<" "<<projVtx.Z()<<std::endl;
180  if (dist1 < fLineDistThreshold &&
181  radProjVtx <= 30.) { // more than 2 lines from a same vertex in the beam region
182  if (std::find(paired.begin(), paired.end(), i) == paired.end()) {
183  paired.push_back(i);
184  }
185  paired.push_back(j);
186  }
187  }
188  } // j loop lines
189  } // i loop lines
190  if (paired.size() > 1)
191  result.push_back(paired);
192 
193  // for (size_t ipaired = 0; ipaired < paired.size(); ipaired++) {
194  // std::cout<<paired.at(ipaired)<<std::endl;
195  // }
196 
197  return result;
198 }
199 
200 std::vector<std::pair<Int_t, XYZVector>>
201 AtFindVertex::CoGVtxSingleTrack(std::vector<std::vector<Double_t>> lines, std::vector<Int_t> itracks)
202 {
203  std::vector<std::pair<Int_t, XYZVector>> result;
204  for (Int_t i = 0; i < lines.size(); i++) {
205  XYZVector vtx(0, 0, 0);
206  // std::cout<<lines.size()<<" check lines size "<<std::endl;
207  std::vector<Double_t> line = lines.at(i);
208  // Double_t angle = angLines(line, fBeamLine);
209  Double_t dist = distLines(line, fBeamLine);
210  if (dist < fLineDistThreshold) {
211  std::vector<XYZVector> projVtxOnLines1 = ClosestPointProjOnLines(line, fBeamLine);
212  vtx = projVtxOnLines1.at(
213  0); // this way the track angle is better than taking the CoG, the uncertainty on the range is not improved
214  auto p = std::make_pair(itracks.at(i), vtx);
215  result.push_back(p);
216  }
217  } // loop i
218 
219  return result;
220 }
221 
222 std::vector<XYZVector> AtFindVertex::CoGVtx(std::vector<std::vector<Int_t>> vtxCand,
223  std::vector<std::vector<Double_t>> lines, std::vector<Double_t> wlines)
224 {
225  std::vector<XYZVector> result;
226 
227  // loop on vtx Candidates
228  for (auto iv : vtxCand) {
229 
230  XYZVector CoG(0, 0, 0);
231 
232  std::vector<XYZVector> sumVtx; // sum of points corresponding to where are the closest distances between each
233  // lines
234  XYZVector buffVec1(0, 0, 0);
235  sumVtx.resize(iv.size(), buffVec1);
236 
237  for (Int_t i = 0; i < iv.size() - 1; i++) {
238  Int_t ii = iv.at(i);
239  std::vector<Double_t> line = lines.at(ii);
240 
241  for (Int_t j = i + 1; j < iv.size(); j++) {
242  Int_t jj = iv.at(j);
243  std::vector<Double_t> line_f = lines.at(jj);
244 
245  Double_t angle = angLines(line, line_f);
246  Double_t dist = distLines(line, line_f);
247  if (dist < fLineDistThreshold) {
248  if (angle < 10 || angle > 170) {
249  std::vector<XYZVector> projVtxOnLines1 = ClosestPointProjOnLines(line, fBeamLine);
250  std::vector<XYZVector> projVtxOnLines2 = ClosestPointProjOnLines(line_f, fBeamLine);
251  sumVtx.at(i) += projVtxOnLines1.at(0);
252  sumVtx.at(j) += projVtxOnLines2.at(0);
253  } else {
254  std::vector<XYZVector> projVtxOnLines = ClosestPointProjOnLines(line, line_f);
255  sumVtx.at(i) += projVtxOnLines.at(0);
256  sumVtx.at(j) += projVtxOnLines.at(1);
257  // std::cout<<"check CoG "<<line.at(0)<<" "<<line.at(1)<<" "<<line_f.at(0)<<"
258  // "<<line_f.at(1)<<std::endl;
259  }
260  }
261  } // End of track_f (for loop j)
262  } // Loop over the lines (for loop i)
263 
264  Double_t sumW = 0; // sum of the weights
265  for (Int_t i = 0; i < iv.size(); i++) {
266  // std::cout<<"sumvtx "<<sumVtx.at(i).X()<<" "<<sumVtx.at(i).Y()<<" "<<sumVtx.at(i).Z()<<" chi2
267  // "<<wlines.at(iv.at(i))<<std::endl;
268  CoG += sumVtx.at(i) * (1. / wlines.at(iv.at(i)));
269  sumW += (Double_t)(1. / wlines.at(iv.at(i)));
270  }
271  CoG = CoG * (1. / (iv.size() - 1)) * (1. / sumW);
272  std::cout << " vertex " << CoG.X() << " " << CoG.Y() << " " << CoG.Z() << std::endl;
273  result.push_back(CoG);
274 
275  } // for iv vertex candidates
276 
277  return result;
278 }
279 
280 // returns the mean point at the closest distance between two lines
281 XYZVector AtFindVertex::ClosestPoint2Lines(std::vector<Double_t> line1, std::vector<Double_t> line2)
282 {
283  XYZVector p1(line1.at(0), line1.at(1), line1.at(2));
284  XYZVector d1(line1.at(3), line1.at(4), line1.at(5));
285  XYZVector p2(line2.at(0), line2.at(1), line2.at(2));
286  XYZVector d2(line2.at(3), line2.at(4), line2.at(5));
287  XYZVector n1 = d1.Cross(d2.Cross(d1));
288  XYZVector n2 = d2.Cross(d1.Cross(d2));
289  Double_t t1 = (p2 - p1).Dot(n2) / (d1.Dot(n2));
290  Double_t t2 = (p1 - p2).Dot(n1) / (d2.Dot(n1));
291  XYZVector c1 = p1 + t1 * d1;
292  XYZVector c2 = p2 + t2 * d2;
293  XYZVector meanpoint = 0.5 * (c1 + c2);
294 
295  return meanpoint;
296 }
297 
298 // returns the projections on each lines of the mean point at the closest distance between two lines
299 std::vector<XYZVector> AtFindVertex::ClosestPointProjOnLines(std::vector<Double_t> line1, std::vector<Double_t> line2)
300 {
301  std::vector<XYZVector> result;
302  XYZVector p1(line1.at(0), line1.at(1), line1.at(2));
303  XYZVector d1(line1.at(3), line1.at(4), line1.at(5));
304  XYZVector p2(line2.at(0), line2.at(1), line2.at(2));
305  XYZVector d2(line2.at(3), line2.at(4), line2.at(5));
306  XYZVector n1 = d1.Cross(d2.Cross(d1));
307  XYZVector n2 = d2.Cross(d1.Cross(d2));
308  Double_t t1 = (p2 - p1).Dot(n2) / (d1.Dot(n2));
309  Double_t t2 = (p1 - p2).Dot(n1) / (d2.Dot(n1));
310  XYZVector c1 = p1 + t1 * d1;
311  XYZVector c2 = p2 + t2 * d2;
312  result.push_back(c1);
313  result.push_back(c2);
314 
315  return result;
316 }
317 
318 // returns the projection of a point on the parametric line
319 XYZVector AtFindVertex::ptOnLine(std::vector<Double_t> line, XYZVector pointToProj)
320 {
321  XYZVector result(-999, -999, -999);
322  XYZVector posOn(line.at(0), line.at(1), line.at(2));
323  XYZVector dir(line.at(3), line.at(4), line.at(5));
324  XYZVector vop1 = ((dir.Cross(pointToProj - posOn)).Cross(dir)).Unit();
325  Double_t paraVar1 = pointToProj.Dot(dir.Unit()) - posOn.Dot(dir.Unit());
326  Double_t paraVar2 = posOn.Dot(vop1) - pointToProj.Dot(vop1);
327  XYZVector vInter1 = posOn + dir.Unit() * paraVar1;
328  XYZVector vInter2 = pointToProj + vop1 * paraVar2;
329  if (sqrt((vInter1 - vInter2).Mag2()) < 1e-6)
330  result = vInter1;
331 
332  return result;
333 }
334 
335 // returns the distance between a point and a parametric line
336 Double_t AtFindVertex::distPtLine(XYZVector dir, XYZVector ptLine, XYZVector pt)
337 {
338  return sqrt((ptLine - pt).Cross(dir).Mag2()) / sqrt(dir.Mag2());
339 }
340 
341 // returns the distance between two lines
342 Double_t AtFindVertex::distLines(std::vector<Double_t> line1, std::vector<Double_t> line2)
343 {
344  XYZVector p1(line1.at(0), line1.at(1), line1.at(2));
345  XYZVector d1(line1.at(3), line1.at(4), line1.at(5));
346  XYZVector p2(line2.at(0), line2.at(1), line2.at(2));
347  XYZVector d2(line2.at(3), line2.at(4), line2.at(5));
348  XYZVector n = d1.Cross(d2);
349 
350  return fabs(n.Dot(p1 - p2) / sqrt(n.Mag2()));
351 }
352 
353 // returns the angle between two lines
354 Double_t AtFindVertex::angLines(std::vector<Double_t> line1, std::vector<Double_t> line2)
355 {
356  XYZVector d1(line1.at(3), line1.at(4), line1.at(5));
357  XYZVector d2(line2.at(3), line2.at(4), line2.at(5));
358 
359  return acos(d1.Dot(d2) / (sqrt(d1.Mag2()) * sqrt(d2.Mag2()))) * 180. / 3.1415;
360 }
361 
362 // check if a track already makes a vertex
363 Bool_t AtFindVertex::checkExclusivity(std::vector<Int_t> v1, std::vector<Int_t> v2)
364 {
365  Bool_t result = kTRUE;
366  std::vector<Int_t> diff;
367  std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), std::inserter(diff, diff.begin()));
368  if (v1.size() != diff.size())
369  result = kFALSE;
370 
371  return result;
372 }
AtFindVertex::checkExclusivity
Bool_t checkExclusivity(std::vector< Int_t > v1, std::vector< Int_t > v2)
Definition: AtFindVertex.cxx:365
AtFindVertex::SortTrackSameVtx
std::vector< std::vector< Int_t > > SortTrackSameVtx(std::vector< std::vector< Double_t >> lines)
Definition: AtFindVertex.cxx:136
AtFindVertex::angLines
Double_t angLines(std::vector< Double_t > line1, std::vector< Double_t > line2)
Definition: AtFindVertex.cxx:356
AtFindVertex::AtFindVertex
AtFindVertex(Double_t lineDistThreshold=15)
Definition: AtFindVertex.cxx:29
AtFindVertex::CoGVtx
std::vector< XYZVector > CoGVtx(std::vector< std::vector< Int_t >> vtxCand, std::vector< std::vector< Double_t >> lines, std::vector< Double_t > wlines)
Definition: AtFindVertex.cxx:224
tracksFromVertex::vertex
XYZVector vertex
Definition: AtFindVertex.h:23
XYZVector
ROOT::Math::XYZVector XYZVector
Definition: AtFindVertex.h:20
c2
constexpr auto c2
Definition: AtRadialChargeModel.cxx:21
cGREEN
constexpr auto cGREEN
Definition: AtFindVertex.cxx:25
AtFindVertex::distLines
Double_t distLines(std::vector< Double_t > line1, std::vector< Double_t > line2)
Definition: AtFindVertex.cxx:344
AtFindVertex::distPtLine
Double_t distPtLine(XYZVector dir, XYZVector ptLine, XYZVector pt)
Definition: AtFindVertex.cxx:338
AtPattern.h
AtPatterns::AtPatternLine
Describes a linear track.
Definition: AtPatternLine.h:28
AtFindVertex::~AtFindVertex
virtual ~AtFindVertex()
tracksFromVertex
Definition: AtFindVertex.h:22
cYELLOW
constexpr auto cYELLOW
Definition: AtFindVertex.cxx:23
AtFindVertex.h
AtFindVertex::ptOnLine
XYZVector ptOnLine(std::vector< Double_t > line, XYZVector pointToProj)
Definition: AtFindVertex.cxx:321
AtPatternLine.h
AtFindVertex::SetTracksVertex
void SetTracksVertex(tracksFromVertex val)
Definition: AtFindVertex.h:49
AtFindVertex::ClosestPoint2Lines
XYZVector ClosestPoint2Lines(std::vector< Double_t > line1, std::vector< Double_t > line2)
Definition: AtFindVertex.cxx:283
tracksFromVertex::tracks
std::vector< AtTrack > tracks
Definition: AtFindVertex.h:24
cNORMAL
constexpr auto cNORMAL
Definition: AtFindVertex.cxx:24
AtTrack.h
AtFindVertex::FindVertexSingleLine
void FindVertexSingleLine(std::vector< AtTrack > tracks)
Definition: AtFindVertex.cxx:54
AtFindVertex::FindVertexMultipleLines
void FindVertexMultipleLines(std::vector< AtTrack > tracks, Int_t nbTracksPerVtx)
Definition: AtFindVertex.cxx:86
cRED
constexpr auto cRED
Definition: AtFindVertex.cxx:22
AtFindVertex::ClosestPointProjOnLines
std::vector< XYZVector > ClosestPointProjOnLines(std::vector< Double_t > line1, std::vector< Double_t > line2)
Definition: AtFindVertex.cxx:301
AtFindVertex::FindVertex
void FindVertex(std::vector< AtTrack > tracks, Int_t nbTracksPerVtx)
Definition: AtFindVertex.cxx:44
AtFindVertex::CoGVtxSingleTrack
std::vector< std::pair< Int_t, XYZVector > > CoGVtxSingleTrack(std::vector< std::vector< Double_t >> lines, std::vector< Int_t > itracks)
Definition: AtFindVertex.cxx:203