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