Belle II Software  release-05-01-25
StandaloneCosmicsCollector.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2018 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Felix Metzner *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 #pragma once
11 
12 #include <vector>
13 #include <utility>
14 #include <Eigen/Dense>
15 #include <Eigen/Geometry>
16 
17 #include <framework/datastore/StoreArray.h>
18 
19 #include <tracking/spacePointCreation/SpacePoint.h>
20 
21 namespace Belle2 {
35  class StandaloneCosmicsCollector {
36 
37  public:
39  StandaloneCosmicsCollector() = default;
40 
42  ~StandaloneCosmicsCollector() = default;
43 
44 
53  void setSortingMode(unsigned short index)
54  {
55  if ((index < 1) or (index > 3)) {
56  B2FATAL("Invalid sorting mode chosen! You used " << m_sortingMode
57  << ". Must be one of 1 (by radius), 2 (by x) or 3 (by y).");
58  }
59  m_sortingMode = index;
60  }
61 
68  void addSpacePoints(std::vector<StoreArray<SpacePoint>> SPs)
69  {
70  m_spacePoints.clear();
71  m_direction.clear();
72  m_start.clear();
73  m_reducedChi2 = 10;
74  for (auto& spArray : SPs) {
75  for (auto& sp : spArray) {
77  }
78  }
79  }
80 
81 
94  bool doFit(double qualityCut, int maxRejected, int minSPs)
95  {
96  bool fitting = true;
97  int rejected = 0;
98 
99  // cppcheck-suppress knownConditionTrueFalse
100  while (m_reducedChi2 > qualityCut && fitting) {
101  fitting = doLineFit(minSPs);
102  if (not fitting) {return false;}
103  if (m_reducedChi2 > qualityCut) {
104  B2DEBUG(20, "Refitting without sp with index " << m_shittiest.second
105  << " and chi2 contribution " << m_shittiest.first << "...");
106  m_spacePoints.erase(m_spacePoints.begin() + m_shittiest.second);
107  rejected++;
108  }
109  if (rejected > maxRejected) { B2DEBUG(20, "Rejected " << rejected << "!"); return false; }
110  }
111  return fitting;
112  }
113 
114 
124  std::pair<std::vector<double>, std::vector<double>> getResult()
125  {
126  return std::pair<std::vector<double>, std::vector<double>> (m_start, m_direction);
127  }
128 
129 
136  std::vector<const SpacePoint*> getSPTC()
137  {
138  return m_spacePoints;
139  }
140 
141 
147  double getReducedChi2()
148  {
149  return m_reducedChi2;
150  }
151 
152 
153  private:
154 
160  void addSpacePoint(const SpacePoint* SP)
161  {
162  auto forwardIt = std::lower_bound(m_spacePoints.begin(), m_spacePoints.end(), SP,
163  [this](const SpacePoint * lhs, const SpacePoint * rhs)
164  -> bool { return this->compareRads(lhs, rhs); });
165  m_spacePoints.insert(forwardIt, SP);
166  }
167 
168 
181  bool doLineFit(int minSPs)
182  {
183  int nHits = m_spacePoints.size();
184  B2DEBUG(20, "Trying fit with " << nHits << " hits...");
185  // Aborting fit and returning false if the minimal number of SpacePoints required is not met.
186  if (nHits < minSPs) { B2DEBUG(20, "Only " << nHits << " hits!"); return false; };
187 
188  Eigen::Matrix<double, 3, 1> average = Eigen::Matrix<double, 3, 1>::Zero(3, 1);
189  Eigen::Matrix<double, Eigen::Dynamic, 3> data = Eigen::Matrix<double, Eigen::Dynamic, 3>::Zero(nHits, 3);
190  Eigen::Matrix<double, Eigen::Dynamic, 3> P = Eigen::Matrix<double, Eigen::Dynamic, 3>::Zero(nHits, 3);
191 
192  for (const auto& sp : m_spacePoints) {
193  average(0) += sp->getPosition().X();
194  average(1) += sp->getPosition().Y();
195  average(2) += sp->getPosition().Z();
196  }
197  average *= 1. / nHits;
198 
199  int index = 0;
200  for (const auto& sp : m_spacePoints) {
201  data(index, 0) = sp->getPosition().X();
202  data(index, 1) = sp->getPosition().Y();
203  data(index, 2) = sp->getPosition().Z();
204 
205  P(index, 0) = sp->getPosition().X() - average(0);
206  P(index, 1) = sp->getPosition().Y() - average(1);
207  P(index, 2) = sp->getPosition().Z() - average(2);
208  index++;
209  }
210 
211  //Principal component analysis
212  Eigen::Matrix<double, 3, 3> product = P.transpose() * P;
213 
214  Eigen::EigenSolver<Eigen::Matrix<double, 3, 3>> eigencollection(product);
215  Eigen::Matrix<double, 3, 1> eigenvalues = eigencollection.eigenvalues().real();
216  Eigen::Matrix<std::complex<double>, 3, 3> eigenvectors = eigencollection.eigenvectors();
217  Eigen::Matrix<double, 3, 1>::Index maxRow, maxCol;
218  eigenvalues.maxCoeff(&maxRow, &maxCol);
219 
220  Eigen::Matrix<double, 3, 1> e = eigenvectors.col(maxRow).real();
221 
222  // Setting starting point to the data point with larges radius
223  Eigen::Matrix<double, 3, 1> start = data.row(nHits - 1).transpose();
224  Eigen::Matrix<double, 3, 1> second = data.row(nHits - 2).transpose();
225  m_start = {start(0), start(1), start(2)};
226  // Setting direction vector towards the inside of the detector
227  m_direction = {e(0), e(1), e(2)};
228  Eigen::Hyperplane<double, 3> plane(e.normalized(), start);
229  Eigen::ParametrizedLine<double, 3> line(second, e.normalized());
230  double factor = line.intersectionParameter(plane);
231  if (factor > 0) {
232  m_direction = { -e(0), -e(1), -e(2)};
233  }
234 
235  // Resorting SpacePoints based on the obtained line fit result.
236  resortHits();
237 
238  // Calculating reduced chi2 value of the line fit using the distances of the SpacePoints to the obtained line and
239  // keeping the m_spacePoints index and the chi2 contribution of the SpacePoint with the largest contribution.
240  m_reducedChi2 = 0;
241  m_shittiest = std::pair<double, int>(0., 0);
242  int shit_index = 0;
243  for (const auto& sp : m_spacePoints) {
244  Eigen::Matrix<double, 3, 1> origin(sp->getPosition().X(), sp->getPosition().Y(), sp->getPosition().Z());
245  plane = Eigen::Hyperplane<double, 3>(e.normalized(), origin);
246 
247  Eigen::Matrix<double, 3, 1> point = line.intersectionPoint(plane);
248 
249  double delta_chi2 = (point - origin).transpose() * (point - origin);
250  m_reducedChi2 += delta_chi2;
251 
252  if (delta_chi2 > m_shittiest.first) {
253  m_shittiest.first = delta_chi2;
254  m_shittiest.second = shit_index;
255  }
256  shit_index++;
257  }
258 
259  m_reducedChi2 *= 1. / nHits;
260  B2DEBUG(20, "Reduced chi2 result is " << m_reducedChi2 << "...");
261  return true;
262  }
263 
264 
272  bool compareRads(const SpacePoint* a, const SpacePoint* b)
273  {
274  if (m_sortingMode == 1) {
275  double radA = a->getPosition().X() * a->getPosition().X() + a->getPosition().Y() * a->getPosition().Y();
276  double radB = b->getPosition().X() * b->getPosition().X() + b->getPosition().Y() * b->getPosition().Y();
277  return radA < radB;
278  } else if (m_sortingMode == 2) {
279  double xA = a->getPosition().X();
280  double xB = b->getPosition().X();
281  return xA < xB;
282  } else if (m_sortingMode == 3) {
283  double yA = a->getPosition().Y();
284  double yB = b->getPosition().Y();
285  return yA < yB;
286  } else {
287  B2FATAL("Invalid sorting mode chosen! You used " << m_sortingMode
288  << ". Must be one of 1 (by radius), 2 (by x) or 3 (by y).");
289  }
290  }
291 
292 
299  void resortHits()
300  {
301  std::vector<const SpacePoint*> sortedSPs;
302  for (auto& SP : m_spacePoints) {
303  auto forwardIt = std::lower_bound(sortedSPs.begin(), sortedSPs.end(), SP,
304  [this](const SpacePoint * lhs, const SpacePoint * rhs) -> bool {
305  return this->comparePars(lhs, rhs);
306  });
307  sortedSPs.insert(forwardIt, SP);
308  }
309  m_spacePoints = sortedSPs;
310  }
311 
312 
320  bool comparePars(const SpacePoint* a, const SpacePoint* b)
321  {
322  Eigen::Matrix<double, 3, 1> posA(a->getPosition().X(), a->getPosition().Y(), a->getPosition().Z());
323  Eigen::Matrix<double, 3, 1> posB(b->getPosition().X(), b->getPosition().Y(), b->getPosition().Z());
324 
325  Eigen::Matrix<double, 3, 1> direction(m_direction[0], m_direction[1], m_direction[2]);
326  Eigen::Matrix<double, 3, 1> origin(m_start[0], m_start[1], m_start[2]);
327 
328  Eigen::ParametrizedLine<double, 3> line(origin, direction.normalized());
329  Eigen::Hyperplane<double, 3> planeA(direction.normalized(), posA);
330  Eigen::Hyperplane<double, 3> planeB(direction.normalized(), posB);
331 
332  double parA = line.intersectionParameter(planeA);
333  double parB = line.intersectionParameter(planeB);
334  return parA < parB;
335  }
336 
337 
339  std::vector<const SpacePoint*> m_spacePoints;
340 
346  unsigned short m_sortingMode = 1;
347 
352  double m_reducedChi2 = 10;
353 
360  std::pair<double, int> m_shittiest = std::pair<double, int>(0., 0);
361 
363  std::vector<double> m_start {0., 0., 0.};
364 
366  std::vector<double> m_direction {0., 0., 0.};
367  };
369 }
370 
Belle2::StandaloneCosmicsCollector::m_shittiest
std::pair< double, int > m_shittiest
Pair containing the index of the vector m_spacePoints for the SpacePoint with the largest contributio...
Definition: StandaloneCosmicsCollector.h:368
Belle2::StandaloneCosmicsCollector::addSpacePoint
void addSpacePoint(const SpacePoint *SP)
Adding single SpacePoint to the sorted member vector m_spacePoints, beginning with the SpacePoint wit...
Definition: StandaloneCosmicsCollector.h:168
prepareAsicCrosstalkSimDB.e
e
aux.
Definition: prepareAsicCrosstalkSimDB.py:53
Belle2::StandaloneCosmicsCollector::getSPTC
std::vector< const SpacePoint * > getSPTC()
Getter for the sorted list of SpacePoints used for the final fit which met the given requirements.
Definition: StandaloneCosmicsCollector.h:144
Belle2::StandaloneCosmicsCollector::comparePars
bool comparePars(const SpacePoint *a, const SpacePoint *b)
Comparison function to compare two SpacePoints based on the distance between the start point of the f...
Definition: StandaloneCosmicsCollector.h:328
Belle2::StandaloneCosmicsCollector::getReducedChi2
double getReducedChi2()
Getter for the final reduced chi squared value obtained for the set of SpacePoints used for the last ...
Definition: StandaloneCosmicsCollector.h:155
Belle2::StandaloneCosmicsCollector::m_start
std::vector< double > m_start
Start point obtained by the last performed line fit.
Definition: StandaloneCosmicsCollector.h:371
Belle2::StandaloneCosmicsCollector::StandaloneCosmicsCollector
StandaloneCosmicsCollector()=default
Constructor.
Belle2::StandaloneCosmicsCollector::addSpacePoints
void addSpacePoints(std::vector< StoreArray< SpacePoint >> SPs)
Function to initialize the track finder anew for an event with its set of SpacePoints provided via th...
Definition: StandaloneCosmicsCollector.h:76
Belle2::StandaloneCosmicsCollector::m_reducedChi2
double m_reducedChi2
Member variable containing the reduced chi squared value of the current line fit.
Definition: StandaloneCosmicsCollector.h:360
Belle2::StandaloneCosmicsCollector::resortHits
void resortHits()
Function to resort the member vector of SpacePoints m_spacePoints based on the members m_start and m_...
Definition: StandaloneCosmicsCollector.h:307
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StandaloneCosmicsCollector::doFit
bool doFit(double qualityCut, int maxRejected, int minSPs)
Function to perform the actual line fit based on the StoreArray of SpacePoints provided.
Definition: StandaloneCosmicsCollector.h:102
Belle2::StandaloneCosmicsCollector::setSortingMode
void setSortingMode(unsigned short index)
Set sorting mode used in addSpacePoints.
Definition: StandaloneCosmicsCollector.h:61
Belle2::StandaloneCosmicsCollector::~StandaloneCosmicsCollector
~StandaloneCosmicsCollector()=default
Destructor.
Belle2::StandaloneCosmicsCollector::doLineFit
bool doLineFit(int minSPs)
Function performing the actual line fit via a principal component analysis methode yielding a directi...
Definition: StandaloneCosmicsCollector.h:189
Belle2::StandaloneCosmicsCollector::m_sortingMode
unsigned short m_sortingMode
Storing identifier for sorting algorithm to be used for the function addSpacePoint.
Definition: StandaloneCosmicsCollector.h:354
Belle2::StandaloneCosmicsCollector::m_direction
std::vector< double > m_direction
Direction of the line obtained by the last performed line fit.
Definition: StandaloneCosmicsCollector.h:374
Belle2::StandaloneCosmicsCollector::compareRads
bool compareRads(const SpacePoint *a, const SpacePoint *b)
Compare function used by addSpacePoint to sort the member vector of SpacePoints m_spacePoints by the ...
Definition: StandaloneCosmicsCollector.h:280
Belle2::StandaloneCosmicsCollector::m_spacePoints
std::vector< const SpacePoint * > m_spacePoints
Member vector of SpacePoints holding the SpacePoints considered for the track candidate.
Definition: StandaloneCosmicsCollector.h:347
Belle2::StandaloneCosmicsCollector::getResult
std::pair< std::vector< double >, std::vector< double > > getResult()
Getter for the position and momentum seed resulting from the linear fit.
Definition: StandaloneCosmicsCollector.h:132
Belle2::StoreArray< SpacePoint >