PandaRoot
PndApolloniusTriplet.h
Go to the documentation of this file.
1 #pragma once
2 
3 #define _USE_MATH_DEFINES
4 
5 #include <math.h>
6 #include <tuple>
7 
8 #include "PndSttGeometryMap.h"
9 #include "FairHit.h"
10 #include "PndSttHit.h"
11 #include "FairLogger.h"
12 #include "PndHoughApollonius.h"
14 // general
15 using std::cout;
16 using std::endl;
17 
18 namespace PndApollonius {
19 
20 struct Thresholds {
23 
26 
31  double fDistanceThresholdGEM = 1.;
32 
33  double fSTTArcLengthCut = 26.;
35  double fMVDArcLengthCutMid = 7.;
36  double fMVDArcLengthCutFar = 10.;
37 };
38 
39 struct Triplet {
40  std::array<PndSttHit *, 3> fTripletHits;
41  friend std::ostream &operator<<(std::ostream &output, const Triplet &t)
42 
43  {
44  output << "Triplet: ";
45  for (auto hit : t.fTripletHits)
46  output << hit->GetTubeID() << "(" << hit->GetX() << "," << hit->GetY() << ") /";
47  output << std::endl;
48 
49  return output;
50  }
51 };
52 
54 
55  enum detID { MVDpixel, MVDstrip, STT, GEM, NOTDEFINED };
56  std::vector<std::string> detID_Names{"MVD_Pixel", "MVD_Strip", "STT", "GEM", "NOTDEFINED"};
57 
59  TripletSolution(TVector3 track) : fTrack(track){};
60 
61  void AddHits(detID detector, std::vector<FairHit *> data) { fHits[detector] = data; }
62 
63  void AddHits(std::vector<PndSttHit *> sttHits) { fHits[STT].insert(fHits[STT].end(), sttHits.begin(), sttHits.end()); }
64 
65  void AddHit(detID detector, FairHit *data)
66  {
67  if (fHits.count(detector) == 0) {
68  fHits[detector];
69  }
70  if (std::find(fHits[detector].begin(), fHits[detector].end(), data) == fHits[detector].end()) { // add only if hit is not in dataset
71  fHits[detector].push_back(data);
72  }
73  }
74 
75  int GetNHits() { return fHits[MVDpixel].size() + fHits[MVDstrip].size() + fHits[STT].size() + fHits[GEM].size(); }
76 
77  TVector2 HitOnTrack(FairHit *hit) { return TVector2(hit->GetX() - fTrack.X(), hit->GetY() - fTrack.Y()); }
78 
79  void IsClockwise()
80  {
81  std::vector<FairHit *> sttHits = fHits[STT];
82  if (sttHits.size() > 2) {
83 
84  fClockwise = true;
85  std::sort(sttHits.begin(), sttHits.end(), [](FairHit *first, FairHit *second) { return (*(static_cast<PndSttHit *>(first)) < *(static_cast<PndSttHit *>(second))); });
86  TVector2 firstHit(HitOnTrack(sttHits.front()));
87  TVector2 secondHit(HitOnTrack(sttHits.back()));
88  if (firstHit.DeltaPhi(secondHit) < 0) {
89  fClockwise = false;
90  }
91  }
92  }
93 
94  void SortHits(TVector2 &firstHit, detID detector)
95  {
96  if (fClockwise) {
97  std::sort(fHits[detector].begin(), fHits[detector].end(), [&](FairHit *a, FairHit *b) {
98  double phi_a = HitOnTrack(a).DeltaPhi(firstHit);
99  double phi_b = HitOnTrack(b).DeltaPhi(firstHit);
100  if (phi_a <= 0)
101  phi_a += 2 * TMath::Pi();
102  if (phi_b <= 0)
103  phi_b += 2 * TMath::Pi();
104 
105  return (phi_a > phi_b);
106  });
107  } else {
108  std::sort(fHits[detector].begin(), fHits[detector].end(), [&](FairHit *a, FairHit *b) {
109  double phi_a = HitOnTrack(a).DeltaPhi(firstHit);
110  double phi_b = HitOnTrack(b).DeltaPhi(firstHit);
111  if (phi_a < 0)
112  phi_a += 2 * TMath::Pi();
113  if (phi_b < 0)
114  phi_b += 2 * TMath::Pi();
115  return (phi_a < phi_b);
116  });
117  }
118  }
119 
120  void SortStt(PndSttGeometryMap *fGeometryMap)
121  {
122  std::vector<FairHit *> sttHits = fHits[STT];
123  if (sttHits.size() > 2) {
124 
125  IsClockwise();
126 
127  std::sort(sttHits.begin(), sttHits.end(), [](FairHit *first, FairHit *second) { return (*(static_cast<PndSttHit *>(first)) < *(static_cast<PndSttHit *>(second))); });
128  std::vector<FairHit *> possibleFirstHits;
129  int minRow = 100;
130  for( auto hit : sttHits){
131  if (fGeometryMap->GetRow(static_cast<PndSttHit *>(hit)->GetTubeID()) <= minRow) {
132  minRow = fGeometryMap->GetRow(static_cast<PndSttHit *>(hit)->GetTubeID());
133  possibleFirstHits.push_back(hit);
134  } else
135  break;
136  }
137  TVector2 firstHit;
138  if (fClockwise) {
139  firstHit = HitOnTrack(possibleFirstHits.back());
140  } else {
141  firstHit = HitOnTrack(possibleFirstHits.front());
142  }
143  SortHits(firstHit, STT);
144  }
145  }
146 
147  FairHit *GetFirstHit(PndSttGeometryMap *fGeometryMap)
148  {
149  std::vector<FairHit *> mvdPixelHits = fHits[MVDpixel];
150  std::vector<FairHit *> mvdStripHits = fHits[MVDstrip];
151  std::vector<FairHit *> sttHits = fHits[STT];
152  std::vector<FairHit *> gemHits = fHits[GEM];
153 
154  if (mvdPixelHits.size() > 0) {
155  double dSquare = 100000.;
156  FairHit *first = nullptr;
157  for (auto hit : mvdPixelHits) {
158  if (((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY() + (hit->GetZ() * hit->GetZ()))) < dSquare) {
159  dSquare = ((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY()) + (hit->GetZ() * hit->GetZ()));
160  first = hit;
161  }
162  }
163  return first;
164  } else if (mvdStripHits.size() > 0) {
165  double dSquare = 100000.;
166  FairHit *first = nullptr;
167  for (auto hit : mvdStripHits) {
168  if (((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY() + (hit->GetZ() * hit->GetZ()))) < dSquare) {
169  dSquare = ((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY()) + (hit->GetZ() * hit->GetZ()));
170  first = hit;
171  }
172  }
173  return first;
174 
175  } else if (sttHits.size() > 0) {
176  return sttHits.front();
177  } else if (gemHits.size() > 0) {
178  double dSquare = 100000.;
179  FairHit *first = nullptr;
180  for (auto hit : gemHits) {
181  if (((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY())) < dSquare) {
182  dSquare = ((hit->GetX() * hit->GetX()) + (hit->GetY() * hit->GetY()));
183  first = hit;
184  }
185  }
186  return first;
187  } else
188  return nullptr;
189  }
190 
191  void SortAllHits(PndSttGeometryMap *fGeometryMap)
192  {
193  std::vector<FairHit *> sttHits = fHits[STT];
194  fAllHits.clear();
195  if (sttHits.size() > 2) {
196  FairHit *first = GetFirstHit(fGeometryMap);
197 
198  TVector2 firstHit(HitOnTrack(first));
199  TVector2 secondHit(HitOnTrack(sttHits.back()));
200  bool hasChanged = false;
201  if (firstHit.DeltaPhi(secondHit) < 0 && fClockwise) {
202  hasChanged = true;
203  fClockwise = false;
204  } else if (firstHit.DeltaPhi(secondHit) >= 0 && !fClockwise) {
205  hasChanged = true;
206  fClockwise = true;
207  }
208 
209  if (hasChanged) {
210  SortHits(firstHit, MVDpixel);
211  SortHits(firstHit, MVDstrip);
212  SortHits(firstHit, STT);
213  SortHits(firstHit, GEM);
214  fAllHits.insert(fAllHits.end(), fHits[MVDpixel].begin(), fHits[MVDpixel].end());
215  fAllHits.insert(fAllHits.end(), fHits[MVDstrip].begin(), fHits[MVDstrip].end());
216  fAllHits.insert(fAllHits.end(), fHits[STT].begin(), fHits[STT].end());
217  fAllHits.insert(fAllHits.end(), fHits[GEM].begin(), fHits[GEM].end());
218  } else {
219  SortHits(firstHit, MVDpixel);
220  SortHits(firstHit, MVDstrip);
221  fAllHits.insert(fAllHits.end(), fHits[MVDpixel].begin(), fHits[MVDpixel].end());
222  fAllHits.insert(fAllHits.end(), fHits[MVDstrip].begin(), fHits[MVDstrip].end());
223  fAllHits.insert(fAllHits.end(), fHits[STT].begin(), fHits[STT].end());
224  SortHits(firstHit, GEM);
225  fAllHits.insert(fAllHits.end(), fHits[GEM].begin(), fHits[GEM].end());
226  }
227  }
228  }
229 
230  friend std::ostream &operator<<(std::ostream &output, const TripletSolution &t)
231  {
232  output << "Track x/y/r " << t.fTrack.X() << "/" << t.fTrack.Y() << "/" << t.fTrack.Z() << " ";
233  if (t.fTriplet.fTripletHits[0] != nullptr) {
234  output << " trip: " << t.fTriplet.fTripletHits[0]->GetTubeID() << "/" << t.fTriplet.fTripletHits[1]->GetTubeID() << "/" << t.fTriplet.fTripletHits[2]->GetTubeID() << " ";
235  }
236  if (t.fHits.count(TripletSolution::detID::MVDpixel) > 0) {
237  output << t.detID_Names.at(TripletSolution::detID::MVDpixel) << " : ";
238  for (auto hit : t.fHits.at(TripletSolution::detID::MVDpixel)) {
239  output << hit->GetEntryNr() << "/";
240  }
241  output << " ";
242  }
243  if (t.fHits.count(TripletSolution::detID::MVDstrip) > 0) {
244  output << t.detID_Names.at(TripletSolution::detID::MVDstrip) << " : ";
245  for (auto hit : t.fHits.at(TripletSolution::detID::MVDstrip)) {
246  output << hit->GetEntryNr() << "/";
247  }
248  output << " ";
249  }
250  if (t.fHits.count(TripletSolution::detID::STT) > 0) {
251  output << t.detID_Names.at(TripletSolution::detID::STT) << " : ";
252  for (auto hit : t.fHits.at(TripletSolution::detID::STT)) {
253  PndSttHit *myHit = static_cast<PndSttHit *>(hit);
254  output << myHit->GetTubeID() << "/";
255  }
256  output << " ";
257  }
258  if (t.fHits.count(TripletSolution::detID::GEM) > 0) {
259  output << t.detID_Names.at(TripletSolution::detID::GEM) << " : ";
260  for (auto hit : t.fHits.at(TripletSolution::detID::GEM)) {
261  output << hit->GetEntryNr() << "/";
262  }
263  output << " ";
264  }
265 
266  output << "MSD: " << t.fMeanSquare;
267  return output;
268  }
269 
270  Triplet fTriplet{nullptr, nullptr, nullptr}; //< triplet used to create solution
271  TVector3 fTrack; //< circle coordinates of track in x,y,r in [cm]
272  std::map<detID, std::vector<FairHit *>> fHits;
273  std::vector<FairHit *> fAllHits;
274  double fMeanSquare = 1000000.;
275  bool fClockwise = true;
276 };
277 
279  std::vector<PndSttHit *> fFirstRow;
280  std::vector<PndSttHit *> fMidRow;
281  std::vector<PndSttHit *> fLastRow;
282 
284  {
285  fFirstRow.insert(fFirstRow.end(), right.fFirstRow.begin(), right.fFirstRow.end());
286  fMidRow.insert(fMidRow.end(), right.fMidRow.begin(), right.fMidRow.end());
287  fLastRow.insert(fLastRow.end(), right.fLastRow.begin(), right.fLastRow.end());
288 
289  return *this;
290  }
291 
292  friend std::ostream &operator<<(std::ostream &output, const TripletValues &t)
293  {
294  output << "FirstRow: ";
295  std::for_each(t.fFirstRow.begin(), t.fFirstRow.end(), [](PndSttHit *hit) { std::cout << hit->GetTubeID() << "(" << hit->GetX() << "," << hit->GetY() << ") /"; });
296  output << std::endl;
297  output << "MidRow: ";
298  std::for_each(t.fMidRow.begin(), t.fMidRow.end(), [](PndSttHit *hit) { std::cout << hit->GetTubeID() << "(" << hit->GetX() << "," << hit->GetY() << ") /"; });
299  output << std::endl;
300  output << "LastRow: ";
301  std::for_each(t.fLastRow.begin(), t.fLastRow.end(), [](PndSttHit *hit) { std::cout << hit->GetTubeID() << "(" << hit->GetX() << "," << hit->GetY() << ") /"; });
302  output << std::endl;
303 
304  return output;
305  }
306 };
307 
309  std::map<int, PndSttHit *> fMapCAToMidTube;
310  std::map<int, PndSttHit *> fMapCAToOuterTube;
311  std::map<PndSttHit *, int> fMapInnerTubeToCA;
312  std::map<PndSttHit *, int> fMapMidTubeToCA;
313 
314  void Reset()
315  {
316  fMapCAToMidTube.clear();
317  fMapCAToOuterTube.clear();
318  fMapInnerTubeToCA.clear();
319  fMapMidTubeToCA.clear();
320  }
321 };
322 
330  std::map<int, std::vector<PndSttHit *>> GetAllTubesByRow(std::vector<PndSttHit *> hits, PndSttGeometryMap *fGeometryMap, int &fAllHitsCounter)
331  {
332  std::map<int, std::vector<PndSttHit *>> result;
333  fAllHitsCounter = 0;
334  for (auto myHit : hits) {
335  auto it = std::find_if(result[fGeometryMap->GetRow(myHit->GetTubeID())].begin(), result[fGeometryMap->GetRow(myHit->GetTubeID())].end(),
336  [&myHit](const PndSttHit *hit) { return myHit->GetTubeID() == hit->GetTubeID(); });
337  if (it == result[fGeometryMap->GetRow(myHit->GetTubeID())].end()) {
338  result[fGeometryMap->GetRow(myHit->GetTubeID())].push_back(myHit);
339  fAllHitsCounter += 1;
340  } else {
341  if ((*it)->GetTimeStamp() > myHit->GetTimeStamp())
342  result[fGeometryMap->GetRow(myHit->GetTubeID())][it - result[fGeometryMap->GetRow(myHit->GetTubeID())].begin()] = myHit;
343  }
344  }
345  return result;
346  }
353  std::map<int, std::vector<std::vector<PndSttHit *>>>
354  GetTubeStructure(std::vector<PndSttHit *> hits, PndSttGeometryMap *fGeometryMap, int &fAllHitsCounter, bool &fIsStrongCurling)
355  {
356 
357  // fIsCurling = false;
358  fIsStrongCurling = false;
359 
360  std::map<int, std::vector<std::vector<PndSttHit *>>> result;
361  std::map<int, std::vector<PndSttHit *>> tubesByRow = GetAllTubesByRow(hits, fGeometryMap, fAllHitsCounter);
362 
363  int curlingRows = 0;
364 
365  for (auto tubes : tubesByRow) {
366  std::sort(tubes.second.begin(), tubes.second.end(), [](PndSttHit *first, PndSttHit *second) { return (first->GetTubeID() < second->GetTubeID()); });
367  std::vector<PndSttHit *> group;
368  int oldTubeId = -1;
369  if (tubes.second.size() > 0)
370  oldTubeId = tubes.second[0]->GetTubeID();
371  std::vector<std::vector<PndSttHit *>> rowGroups;
372 
373  for (auto sttHit : tubes.second) {
374  if (TMath::Abs(sttHit->GetTubeID() - oldTubeId) > 1) {
375  if (group.size() > 5 && (tubes.first != tubesByRow.rbegin()->first)) { // more than five tubes adjacent to each other in one row but not the last row
376  curlingRows++;
377  }
378  rowGroups.push_back(group);
379  group.clear();
380  }
381  group.push_back(sttHit);
382  oldTubeId = sttHit->GetTubeID();
383  }
384  rowGroups.push_back(group);
385 
386  if (group.size() > 5 && (tubes.first != tubesByRow.rbegin()->first)) { // more than five tubes adjacent to each other in one row but not the last row
387  // fIsCurling = true;
388  curlingRows++;
389  }
390 
391  result[tubes.first] = (rowGroups); // todo: better condition to identify strong curling tracks needed
392 
393  if (result[tubes.first].size() > 5) // more than 5 separated groups in one row
394  fIsStrongCurling = true;
395  }
396 
397  if (curlingRows > 2)
398  fIsStrongCurling = true;
399  // todo: The condition for a track being strongly curved is not good. Use number of neighbors to discard strongly curved tracks
400  // use number of hit tubes áą•er row to determine curved or curling tracks (no second circle in stt)
401  // for curved or curling tracks we can try to use one inner tube as last tube or we can merge produced clones
402  // std::cout << "curling track fIsCurling: " << fIsCurling << " fIsStrongCurling: " << fIsStrongCurling << " curlingRows: " << curlingRows << std::endl;
403 
404  return result;
405  }
406 
412  ReductionMaps CreateMaps(TripletValues &triplets, std::map<FairLink, int> &fMapHitstoCATracklet)
413  {
414  ReductionMaps maps;
415  maps.Reset();
416  for (auto InnerSttHit : triplets.fFirstRow) {
417  auto CAId_it = fMapHitstoCATracklet.find(InnerSttHit->GetEntryNr());
418 
419  if (CAId_it != fMapHitstoCATracklet.end()) {
420  // Is a ca tracklet
421  FairLink CALink = InnerSttHit->GetEntryNr();
422  maps.fMapInnerTubeToCA[InnerSttHit] = fMapHitstoCATracklet[CALink];
423  }
424  }
425  for (auto MidSttHit : triplets.fMidRow) {
426  auto CAId_it = fMapHitstoCATracklet.find(MidSttHit->GetEntryNr());
427 
428  if (CAId_it != fMapHitstoCATracklet.end()) {
429  // Is a ca tracklet
430  FairLink CALink = MidSttHit->GetEntryNr();
431  maps.fMapCAToMidTube[fMapHitstoCATracklet[CALink]] = MidSttHit;
432  maps.fMapMidTubeToCA[MidSttHit] = fMapHitstoCATracklet[CALink];
433  }
434  }
435  for (auto OuterSttHit : triplets.fLastRow) {
436  auto CAId_it = fMapHitstoCATracklet.find(OuterSttHit->GetEntryNr());
437 
438  if (CAId_it != fMapHitstoCATracklet.end()) {
439  // Is a ca tracklet
440  FairLink CALink = OuterSttHit->GetEntryNr();
441  maps.fMapCAToOuterTube[fMapHitstoCATracklet[CALink]] = OuterSttHit;
442  }
443  }
444  return maps;
445  }
446 
453  std::vector<Triplet> ReduceCombinatorics(TripletValues &triplets, std::map<FairLink, int> &fMapHitstoCATracklet, TClonesArray *sttHits, PndSttCA *fCATrackFinder,
454  PndSttGeometryMap *fGeometryMap, double &fMinDistance, bool &fWithCombiReduction)
455  {
456 
457  std::vector<Triplet> result;
458  if (fWithCombiReduction) {
459  ReductionMaps maps = CreateMaps(triplets, fMapHitstoCATracklet);
460 
461  std::vector<int> RemovedTubeIdsLast;
462  RemovedTubeIdsLast.clear();
463  std::vector<int> RemovedTubeIdsMid;
464  RemovedTubeIdsMid.clear();
465  for (PndSttHit *iTube : triplets.fFirstRow) {
466  LOG(debug) << "FirstRow: ";
467  std::for_each(triplets.fFirstRow.begin(), triplets.fFirstRow.end(), [](PndSttHit *hit) { LOG(debug) << hit->GetEntryNr() << "/"; });
468  LOG(debug) << "iTube: " << iTube->GetEntryNr() << " has tubeId: " << iTube->GetTubeID() << " (" << iTube->GetX() << "," << iTube->GetY() << ")";
469  LOG(debug) << "first hit " << *iTube;
470 
471  if (maps.fMapCAToMidTube.find(maps.fMapInnerTubeToCA[iTube]) == maps.fMapCAToMidTube.end() ||
472  fMapHitstoCATracklet.find(iTube->GetEntryNr()) == fMapHitstoCATracklet.end()) {
473  // inner tube has no connection to mid tube
474  for (auto mTube : triplets.fMidRow) {
475 
476  if (iTube->GetTubeID() == mTube->GetTubeID() || std::find(RemovedTubeIdsMid.begin(), RemovedTubeIdsMid.end(), mTube->GetTubeID()) !=
477  RemovedTubeIdsMid.end()) //||
478  // fGeometryMap->GetRow(iTube->GetTubeID()) >= fGeometryMap->GetRow(mTube->GetTubeID()))
479  continue;
480  LOG(debug) << "mid hit " << *mTube;
481 
482  if (maps.fMapCAToOuterTube.find(maps.fMapMidTubeToCA[mTube]) == maps.fMapCAToOuterTube.end() ||
483  fMapHitstoCATracklet.find(mTube->GetEntryNr()) == fMapHitstoCATracklet.end()) {
484  // mid tube has no connection to outer tube
485 
486  for (auto oTube : triplets.fLastRow) {
487  if (mTube->GetTubeID() == oTube->GetTubeID() || std::find(RemovedTubeIdsLast.begin(), RemovedTubeIdsLast.end(), oTube->GetTubeID()) !=
488  RemovedTubeIdsLast.end()) //||
489  // fGeometryMap->GetRow(oTube->GetTubeID()) <= fGeometryMap->GetRow(mTube->GetTubeID()))
490  continue;
491  LOG(debug) << "last hit " << *oTube;
492  if (sqrt((iTube->GetX() - oTube->GetX()) * (iTube->GetX() - oTube->GetX()) + (iTube->GetY() - oTube->GetY()) * (iTube->GetY() - oTube->GetY())) < fMinDistance)
493  continue;
494  Triplet t{iTube, mTube, oTube};
495  result.push_back(t);
496  }
497  } else {
498  // mid tube has a connection to outer tube
499  PndSttHit *connectedOuterTube = maps.fMapCAToOuterTube[maps.fMapMidTubeToCA[mTube]];
500  if (mTube->GetTubeID() == connectedOuterTube->GetTubeID()) {
501  PndTrackCand trackCand_temp = fCATrackFinder->GetFirstTrackCand(maps.fMapMidTubeToCA[mTube]);
502  for (int i = trackCand_temp.GetNHits() - 1; i >= trackCand_temp.GetNHits() / 2; i--) {
503  FairLink OuterLink = trackCand_temp.GetSortedHit(i);
504 
505  PndSttHit *OuterSttHit = (PndSttHit *)sttHits->At(OuterLink.GetIndex());
506 
507  if (!fGeometryMap->IsSkewedStraw(OuterSttHit->GetTubeID()) && OuterSttHit->GetTubeID() != mTube->GetTubeID()) {
508  connectedOuterTube = OuterSttHit;
509  break;
510  }
511  }
512 
513  LOG(debug) << *mTube << "," << *connectedOuterTube;
514  }
515  if (mTube->GetTubeID() == connectedOuterTube->GetTubeID()) {
516  LOG(debug) << "mTube == connectedOuterTube";
517  continue;
518  }
519  LOG(debug) << "last hit connected" << *connectedOuterTube;
520 
521  if (sqrt((iTube->GetX() - connectedOuterTube->GetX()) * (iTube->GetX() - connectedOuterTube->GetX()) +
522  (iTube->GetY() - connectedOuterTube->GetY()) * (iTube->GetY() - connectedOuterTube->GetY())) < fMinDistance)
523  continue;
524 
525  Triplet t{iTube, mTube, connectedOuterTube};
526  result.push_back(t);
527  RemovedTubeIdsLast.push_back(connectedOuterTube->GetTubeID());
528  }
529  }
530  } else {
531  // inner tube has a connection to mid tube
532  PndSttHit *connectedMidTube = maps.fMapCAToMidTube[maps.fMapInnerTubeToCA[iTube]];
533  PndSttHit *connectedMidTubeForCA = maps.fMapCAToMidTube[maps.fMapInnerTubeToCA[iTube]];
534 
535  if (iTube->GetTubeID() == connectedMidTube->GetTubeID()) {
536  PndTrackCand trackCand_temp = fCATrackFinder->GetFirstTrackCand(maps.fMapInnerTubeToCA[iTube]);
537  for (int i = trackCand_temp.GetNHits() / 2; i >= 0; i--) {
538  FairLink linkMid = trackCand_temp.GetSortedHit(i);
539  PndSttHit *MidSttHit = (PndSttHit *)sttHits->At(linkMid.GetIndex());
540 
541  if (!fGeometryMap->IsSkewedStraw(MidSttHit->GetTubeID()) && MidSttHit->GetTubeID() != iTube->GetTubeID()) {
542  connectedMidTube = MidSttHit;
543  break;
544  }
545  }
546  }
547 
548  if (iTube->GetTubeID() == connectedMidTube->GetTubeID()) {
549  continue;
550  }
551  LOG(debug) << "mid hit connected " << *connectedMidTube;
552  if (maps.fMapCAToOuterTube.find(maps.fMapInnerTubeToCA[iTube]) == maps.fMapCAToOuterTube.end()) {
553  // mid tube has no connection to outer tube
554  LOG(debug) << "mid tube has no connection to outer tube ";
555 
556  for (auto oTube : triplets.fLastRow) {
557  LOG(debug) << "outer hit " << *oTube;
558 
559  if (oTube->GetTubeID() == connectedMidTube->GetTubeID() ||
560  std::find(RemovedTubeIdsLast.begin(), RemovedTubeIdsLast.end(), oTube->GetTubeID()) != RemovedTubeIdsLast.end()) // ||
561  // fGeometryMap->GetRow(oTube->GetTubeID()) <= fGeometryMap->GetRow(connectedMidTube->GetTubeID()))
562  continue;
563  if (sqrt((iTube->GetX() - oTube->GetX()) * (iTube->GetX() - oTube->GetX()) + (iTube->GetY() - oTube->GetY()) * (iTube->GetY() - oTube->GetY())) < fMinDistance)
564  continue;
565 
566  Triplet t{iTube, connectedMidTube, oTube};
567  result.push_back(t);
568  }
569  } else {
570  // mid tube has a connection to outer tube
571  PndSttHit *connectedOuterTube = maps.fMapCAToOuterTube[maps.fMapMidTubeToCA[connectedMidTubeForCA]];
572  LOG(debug) << "mid tube has a connection to outer tube ";
573  LOG(debug) << "outer hit connected " << *connectedOuterTube;
574 
575  if (connectedOuterTube->GetTubeID() == connectedMidTube->GetTubeID()) {
576  PndTrackCand trackCand_temp = fCATrackFinder->GetFirstTrackCand(maps.fMapMidTubeToCA[connectedMidTubeForCA]);
577 
578  for (int i = trackCand_temp.GetNHits() - 1; i >= 0; i--) {
579  FairLink OuterLink = trackCand_temp.GetSortedHit(i);
580  PndSttHit *OuterSttHit = (PndSttHit *)sttHits->At(OuterLink.GetIndex());
581  LOG(debug) << "try outer hit " << *OuterSttHit;
582  if (!fGeometryMap->IsSkewedStraw(OuterSttHit->GetTubeID()) && OuterSttHit->GetTubeID() != connectedMidTube->GetTubeID()) {
583  connectedOuterTube = OuterSttHit;
584  break;
585  }
586  }
587  }
588  if (connectedMidTube->GetTubeID() == connectedOuterTube->GetTubeID()) {
589  continue;
590  }
591  LOG(debug) << "outer hit connected " << *connectedOuterTube;
592 
593  if (sqrt((iTube->GetX() - connectedOuterTube->GetX()) * (iTube->GetX() - connectedOuterTube->GetX()) +
594  (iTube->GetY() - connectedOuterTube->GetY()) * (iTube->GetY() - connectedOuterTube->GetY())) < fMinDistance)
595  continue;
596 
597  Triplet t{iTube, connectedMidTube, connectedOuterTube};
598  result.push_back(t);
599  RemovedTubeIdsLast.push_back(connectedOuterTube->GetTubeID());
600  }
601  RemovedTubeIdsMid.push_back(connectedMidTube->GetTubeID());
602  }
603  }
604  } else {
605  for (auto iTube : triplets.fFirstRow) {
606  for (auto mTube : triplets.fMidRow) {
607  // if (fGeometryMap->GetRow(iTube->GetTubeID()) >= fGeometryMap->GetRow(mTube->GetTubeID()))
608  // continue;
609  for (auto oTube : triplets.fLastRow) {
610  if (iTube->GetTubeID() == mTube->GetTubeID() ||
611  mTube->GetTubeID() == oTube->GetTubeID()) //||
612  // fGeometryMap->GetRow(oTube->GetTubeID()) <= fGeometryMap->GetRow(mTube->GetTubeID()))
613  continue;
614  if (sqrt((iTube->GetX() - oTube->GetX()) * (iTube->GetX() - oTube->GetX()) + (iTube->GetY() - oTube->GetY()) * (iTube->GetY() - oTube->GetY())) < fMinDistance)
615  continue;
616  Triplet t{iTube, mTube, oTube};
617  result.push_back(t);
618  }
619  }
620  }
621  }
622 
623  return result;
624  }
625 
633  bool IsTripletUsed(std::vector<TripletSolution> &solutions, Triplet &triplet)
634  {
635  auto sol = std::find_if(solutions.begin(), solutions.end(), [&](TripletSolution &sol) {
636  for (auto trip : triplet.fTripletHits) {
637  auto first = std::find_if(sol.fHits[TripletSolution::detID::STT].begin(), sol.fHits[TripletSolution::detID::STT].end(),
638  [&](FairHit *hit) { return (((PndSttHit *)hit)->GetTubeID() == trip->GetTubeID()); });
639  if (first == sol.fHits[TripletSolution::detID::STT].end()) {
640  return false;
641  }
642  }
643  return true;
644  });
645  if (sol != solutions.end())
646  return true;
647  else
648  return false;
649  }
650 
657  std::vector<TripletSolution> GenerateTripletTracks(Triplet triplet, std::vector<PndSttHit *> &sttHits, PndSttGeometryMap *fGeometryMap)
658  {
659  Thresholds threshold;
660  std::vector<TripletSolution> result;
661  std::vector<double *> tmpPoints(3);
662  for (int k = 0; k < triplet.fTripletHits.size(); k++) {
663 
664  double *pVar = new double[4];
665  pVar[0] = (triplet.fTripletHits[k]->GetX());
666  pVar[1] = (triplet.fTripletHits[k]->GetY());
667  pVar[2] = (triplet.fTripletHits[k]->GetIsochrone());
668  pVar[3] = (triplet.fTripletHits[k]->GetIsochroneError());
669  tmpPoints[k] = pVar;
670  }
671  double *apolloniusCircles = new double[6 * 8];
672  // std::cout << "apollonius for hit0 (" << tmpPoints[0][0] << "," << tmpPoints[0][1] << "," << tmpPoints[0][2] << "), hit1 (" << tmpPoints[1][0] << "," << tmpPoints[1][1] <<
673  // ","
674  // << tmpPoints[1][2] << "), hit2 (" << tmpPoints[2][0] << "," << tmpPoints[2][1] << "," << tmpPoints[2][2] << ")," << std::endl;
675 
676  PndHoughApollonius::ApolloniusCudaCalcCPU(1, tmpPoints[0], tmpPoints[1], tmpPoints[2], apolloniusCircles);
677 
678  for (int m = 0; m < 3; m++) {
679  delete[] tmpPoints[m];
680  }
681 
682  for (int solutionIndex = 0; solutionIndex < 8; solutionIndex++) { // there are 8 solutions
683  // std::cout << apolloniusCircles[(solutionIndex * 6) + 0] << " " << apolloniusCircles[(solutionIndex * 6) + 1] << " " << apolloniusCircles[(solutionIndex * 6) + 2] <<
684  // std::endl;
685  if (apolloniusCircles[(solutionIndex * 6) + 0] == 0 && apolloniusCircles[(solutionIndex * 6) + 1] == 0 && apolloniusCircles[(solutionIndex * 6) + 2] == 0)
686  continue;
687  // 1. if radius is not 0 (--> a circle could be calculated) and x is not nan
688  // 1. if x, y, r are not 0
689  else if ((!isnan(apolloniusCircles[(solutionIndex * 6) + 0]) && apolloniusCircles[(solutionIndex * 6) + 2] != 0) ||
690  (apolloniusCircles[(solutionIndex * 6) + 0] != 0 && apolloniusCircles[(solutionIndex * 6) + 1] != 0 && apolloniusCircles[(solutionIndex * 6) + 2] != 0)) {
691 
692  TVector3 apollonius{apolloniusCircles[(solutionIndex * 6) + 0], apolloniusCircles[(solutionIndex * 6) + 1], TMath::Abs(apolloniusCircles[(solutionIndex * 6) + 2])};
693  // std::cout << "apollonius circle: " << apollonius.X() << "," << apollonius.Y() << "," << apollonius.Z() << std::endl;
694  TripletSolution solution = FindHitsCloseToCircle(sttHits, apollonius, threshold.fDistanceThresholdSTTFar, fGeometryMap);
695  /*
696  std::vector<PndSttHit *> hits = FindHitsCloseToCircle(sttHits, apollonius, threshold.fDistanceThresholdSTTFar, fGeometryMap);
697 
698  TripletSolution solution(apollonius);
699 
700  solution.AddHits(hits);
701 
702  solution.SortStt(fGeometryMap);
703 
704  solution.fMeanSquare = MeanSquareDistance(solution);
705  */
706  solution.fTriplet = triplet;
707  LOG(debug) << solution;
708  result.push_back(solution);
709 
710  } else if (!isnan(apolloniusCircles[(solutionIndex * 6) + 0]) && !isnan(apolloniusCircles[(solutionIndex * 6) + 1]) && apolloniusCircles[(solutionIndex * 6) + 2] == 0) { //
711  // case for streight lines
712  // assume max momentum of 5 GeV/c (pTMax = sqrt(s)/2???) B = 2T --> rMax = 100/(0.3*B)*pT
713  double rMax = 100 / (0.3 * 2) * 5; // assume B = 2 and pT = 5 GeV/c
714  // determine center of circle as point on line perpendicular to streight line going through fiirst point of track and has a distance of rMax.
715  // determine perpendicular line
716  double mInverse = -1 / apolloniusCircles[(solutionIndex * 6) + 0];
717  double b = tmpPoints[0][1] - tmpPoints[0][0] * mInverse;
718  // determine intersection poin of the two lines:
719  double intersectionPointX = (b - apolloniusCircles[(solutionIndex * 6) + 1]) / (apolloniusCircles[(solutionIndex * 6) + 0] - mInverse);
720  double intersectionPointY = mInverse * intersectionPointX + b;
721  // find center of circle as intersection point of line and circle with center (intersectionPointX, intersectionPointY) and radius rMax
722  std::vector<double> circle{intersectionPointX, intersectionPointY, rMax};
723  std::vector<double> IP = calcIntersectionPointCircleLine(circle, mInverse, b, 0);
724  TVector3 apollonius{IP[0], IP[1], rMax};
725  TripletSolution solution = FindHitsCloseToCircle(sttHits, apollonius, threshold.fDistanceThresholdSTTFar, fGeometryMap);
726 
727  /*
728  std::vector<PndSttHit *> hits = FindHitsCloseToCircle(sttHits, apollonius, threshold.fDistanceThresholdSTTFar, fGeometryMap);
729 
730  TripletSolution solution(apollonius);
731 
732  solution.AddHits(hits);
733 
734  solution.SortStt(fGeometryMap);
735 
736  solution.fMeanSquare = MeanSquareDistance(solution);
737  */
738  solution.fTriplet = triplet;
739 
740  result.push_back(solution);
741  }
742  }
743 
744  delete[] apolloniusCircles;
745  return result;
746  }
747 
748  std::vector<double> calcIntersectionPointCircleLine(std::vector<double> circle, double m, double b, double Ax)
749  {
750 
751  double x0, y0, r, p, q, intersectionPointX1, intersectionPointY1, intersectionPointX2, intersectionPointY2;
752  if (m == 0 && b == 0) {
753  // m=0;
754  x0 = circle[0];
755  y0 = circle[1];
756  r = circle[2];
757  intersectionPointX1 = Ax;
758  intersectionPointX2 = Ax;
759  // cout << "y0: " << y0 << " r "<<r<<" x0 "<<x0<< " Ax "<< Ax <<endl;
760  intersectionPointY1 = y0 + sqrt(r * r - (Ax - x0) * (Ax - x0));
761  intersectionPointY2 = y0 - sqrt(r * r - (Ax - x0) * (Ax - x0));
762  // cout << "intersectionPointY1: " << intersectionPointY1 << endl;
763  // cout << "intersectionPointY2: " << intersectionPointY2 << endl;
764  } else {
765  // m = (Ay-By)/(Ax-Bx);
766 
767  // b = Ay-m*Ax;
768  x0 = circle[0];
769  y0 = circle[1];
770  r = circle[2];
771  p = (2 * m * (b - y0) - 2 * x0) / (m * m + 1);
772  q = (x0 * x0 + (b - y0) * (b - y0) - r * r) / (m * m + 1);
773  // cout << "m: " << m << endl;
774  // cout << "p: " << p << endl;
775  // cout << "q: " << q << endl;
776 
777  intersectionPointX1 = -p / 2 + sqrt(p * p / 4 - q);
778  intersectionPointY1 = m * intersectionPointX1 + b;
779 
780  intersectionPointX2 = -p / 2 - sqrt(p * p / 4 - q);
781  intersectionPointY2 = m * intersectionPointX2 + b;
782  }
783  vector<double> intersectionPoints;
784  intersectionPoints.push_back(intersectionPointX1);
785  intersectionPoints.push_back(intersectionPointY1);
786  intersectionPoints.push_back(intersectionPointX2);
787  intersectionPoints.push_back(intersectionPointY2);
788  return intersectionPoints;
789  }
790 
798  /*std::vector<PndSttHit *> FindHitsCloseToCircle(std::vector<PndSttHit *> &sttHits, TVector3 &circle, double &fDistanceThresholdSTTFar, PndSttGeometryMap *fGeometryMap)
799  {
800  double threshold;
801  std::vector<PndSttHit *> result;
802  if (circle.Z() != 0){
803  for (auto sttHit : sttHits) {
804  PndSttHit *myHit = sttHit;
805  if (fGeometryMap->IsSkewedStraw(myHit->GetTubeID())) {
806  continue;
807  }
808 
809  threshold = fDistanceThresholdSTTFar; // DetermineDistanceThreshold(TripletSolution::STT, temp, (FairHit *)myHit);
810  double squaredDistance = (myHit->GetX() - circle.X()) * (myHit->GetX() - circle.X()) + (myHit->GetY() - circle.Y()) * (myHit->GetY() - circle.Y());
811  double squaredThreshold = ( threshold + circle.Z() + sttHit->GetIsochrone() ) * ( threshold + circle.Z() + sttHit->GetIsochrone() );
812  if( squaredDistance >= squaredThreshold ){
813  continue;
814  }
815 
816  if(sttHit->GetIsochrone() != 0 && TMath::Abs(DistanceCircleSttHit(circle, myHit, squaredDistance)) < threshold){
817  result.push_back(myHit);
818  }
819  else if(sttHit->GetIsochrone() == 0 && TMath::Abs(DistanceCircleSttHit(circle, myHit, squaredDistance)) < threshold + 0.5) { // workaround for bug in STT digitization
820  (isochrone radius = 0) result.push_back(myHit);
821  }
822  }
823  }
824  // streight line
825  else{
826  for (auto sttHit : sttHits) {
827  PndSttHit *myHit = sttHit;
828  if (fGeometryMap->IsSkewedStraw(myHit->GetTubeID())) {
829  continue;
830  }
831  double squaredDistance = SquaredDistanceLineSttHit(circle, myHit);
832  if( squaredDistance >= (threshold + 0.5) * (threshold + 0.5) )
833  continue;
834 
835  if(sttHit->GetIsochrone() != 0 && TMath::Abs(DistanceLineSttHit(circle, myHit, squaredDistance)) < threshold){
836  result.push_back(myHit);
837  }
838  else if(sttHit->GetIsochrone() == 0 && TMath::Abs(DistanceLineSttHit(circle, myHit, squaredDistance)) < threshold + 0.5) { // workaround for bug in STT digitization
839  (isochrone radius = 0) result.push_back(myHit);
840  }
841  }
842  }
843  return result;
844  }*/
845  TripletSolution FindHitsCloseToCircle(std::vector<PndSttHit *> &sttHits, TVector3 &circle, double &fDistanceThresholdSTTFar, PndSttGeometryMap *fGeometryMap)
846  {
847  TripletSolution solution(circle);
848  double MeanSquareDistance = 0.0;
849  double threshold;
850  std::vector<PndSttHit *> result;
851  if (circle.Z() != 0) {
852  for (auto sttHit : sttHits) {
853  PndSttHit *myHit = sttHit;
854  if (fGeometryMap->IsSkewedStraw(myHit->GetTubeID())) {
855  continue;
856  }
857 
858  threshold = fDistanceThresholdSTTFar; // DetermineDistanceThreshold(TripletSolution::STT, temp, (FairHit *)myHit);
859  double squaredDistance = (myHit->GetX() - circle.X()) * (myHit->GetX() - circle.X()) + (myHit->GetY() - circle.Y()) * (myHit->GetY() - circle.Y());
860  double squaredThreshold = (threshold + circle.Z() + sttHit->GetIsochrone()) * (threshold + circle.Z() + sttHit->GetIsochrone());
861  if (squaredDistance >= squaredThreshold) {
862  continue;
863  }
864  double d = DistanceCircleSttHit(circle, myHit, squaredDistance);
865  if (sttHit->GetIsochrone() != 0 && TMath::Abs(d) < threshold) {
866  result.push_back(myHit);
867  MeanSquareDistance += d * d;
868  } else if (sttHit->GetIsochrone() == 0 && TMath::Abs(d) < threshold + 0.5) { // workaround for bug in STT digitization (isochrone radius = 0)
869  result.push_back(myHit);
870  MeanSquareDistance += d * d;
871  }
872  }
873  }
874  // streight line
875  else {
876  for (auto sttHit : sttHits) {
877  PndSttHit *myHit = sttHit;
878  if (fGeometryMap->IsSkewedStraw(myHit->GetTubeID())) {
879  continue;
880  }
881  double squaredDistance = SquaredDistanceLineSttHit(circle, myHit);
882  if (squaredDistance >= (threshold + 0.5) * (threshold + 0.5))
883  continue;
884  double d = DistanceLineSttHit(circle, myHit, squaredDistance);
885  if (sttHit->GetIsochrone() != 0 && TMath::Abs(d) < threshold) {
886  result.push_back(myHit);
887  MeanSquareDistance += d * d;
888  } else if (sttHit->GetIsochrone() == 0 && TMath::Abs(d) < threshold + 0.5) { // workaround for bug in STT digitization (isochrone radius = 0)
889  result.push_back(myHit);
890  MeanSquareDistance += d * d;
891  }
892  }
893  }
894  solution.AddHits(result);
895  solution.SortStt(fGeometryMap);
896  solution.fMeanSquare = MeanSquareDistance / result.size();
897 
898  return solution;
899  }
900 
902  {
903  double result = 0.0;
904  if (solution.fTrack.Z() == 0) {
905  // for (auto hit : solution.fHits[TripletSolution::STT]) {
906  // result += TMath::Power(DistanceLineSttHit(solution.fTrack, static_cast<PndSttHit *>(hit)), 2);
907  // double d = DistanceLineSttHit(solution.fTrack, static_cast<PndSttHit *>(hit));
908  // result += d * d;
909  //}
910  for (auto hit : solution.fHits[TripletSolution::MVDpixel]) {
911  double d = DistanceLinePoint(solution.fTrack, hit);
912  result += d * d;
913  }
914  for (auto hit : solution.fHits[TripletSolution::MVDstrip]) {
915  double d = DistanceLinePoint(solution.fTrack, hit);
916  result += d * d;
917  }
918  for (auto hit : solution.fHits[TripletSolution::GEM]) {
919  double d = DistanceLinePoint(solution.fTrack, hit);
920  result += d * d;
921  }
922  result /= solution.GetNHits();
923  } else {
924  // for (auto hit : solution.fHits[TripletSolution::STT]) {
925  // double d = DistanceCircleSttHit(solution.fTrack, static_cast<PndSttHit *>(hit));
926  // result += d * d;
927  //}
928  for (auto hit : solution.fHits[TripletSolution::MVDpixel]) {
929  double d = DistanceCirclePoint(solution.fTrack, hit);
930  result += d * d;
931  }
932  for (auto hit : solution.fHits[TripletSolution::MVDstrip]) {
933  double d = DistanceCirclePoint(solution.fTrack, hit);
934  result += d * d;
935  }
936  for (auto hit : solution.fHits[TripletSolution::GEM]) {
937  double d = DistanceCirclePoint(solution.fTrack, hit);
938  result += d * d;
939  }
940  result /= solution.GetNHits();
941  }
942  return result;
943  }
944 
945  double DistanceCirclePoint(TVector3 &circle, FairHit *hit)
946  {
947 
948  TVector2 hitVec{hit->GetX(), hit->GetY()};
949  TVector2 circ{circle.X(), circle.Y()};
950 
951  // double distCenters = (hitVec - circ).Mod();
952  double distCenters = sqrt((hitVec.X() - circ.X()) * (hitVec.X() - circ.X()) + (hitVec.Y() - circ.Y()) * (hitVec.Y() - circ.Y()));
953  return (distCenters - circle.Z());
954  }
955 
956  double DistanceCircleSttHit(TVector3 &circle, PndSttHit *sttHit)
957  {
958 
959  TVector2 hit{sttHit->GetX(), sttHit->GetY()};
960  TVector2 circ{circle.X(), circle.Y()};
961 
963  double distCenters = sqrt((hit.X() - circ.X()) * (hit.X() - circ.X()) + (hit.Y() - circ.Y()) * (hit.Y() - circ.Y()));
964  if (distCenters - circle.Z() > 0) {
965  return (distCenters - circle.Z() - sttHit->GetIsochrone());
966  } else {
967  return (distCenters - circle.Z() + sttHit->GetIsochrone());
968  }
969  }
970 
971  double DistanceCircleSttHit(TVector3 &circle, PndSttHit *sttHit, double &sqaredDistance)
972  {
974  double distCenters = sqrt(sqaredDistance);
975  if (distCenters - circle.Z() > 0) {
976  return (distCenters - circle.Z() - sttHit->GetIsochrone());
977  } else {
978  return (distCenters - circle.Z() + sttHit->GetIsochrone());
979  }
980  }
981 
982  double DistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit, double &squaredDistance) { return sqrt(squaredDistance); }
983 
984  double DistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit)
985  {
986  /*
987  double m = circle.X(); // line parameters y = m * x + b
988  double b = circle.Y(); // line parameters y = m * x + b
989 
990  double x2 = (sttHit->GetY() + sttHit->GetX() / m - b) / (m + 1 / m);
991  double y2 = -1 / m * x2 + sttHit->GetY() + sttHit->GetX() / m;
992 
993  double d = sqrt((sttHit->GetX() - x2) * (sttHit->GetX() - x2) + (sttHit->GetY() - y2) * (sttHit->GetY() - y2)) - abs(sttHit->GetIsochrone());
994 
995  return d;
996  */
997  return sqrt(SquaredDistanceLineSttHit(circle, sttHit));
998  }
999 
1000  double SquaredDistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit)
1001  {
1002 
1003  double m = circle.X(); // line parameters y = m * x + b
1004  double b = circle.Y(); // line parameters y = m * x + b
1005 
1006  double x2 = (sttHit->GetY() + sttHit->GetX() / m - b) / (m + 1 / m);
1007  double y2 = -1 / m * x2 + sttHit->GetY() + sttHit->GetX() / m;
1008 
1009  return ((sttHit->GetX() - x2) * (sttHit->GetX() - x2) + (sttHit->GetY() - y2) * (sttHit->GetY() - y2)) - abs(sttHit->GetIsochrone());
1010  }
1011 
1012  double DistanceLinePoint(TVector3 &circle, FairHit *hit)
1013  {
1014 
1015  double m = circle.X(); // line parameters y = m * x + b
1016  double b = circle.Y(); // line parameters y = m * x + b
1017 
1018  double x2 = (hit->GetY() + hit->GetX() / m - b) / (m + 1 / m);
1019  double y2 = -1 / m * x2 + hit->GetY() + hit->GetX() / m;
1020 
1021  double d = sqrt((hit->GetX() - x2) * (hit->GetX() - x2) + (hit->GetY() - y2) * (hit->GetY() - y2));
1022 
1023  return d;
1024  }
1025 
1031  void CheckContinuitySolutions(std::vector<TripletSolution> &solutions, PndSttGeometryMap *fGeometryMap)
1032  {
1033  solutions.erase(std::remove_if(solutions.begin(), solutions.end(), [&](TripletSolution &sol) { return !IsContinuous(sol, fGeometryMap); }), solutions.end());
1034  }
1035 
1042  bool IsContinuous(TripletSolution &solution, PndSttGeometryMap *fGeometryMap)
1043  {
1044  PndTrackEvaluatorDetStt solutionTest(fGeometryMap);
1045  // std::cout << "IsContinuous? solution: " << solution <<std::endl;
1046  int j = 0;
1047  bool goodSolution = true;
1048 
1049  if (solution.fHits[TripletSolution::detID::STT].size() == 0) {
1050  // std::cout << "has no stt hits" << std::endl;
1051  return false;
1052  }
1053 
1054  solution.SortStt(fGeometryMap);
1055 
1056  // std::cout << "solution after sorting: " << solution <<std::endl;
1057  goodSolution = solutionTest.CheckFirstHit((PndSttHit *)solution.fHits[TripletSolution::detID::STT].front());
1058  PndSttHit *previousHit = (PndSttHit *)solution.fHits[TripletSolution::detID::STT].front();
1059  for (auto hit : solution.fHits[TripletSolution::detID::STT]) {
1060  PndSttHit *sttHit = (PndSttHit *)hit;
1061  if (sttHit == previousHit) {
1062  continue;
1063  } else {
1064  bool good = solutionTest.CheckTwoHits(previousHit, sttHit);
1065  if (good != true) {
1066  // std::cout << "is not conituous for hit (" << sttHit->GetX() << "," << sttHit->GetY() << ") and (" << previousHit->GetX() << "," << previousHit->GetY() << ")" <<
1067  // std::endl;
1068  return false;
1069  }
1070  previousHit = sttHit;
1071  }
1072  }
1073 
1074  if (goodSolution) {
1075  // std::cout << "continuous solution found" << std::endl;
1076  return true;
1077  } else {
1078  // std::cout << "is not conituous: goodSolution: " << goodSolution << std::endl;
1079 
1080  return false;
1081  }
1082  }
1083 
1089  void AddOtherDetectors(vector<TripletSolution> &solutions, PndSttStrawMap *fStrawMap, std::map<TString, TClonesArray *> &fBranchMap)
1090  {
1091  Thresholds threshold;
1092 
1093  for (int i = 0; i < solutions.size(); i++) {
1094  std::vector<int> sectors;
1095  sectors.clear();
1096  double phiHigh = 0;
1097  double phiLow = 0;
1098  for (int n = 0; n < solutions[i].fHits[TripletSolution::detID::STT].size(); n++) {
1099  PndSttHit *sttHit = (PndSttHit *)solutions[i].fHits[TripletSolution::detID::STT][n];
1100  int sectorId = fStrawMap->GetSector(sttHit->GetTubeID());
1101  if (std::find(sectors.begin(), sectors.end(), sectorId) == sectors.end()) {
1102  sectors.push_back(sectorId);
1103  }
1104  }
1105  for (int j = 0; j < sectors.size(); j++) {
1106  vector<int> FirstSectorRow = fStrawMap->GetStrawRow(sectors[j], 0);
1107 
1108  double phiLowTemp = TMath::ATan2(fStrawMap->GetTube(FirstSectorRow[0])->GetPosition().Y(), fStrawMap->GetTube(FirstSectorRow[0])->GetPosition().X());
1109  double phiHighTemp = TMath::ATan2(fStrawMap->GetTube(FirstSectorRow[FirstSectorRow.size() - 1])->GetPosition().Y(),
1110  fStrawMap->GetTube(FirstSectorRow[FirstSectorRow.size() - 1])->GetPosition().X());
1111  if (phiLowTemp < 0)
1112  phiLowTemp = 2 * TMath::Pi() + phiLowTemp;
1113  if (phiHighTemp < 0)
1114  phiHighTemp = 2 * TMath::Pi() + phiHighTemp;
1115 
1116  if (phiHigh == 0 || phiHigh < phiHighTemp)
1117  phiHigh = phiHighTemp;
1118  if (phiLow == 0 || phiLow > phiLowTemp)
1119  phiLow = phiLowTemp;
1120  }
1121 
1122  for (auto it = fBranchMap.begin(); it != fBranchMap.end(); it++) {
1123  for (int j = 0; j < it->second->GetEntriesFast(); j++) {
1124  FairHit *hit = (FairHit *)it->second->At(j);
1125  double phi = TMath::ATan2(hit->GetY(), hit->GetX());
1126  if (phi < 0)
1127  phi = 2 * TMath::Pi() + phi;
1128  double d;
1129  if (solutions[i].fTrack.Z() != 0)
1130  d = DistanceCirclePoint(solutions[i].fTrack, hit);
1131  else if (solutions[i].fTrack.Z() == 0)
1132  d = DistanceLinePoint(solutions[i].fTrack, hit);
1133 
1134  if (it->first == "MVDHitsPixel") {
1135  // std::cout << "Track: " << solutions[i].fTrack.X() << "/" << solutions[i].fTrack.Y() << "/" << solutions[i].fTrack.Z() << " MVDHitsPixel: (" << hit->GetX() << "," <<
1136  // hit->GetY() << ") d: " << d << " threshold: " << threshold.fDistanceThresholdMVDMid2 << " phi: " << phi << " philow: " << phiLow - (30 * TMath::Pi() / 180.) << "
1137  // phiHigh: " << phiHigh + (30 * TMath::Pi() / 180.)<< std::endl;
1138  if (abs(d) < threshold.fDistanceThresholdMVDMid2 && phi < (phiHigh + (30 * TMath::Pi() / 180.)) &&
1139  phi > (phiLow - (30 * TMath::Pi() / 180.))) { // for MVD choose a valid angle of sector borders +- 30 deg (30 deg is a randomly chosen value)
1140  solutions[i].AddHit(TripletSolution::detID::MVDpixel, hit);
1141  }
1142  }
1143  if (it->first == "MVDHitsStrip") {
1144  // std::cout << "Track: " << solutions[i].fTrack.X() << "/" << solutions[i].fTrack.Y() << "/" << solutions[i].fTrack.Z() << " MVDHitsStrip: (" << hit->GetX() << "," <<
1145  // hit->GetY() << ") d: " << d << " threshold: " << threshold.fDistanceThresholdMVDMid2 << " phi: " << phi << " philow: " << phiLow - (30 * TMath::Pi() / 180.) << "
1146  // phiHigh: " << phiHigh + (30 * TMath::Pi() / 180.)<< std::endl;
1147  if (abs(d) < threshold.fDistanceThresholdMVDMid2 && phi < (phiHigh + (30 * TMath::Pi() / 180.)) && phi > (phiLow - (30 * TMath::Pi() / 180.))) {
1148  solutions[i].AddHit(TripletSolution::detID::MVDstrip, hit);
1149  }
1150  }
1151  if (it->first == "GEMHit") {
1152  if (abs(d) < threshold.fDistanceThresholdGEM && phi < phiHigh && phi > phiLow) {
1153  solutions[i].AddHit(TripletSolution::detID::GEM, hit);
1154  }
1155  }
1156  if (it->first == "STTHit") {
1157  PndSttHit *sttHit = (PndSttHit *)hit;
1158  if (fStrawMap->IsSkewedStraw(sttHit->GetTubeID()) && std::find(sectors.begin(), sectors.end(), fStrawMap->GetSector(sttHit->GetTubeID())) != sectors.end()) {
1159  if (abs(d) < threshold.fDistanceThresholdSTTSkewed) {
1160  solutions[i].AddHit(TripletSolution::detID::STT, hit);
1161  }
1162  }
1163  }
1164  if (it->first == "STTCombinedSkewedHits") {
1165  PndSttSkewedHit *SkewedSttHit = (PndSttSkewedHit *)hit;
1166  std::pair<Int_t, Int_t> tubeIDs = SkewedSttHit->GetTubeIDs();
1167 
1168  if (abs(d) < threshold.fDistanceThresholdSTTCombinedSkewed) {
1169  for (int j = 0; j < fBranchMap["STTHit"]->GetEntriesFast(); j++) {
1170  PndSttHit *sttHit = (PndSttHit *)fBranchMap["STTHit"]->At(j);
1171  if ((sttHit->GetTubeID() == tubeIDs.first || sttHit->GetTubeID() == tubeIDs.second) &&
1172  (std::find(sectors.begin(), sectors.end(), fStrawMap->GetSector(sttHit->GetTubeID())) != sectors.end())) {
1173  if (solutions[i].fHits.count(TripletSolution::detID::STT) == 0) {
1174  solutions[i].fHits[TripletSolution::detID::STT];
1175  }
1176  if (std::find(solutions[i].fHits[TripletSolution::detID::STT].begin(), solutions[i].fHits[TripletSolution::detID::STT].end(), (FairHit *)sttHit) ==
1177  solutions[i].fHits[TripletSolution::detID::STT].end()) { // add only if hit is not in dataset
1178  solutions[i].fHits[TripletSolution::detID::STT].push_back((FairHit *)sttHit);
1179  }
1180  }
1181  }
1182  }
1183  }
1184  }
1185  }
1186  solutions[i].fMeanSquare += MeanSquareDistance(solutions[i]);
1187  }
1188  }
1189 
1195  std::vector<TripletSolution> FindBestSolutions(std::vector<TripletSolution> &solutions)
1196  {
1197  std::vector<TripletSolution> result;
1198  LOG(debug) << "find best Solution out of " << solutions.size() << " possible solutions";
1199 
1200  std::vector<TripletSolution> groupedTracks(solutions.size());
1201 
1202  int rSize = solutions.size();
1203  std::sort(solutions.begin(), solutions.end(),
1204  [](TripletSolution &first, TripletSolution &second) { return (first.fHits[TripletSolution::detID::STT].size() > second.fHits[TripletSolution::detID::STT].size()); });
1205 
1206  int i = 0;
1207  int nResults = 0;
1208  while (rSize > 0) {
1209  LOG(debug) << "TrackGroup: " << i++;
1210  TripletSolution first = solutions.front();
1211  LOG(debug) << first;
1212 
1213  // copy all tracks with the same hit tubes into the vector grouped Tracks
1214  std::copy_if(solutions.begin(), solutions.end(), groupedTracks.begin(), [&](TripletSolution &solution) {
1215  bool equalTubes = true;
1216  std::for_each(solution.fHits[TripletSolution::detID::STT].begin(), solution.fHits[TripletSolution::detID::STT].end(), [&](FairHit *hit) {
1217  if (std::find_if(first.fHits[TripletSolution::detID::STT].begin(), first.fHits[TripletSolution::detID::STT].end(), [&](FairHit *firstHit) {
1218  return (((PndSttHit *)firstHit)->GetTubeID() == ((PndSttHit *)hit)->GetTubeID());
1219  }) == first.fHits[TripletSolution::detID::STT].end()) {
1220  equalTubes = false;
1221  }
1222  });
1223  if (equalTubes == true) {
1224  nResults++;
1225  }
1226  return equalTubes;
1227  // if (first.fHits[TripletSolution::detID::STT] == solution.fHits[TripletSolution::detID::STT]) {
1228  // nResults++;
1229  // return true;
1230  // } else
1231  // return false;
1232  });
1233 
1234  LOG(debug) << "GroupedTracks: ";
1235  std::for_each(groupedTracks.begin(), groupedTracks.end(), [](TripletSolution &sol) { LOG(debug) << sol; });
1236 
1237  solutions.resize(nResults);
1238  nResults = 0;
1239  solutions.erase(std::remove_if(solutions.begin(), solutions.end(),
1240  [&](TripletSolution &solution) {
1241  bool equalTubes = true;
1242  std::for_each(solution.fHits[TripletSolution::detID::STT].begin(), solution.fHits[TripletSolution::detID::STT].end(), [&](FairHit *hit) {
1243  if (std::find_if(first.fHits[TripletSolution::detID::STT].begin(), first.fHits[TripletSolution::detID::STT].end(), [&](FairHit *firstHit) {
1244  return (((PndSttHit *)firstHit)->GetTubeID() == ((PndSttHit *)hit)->GetTubeID());
1245  }) == first.fHits[TripletSolution::detID::STT].end()) {
1246  equalTubes = false;
1247  }
1248  });
1249  return equalTubes;
1250  }),
1251  solutions.end());
1252  rSize = solutions.size();
1253 
1254  // save only the track with the smalles mean square
1255  std::sort(groupedTracks.begin(), groupedTracks.end(), [](TripletSolution &a, TripletSolution &b) { return (a.fMeanSquare < b.fMeanSquare); });
1256  result.push_back(groupedTracks[0]); // add track with lowest mean square
1257 
1258  // add track with highest number of hits (and lowest mean square if more than one)
1259  std::sort(groupedTracks.begin(), groupedTracks.end(),
1260  [](TripletSolution &a, TripletSolution &b) { return (a.fHits[TripletSolution::detID::STT].size() > b.fHits[TripletSolution::detID::STT].size()); });
1261 
1262  int maxNHits = groupedTracks[0].fHits[TripletSolution::detID::STT].size();
1264  double lowestMeanSquare = 10000.;
1265  if (groupedTracks[0].fHits[TripletSolution::detID::STT].size() > result[0].fHits[TripletSolution::detID::STT].size()) {
1266  for (auto track : groupedTracks) {
1267  if (track.fHits[TripletSolution::detID::STT].size() < maxNHits)
1268  break;
1269  if (track.fMeanSquare < lowestMeanSquare) {
1270  lowestMeanSquare = track.fMeanSquare;
1271  best = track;
1272  }
1273  }
1274  result.push_back(best); // add track with largest number of hits if not already in
1275  }
1276  LOG(debug) << "GroupedTracks solutions: ";
1277  std::for_each(result.begin(), result.end(), [](TripletSolution &sol) { LOG(debug) << sol; });
1278  }
1279 
1280  return result;
1281  }
1282 
1291  std::vector<TripletSolution> CheckCombinedSolutions(std::vector<TripletSolution> &solutions, int nExpectedTracks)
1292  {
1293  LOG(debug) << "Combine tracks with identical hits. Expected tracks: " << nExpectedTracks << ", Found Tracks: " << solutions.size();
1294 
1295  // if (fIsCurling) {
1296  // nExpectedTracks--;
1297  // }
1298  std::vector<TripletSolution> result;
1299  if (nExpectedTracks < 1) {
1300  LOG(debug) << "-E- no Track expected: " << nExpectedTracks;
1301  return solutions;
1302  }
1303  int diff = solutions.size() - nExpectedTracks;
1304  // Combine Track Solutions: combines all found tracks to groups of tracks possibly belonging together
1305  if (diff < 0) {
1306  // std::cout << "Less tracks as expected. All returned" << std::endl;
1307  return solutions; // todo: better to return empty solutions?
1308  }
1309  // std::cout << "solutions.size(): " << solutions.size() << " nExpectedTracks:" << nExpectedTracks << " diff: " << diff << std::endl;
1310  if (diff > 10) {
1311  // std::cout << "Too many combinations possible. NO combinations done" << std::endl;
1312  return result; // todo: better to return empty solutions?
1313  }
1314 
1315  std::vector<std::vector<int>> combinations = GetKOutOfN(nExpectedTracks, solutions.size());
1316  /*
1317  for (int i = 0; i < combinations.size(); i++) {
1318  std::cout << "combination: ";
1319  for (int j = 0; j < combinations[i].size(); j++) {
1320  std::cout << combinations[i][j] << " / ";
1321  }
1322  std::cout << std::endl;
1323  }
1324  */
1325  // Check Combined Track Solutions if they are a possible solution
1326  result = CheckSolutions(solutions, combinations);
1327 
1328  return result;
1329  }
1330 
1338  std::vector<TripletSolution> CheckSolutions(std::vector<TripletSolution> &solutions, std::vector<std::vector<int>> combinations)
1339  {
1340  std::vector<TripletSolution> result;
1341 
1342  // determines all tubes of a combination of tracks
1343  std::vector<std::pair<std::vector<int>, int>> uniqueTubesPerCombination;
1344  std::for_each(combinations.begin(), combinations.end(),
1345  [&](std::vector<int> combi) { uniqueTubesPerCombination.push_back(make_pair(combi, GetUniqueTubeIDs(solutions, combi).size())); });
1346 
1347  // sorts the vector containing the track combinations by the number of found tubes
1348  std::sort(uniqueTubesPerCombination.begin(), uniqueTubesPerCombination.end(),
1349  [](std::pair<std::vector<int>, int> &first, std::pair<std::vector<int>, int> &second) { return first.second > second.second; });
1350 
1351  LOG(debug) << "Combinations TubeCounts: " << uniqueTubesPerCombination.size();
1352  // std::for_each(uniqueTubesPerCombination.begin(), uniqueTubesPerCombination.end(), [](std::pair<std::vector<int>, int> &combi) {
1353  // std::for_each(combi.first.begin(), combi.first.end(), [](int &val) { std::cout << val << "/"; });
1354  // std::cout << " counts " << combi.second << std::endl;
1355  // });
1356  int highestCount = uniqueTubesPerCombination.front().second;
1357 
1358  std::vector<TripletSolution> tmpSolutions;
1359  std::vector<int> solutionsUsed;
1360  for (auto combi : uniqueTubesPerCombination) {
1361  if (highestCount - combi.second < 1) { // take the solution with the highest hits found todo: this has to be checked
1362  for (auto sol : combi.first) {
1363  if (std::count(solutionsUsed.begin(), solutionsUsed.end(), sol) == 0) {
1364  tmpSolutions.push_back(solutions[sol]);
1365  solutionsUsed.push_back(sol);
1366  }
1367  }
1368  } else {
1369  break;
1370  }
1371  }
1372  result = tmpSolutions;
1373  return result;
1374  }
1375 
1383  std::vector<int> GetUniqueTubeIDs(std::vector<TripletSolution> &solutions, std::vector<int> combinations)
1384  {
1385  std::vector<int> result;
1386  std::for_each(combinations.begin(), combinations.end(), [&](int sol) { // saves all tubes of all tracks in combinations
1387  std::vector<FairHit *> sttHits(solutions[sol].fHits[TripletSolution::STT]);
1388  std::for_each(sttHits.begin(), sttHits.end(), [&](FairHit *hit) { // saves all tubes of a track
1389  if (std::count(result.begin(), result.end(), ((PndSttHit *)hit)->GetTubeID()) == 0) // is tube in result? -->if not add tube
1390  result.push_back(((PndSttHit *)hit)->GetTubeID());
1391  });
1392  });
1393  return result;
1394  }
1395 
1403  std::vector<std::vector<int>> GetKOutOfN(int k, int n)
1404  {
1405  std::vector<std::vector<int>> result;
1406  std::string bitmask(k, 1); // K leading 1's
1407  bitmask.resize(n, 0); // N-K trailing 0's
1408 
1409  // print integers and permute bitmask
1410  do {
1411  std::vector<int> tmp;
1412  for (int i = 0; i < n; ++i) // [0..N-1] integers
1413  {
1414  if (bitmask[i])
1415  tmp.push_back(i);
1416  }
1417  result.push_back(tmp);
1418  } while (std::prev_permutation(bitmask.begin(), bitmask.end()));
1419 
1420  LOG(debug) << "Combinations: " << result.size();
1421 
1422  return result;
1423  }
1424 
1425  std::vector<TripletSolution> CombineIdenticalSolutions(std::vector<TripletSolution> &solutions)
1426  {
1427  std::vector<TripletSolution> result;
1428  std::sort(solutions.begin(), solutions.end(), [](TripletSolution &first, TripletSolution &second) { return (first.GetNHits() > second.GetNHits()); });
1429 
1430  if (solutions.size() == 0)
1431  return result;
1432  for (auto solution : solutions) {
1433  if (std::none_of(result.begin(), result.end(), [&](TripletSolution &res) { return ContainsTriplet(solution.fTriplet, res); })) {
1434  result.push_back(solution);
1435  }
1436  }
1437  return result;
1438  }
1439 
1440  bool ContainsTriplet(Triplet &triplet, TripletSolution &solution)
1441  {
1442  bool result = true;
1443  for (auto hit : triplet.fTripletHits) {
1444  auto found = std::find(solution.fHits[TripletSolution::detID::STT].begin(), solution.fHits[TripletSolution::detID::STT].end(), hit);
1445  if (found == solution.fHits[TripletSolution::detID::STT].end()) {
1446  return false;
1447  }
1448  }
1449  return result;
1450  }
1451 
1461  std::vector<PndSttHit *> TubeReduction(std::vector<std::pair<int, int>> &Rows, std::map<int, std::vector<std::vector<PndSttHit *>>> &tubeStructure,
1462  std::map<FairLink, int> &fMapHitstoCATracklet, int position)
1463  {
1464  std::vector<PndSttHit *> result;
1465  std::map<int, std::vector<PndSttHit *>> FoundCAs;
1466  result.clear();
1467  FoundCAs.clear();
1468  for (auto row : Rows) {
1469  for (auto hitGroup : tubeStructure[row.first]) {
1470  if (hitGroup.size() > 5)
1471  continue;
1472  for (auto sttHit : hitGroup) {
1473  auto it = fMapHitstoCATracklet.find(sttHit->GetEntryNr());
1474  if (it == fMapHitstoCATracklet.end()) {
1475  // the hit doesnt belong to a CA tracklet
1476  result.push_back(sttHit);
1477  } else {
1478  if (FoundCAs.find(fMapHitstoCATracklet[sttHit->GetEntryNr()]) == FoundCAs.end()) {
1479  // std::cout << "the hit belongs to a CA tracklet" << std::endl;
1480  // CA track was still not found
1481  std::vector<PndSttHit *> temp;
1482  temp.push_back(sttHit);
1483  FoundCAs[fMapHitstoCATracklet[sttHit->GetEntryNr()]] = {temp};
1484  } else {
1485  FoundCAs[fMapHitstoCATracklet[sttHit->GetEntryNr()]].push_back(sttHit);
1486  }
1487  }
1488  }
1489  }
1490  }
1491  std::map<int, std::vector<PndSttHit *>>::iterator FoundCAsIter;
1492 
1493  for (FoundCAsIter = FoundCAs.begin(); FoundCAsIter != FoundCAs.end(); FoundCAsIter++) {
1494  PndSttHit *CASttHit;
1495  FairLink CALink;
1496  std::sort(FoundCAsIter->second.begin(), FoundCAsIter->second.end());
1497  if (position == 0) {
1498  CASttHit = FoundCAsIter->second[0];
1499  // fMapInnerTubeToCA[CASttHit] = fMapHitstoCATracklet[CALink];
1500  } else if (position == 1) {
1501  CASttHit = FoundCAsIter->second[FoundCAsIter->second.size() / 2];
1502  // fMapCAToOuterTube[fMapHitstoCATracklet[CALink]] = CASttHit;
1503  } else if (position == 2) {
1504  CASttHit = FoundCAsIter->second[FoundCAsIter->second.size() - 1];
1505  // fMapCAToOuterTube[fMapHitstoCATracklet[CALink]] = CASttHit;
1506  }
1507  result.push_back(CASttHit);
1508  }
1509  return result;
1510  }
1511 
1512  std::map<FairLink, int> GetHitsToCAMap(PndSttCA *fCATrackFinder)
1513  {
1514  std::map<FairLink, int> fMapHitstoCATracklet;
1515  fMapHitstoCATracklet.clear();
1516  fCATrackFinder->FindTracks();
1517 
1518  for (int i = 0; i < fCATrackFinder->NumFirstTrackCands(); i++) {
1519  PndTrackCand trackCand_temp = fCATrackFinder->GetFirstTrackCand(i);
1520  if (trackCand_temp.GetNHits() < 2)
1521  continue;
1522 
1523  for (int j = 0; j < trackCand_temp.GetNHits(); j++) {
1524  fMapHitstoCATracklet[trackCand_temp.GetSortedHit(j)] = i;
1525  }
1526  }
1527  return fMapHitstoCATracklet;
1528  }
1529 };
1530 
1531 } // namespace PndApollonius
1532 
std::map< int, PndSttHit * > fMapCAToMidTube
Int_t GetTubeID() const
Definition: PndSttHit.h:71
std::array< PndSttHit *, 3 > fTripletHits
friend std::ostream & operator<<(std::ostream &output, const TripletSolution &t)
double SquaredDistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit)
std::pair< Int_t, Int_t > GetTubeIDs() const
__m128 m
Definition: P4_F32vec4.h:26
FairHit * GetFirstHit(PndSttGeometryMap *fGeometryMap)
friend F32vec4 sqrt(const F32vec4 &a)
Definition: P4_F32vec4.h:28
void FindTracks()
void AddHits(detID detector, std::vector< FairHit *> data)
PndTrackCand GetFirstTrackCand(int i)
Definition: PndSttCA.h:56
friend std::ostream & operator<<(std::ostream &output, const Triplet &t)
PndTrackCandHit GetSortedHit(UInt_t i)
Definition: PndTrackCand.h:51
std::vector< Triplet > ReduceCombinatorics(TripletValues &triplets, std::map< FairLink, int > &fMapHitstoCATracklet, TClonesArray *sttHits, PndSttCA *fCATrackFinder, PndSttGeometryMap *fGeometryMap, double &fMinDistance, bool &fWithCombiReduction)
Find triplet combinations with higher probability to be a proper one.
std::map< int, std::vector< std::vector< PndSttHit * > > > GetTubeStructure(std::vector< PndSttHit *> hits, PndSttGeometryMap *fGeometryMap, int &fAllHitsCounter, bool &fIsStrongCurling)
Creates a map that connects each STT row with a set of groups. All STT hits in one group are directly...
int NumFirstTrackCands()
Definition: PndSttCA.h:62
bool IsSkewedStraw(int strawindex) const
double MeanSquareDistance(TripletSolution &solution)
int GetRow(int strawindex) const
static void ApolloniusCudaCalcCPU(int num, double hit0[], double hit1[], double hit2[], double apolloniusCircles[])
Calculation of Apollonius circles on CPU. (This is the same as implemented in cuda).
std::vector< TripletSolution > FindBestSolutions(std::vector< TripletSolution > &solutions)
Select best solution(s) out of the 8 generated by triplet.
TripletValues & operator+=(const TripletValues &right)
UInt_t GetNHits() const
Definition: PndTrackCand.h:57
TripletSolution FindHitsCloseToCircle(std::vector< PndSttHit *> &sttHits, TVector3 &circle, double &fDistanceThresholdSTTFar, PndSttGeometryMap *fGeometryMap)
Finds all hits that are close to a specific circle.
void AddHit(detID detector, FairHit *data)
void SortHits(TVector2 &firstHit, detID detector)
double DistanceCircleSttHit(TVector3 &circle, PndSttHit *sttHit, double &sqaredDistance)
unsigned int i
Definition: P4_F32vec4.h:21
double DistanceCircleSttHit(TVector3 &circle, PndSttHit *sttHit)
std::map< int, PndSttHit * > fMapCAToOuterTube
friend std::ostream & operator<<(std::ostream &output, const TripletValues &t)
virtual bool CheckFirstHit(FairLink *hit)
std::vector< TripletSolution > CombineIdenticalSolutions(std::vector< TripletSolution > &solutions)
std::map< FairLink, int > GetHitsToCAMap(PndSttCA *fCATrackFinder)
int GetSector(int strawindex) const
void CheckContinuitySolutions(std::vector< TripletSolution > &solutions, PndSttGeometryMap *fGeometryMap)
Checks if a track candidate is continuous in the STT.
double DistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit)
#define GEM
static T Abs(const T &x)
Definition: PndCAMath.h:56
std::map< PndSttHit *, int > fMapInnerTubeToCA
std::vector< std::vector< int > > GetKOutOfN(int k, int n)
Determines all possible combinations of tracks.
std::vector< TripletSolution > CheckSolutions(std::vector< TripletSolution > &solutions, std::vector< std::vector< int >> combinations)
Check Combined Track Solutions if they are a possible solution.
const vector< int > & GetStrawRow(int sector, int row) const
double DistanceLinePoint(TVector3 &circle, FairHit *hit)
bool ContainsTriplet(Triplet &triplet, TripletSolution &solution)
TVector2 HitOnTrack(FairHit *hit)
bool IsTripletUsed(std::vector< TripletSolution > &solutions, Triplet &triplet)
Checks is the triplet is already found in a good solution.
static T ATan2(const T &y, const T &x)
std::vector< double > calcIntersectionPointCircleLine(std::vector< double > circle, double m, double b, double Ax)
TVector3 GetPosition()
std::vector< PndSttHit * > fFirstRow
PndSttTube * GetTube(int strawindex) const
bool IsSkewedStraw(int strawindex) const
std::vector< TripletSolution > GenerateTripletTracks(Triplet triplet, std::vector< PndSttHit *> &sttHits, PndSttGeometryMap *fGeometryMap)
Generate tracks for one triplet.
static float Pi()
Definition: PndCAMath.h:115
std::vector< int > GetUniqueTubeIDs(std::vector< TripletSolution > &solutions, std::vector< int > combinations)
returns a vector of all tubes of all tracks in one combination
std::map< int, std::vector< PndSttHit * > > GetAllTubesByRow(std::vector< PndSttHit *> hits, PndSttGeometryMap *fGeometryMap, int &fAllHitsCounter)
Sorts all STT hits by row and returns a map that connects each row with the hits in that row...
void AddOtherDetectors(vector< TripletSolution > &solutions, PndSttStrawMap *fStrawMap, std::map< TString, TClonesArray *> &fBranchMap)
Add MVD and GEM hits to solutions.
ReductionMaps CreateMaps(TripletValues &triplets, std::map< FairLink, int > &fMapHitstoCATracklet)
Created maps that connect the hits with a corresponding CA tracklet.
virtual bool CheckTwoHits(FairLink *first, FairLink *second)
void SortAllHits(PndSttGeometryMap *fGeometryMap)
Double_t GetIsochrone() const
Definition: PndSttHit.h:58
std::map< detID, std::vector< FairHit * > > fHits
std::vector< PndSttHit * > fMidRow
double DistanceCirclePoint(TVector3 &circle, FairHit *hit)
void AddHits(std::vector< PndSttHit *> sttHits)
std::vector< PndSttHit * > fLastRow
std::vector< PndSttHit * > TubeReduction(std::vector< std::pair< int, int >> &Rows, std::map< int, std::vector< std::vector< PndSttHit *>>> &tubeStructure, std::map< FairLink, int > &fMapHitstoCATracklet, int position)
Reduces the number of tubes chosen for combination–> if several tubes in one region (inner...
std::map< PndSttHit *, int > fMapMidTubeToCA
std::vector< TripletSolution > CheckCombinedSolutions(std::vector< TripletSolution > &solutions, int nExpectedTracks)
Combines and Checks all Solutions to generate only the true particle tracks.
double DistanceLineSttHit(TVector3 &circle, PndSttHit *sttHit, double &squaredDistance)
std::vector< FairHit * > fAllHits
std::vector< std::string > detID_Names
void SortStt(PndSttGeometryMap *fGeometryMap)
bool IsContinuous(TripletSolution &solution, PndSttGeometryMap *fGeometryMap)
Checks if te found STT hits are continuous.