Belle II Software development
StandaloneCosmicsCollector.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#pragma once
9
10#include <vector>
11#include <utility>
12#include <Eigen/Dense>
13#include <Eigen/Geometry>
14
15#include <framework/datastore/StoreArray.h>
16
17#include <tracking/spacePointCreation/SpacePoint.h>
18
19namespace Belle2 {
34
35 public:
38
41
42
51 void setSortingMode(unsigned short index)
52 {
53 if ((index < 1) or (index > 3)) {
54 B2FATAL("Invalid sorting mode chosen! You used " << m_sortingMode
55 << ". Must be one of 1 (by radius), 2 (by x) or 3 (by y).");
56 }
57 m_sortingMode = index;
58 }
59
67 {
68 m_spacePoints.clear();
69 m_direction.clear();
70 m_start.clear();
71 m_reducedChi2 = 10;
72 for (const auto& spArray : SPs) {
73 for (const auto& sp : spArray) {
74 addSpacePoint(&sp);
75 }
76 }
77 }
78
79
92 bool doFit(double qualityCut, int maxRejected, int minSPs)
93 {
94 bool fitting = true;
95 int rejected = 0;
96
97 while (m_reducedChi2 > qualityCut && fitting) {
98 fitting = doLineFit(minSPs);
99 if (not fitting) {return false;}
100 if (m_reducedChi2 > qualityCut) {
101 B2DEBUG(20, "Refitting without sp with index " << m_largestChi2.second
102 << " and chi2 contribution " << m_largestChi2.first << "...");
103 m_spacePoints.erase(m_spacePoints.begin() + m_largestChi2.second);
104 rejected++;
105 }
106 if (rejected > maxRejected) { B2DEBUG(20, "Rejected " << rejected << "!"); return false; }
107 }
108 return fitting;
109 }
110
111
121 std::pair<std::vector<double>, std::vector<double>> getResult()
122 {
123 return std::pair<std::vector<double>, std::vector<double>> (m_start, m_direction);
124 }
125
126
133 std::vector<const SpacePoint*> getSPTC()
134 {
135 return m_spacePoints;
136 }
137
138
145 {
146 return m_reducedChi2;
147 }
148
149
150 private:
151
157 void addSpacePoint(const SpacePoint* SP)
158 {
159 auto forwardIt = std::lower_bound(m_spacePoints.begin(), m_spacePoints.end(), SP,
160 [this](const SpacePoint * lhs, const SpacePoint * rhs)
161 -> bool { return this->compareRads(lhs, rhs); });
162 m_spacePoints.insert(forwardIt, SP);
163 }
164
165
178 bool doLineFit(int minSPs)
179 {
180 int nHits = m_spacePoints.size();
181 B2DEBUG(20, "Trying fit with " << nHits << " hits...");
182 // Aborting fit and returning false if the minimal number of SpacePoints required is not met.
183 if (nHits < minSPs) { B2DEBUG(20, "Only " << nHits << " hits!"); return false; };
184
185 Eigen::Matrix<double, 3, 1> average = Eigen::Matrix<double, 3, 1>::Zero(3, 1);
186 Eigen::Matrix<double, Eigen::Dynamic, 3> data = Eigen::Matrix<double, Eigen::Dynamic, 3>::Zero(nHits, 3);
187 Eigen::Matrix<double, Eigen::Dynamic, 3> P = Eigen::Matrix<double, Eigen::Dynamic, 3>::Zero(nHits, 3);
188
189 for (const auto& sp : m_spacePoints) {
190 average(0) += sp->getPosition().X();
191 average(1) += sp->getPosition().Y();
192 average(2) += sp->getPosition().Z();
193 }
194 average *= 1. / nHits;
195
196 int index = 0;
197 for (const auto& sp : m_spacePoints) {
198 data(index, 0) = sp->getPosition().X();
199 data(index, 1) = sp->getPosition().Y();
200 data(index, 2) = sp->getPosition().Z();
201
202 P(index, 0) = sp->getPosition().X() - average(0);
203 P(index, 1) = sp->getPosition().Y() - average(1);
204 P(index, 2) = sp->getPosition().Z() - average(2);
205 index++;
206 }
207
208 //Principal component analysis
209 Eigen::Matrix<double, 3, 3> product = P.transpose() * P;
210
211 Eigen::EigenSolver<Eigen::Matrix<double, 3, 3>> eigencollection(product);
212 Eigen::Matrix<double, 3, 1> eigenvalues = eigencollection.eigenvalues().real();
213 Eigen::Matrix<std::complex<double>, 3, 3> eigenvectors = eigencollection.eigenvectors();
214 Eigen::Matrix<double, 3, 1>::Index maxRow, maxCol;
215 eigenvalues.maxCoeff(&maxRow, &maxCol);
216
217 Eigen::Matrix<double, 3, 1> e = eigenvectors.col(maxRow).real();
218
219 // Setting starting point to the data point with larges radius
220 Eigen::Matrix<double, 3, 1> start = data.row(nHits - 1).transpose();
221 Eigen::Matrix<double, 3, 1> second = data.row(nHits - 2).transpose();
222 m_start = {start(0), start(1), start(2)};
223 // Setting direction vector towards the inside of the detector
224 m_direction = {e(0), e(1), e(2)};
225 Eigen::Hyperplane<double, 3> plane(e.normalized(), start);
226 Eigen::ParametrizedLine<double, 3> line(second, e.normalized());
227 double factor = line.intersectionParameter(plane);
228 if (factor > 0) {
229 m_direction = { -e(0), -e(1), -e(2)};
230 }
231
232 // Resorting SpacePoints based on the obtained line fit result.
233 resortHits();
234
235 // Calculating reduced chi2 value of the line fit using the distances of the SpacePoints to the obtained line and
236 // keeping the m_spacePoints index and the chi2 contribution of the SpacePoint with the largest contribution.
237 m_reducedChi2 = 0;
238 m_largestChi2 = std::pair<double, int>(0., 0);
239 int largestChi2_index = 0;
240 for (const auto& sp : m_spacePoints) {
241 Eigen::Matrix<double, 3, 1> origin(sp->getPosition().X(), sp->getPosition().Y(), sp->getPosition().Z());
242 plane = Eigen::Hyperplane<double, 3>(e.normalized(), origin);
243
244 Eigen::Matrix<double, 3, 1> point = line.intersectionPoint(plane);
245
246 double delta_chi2 = (point - origin).transpose() * (point - origin);
247 m_reducedChi2 += delta_chi2;
248
249 if (delta_chi2 > m_largestChi2.first) {
250 m_largestChi2.first = delta_chi2;
251 m_largestChi2.second = largestChi2_index;
252 }
253 largestChi2_index++;
254 }
255
256 m_reducedChi2 *= 1. / nHits;
257 B2DEBUG(20, "Reduced chi2 result is " << m_reducedChi2 << "...");
258 return true;
259 }
260
261
269 bool compareRads(const SpacePoint* a, const SpacePoint* b)
270 {
271 if (m_sortingMode == 1) {
272 double radA = a->getPosition().X() * a->getPosition().X() + a->getPosition().Y() * a->getPosition().Y();
273 double radB = b->getPosition().X() * b->getPosition().X() + b->getPosition().Y() * b->getPosition().Y();
274 return radA < radB;
275 } else if (m_sortingMode == 2) {
276 double xA = a->getPosition().X();
277 double xB = b->getPosition().X();
278 return xA < xB;
279 } else if (m_sortingMode == 3) {
280 double yA = a->getPosition().Y();
281 double yB = b->getPosition().Y();
282 return yA < yB;
283 } else {
284 B2FATAL("Invalid sorting mode chosen! You used " << m_sortingMode
285 << ". Must be one of 1 (by radius), 2 (by x) or 3 (by y).");
286 }
287 }
288
289
297 {
298 std::vector<const SpacePoint*> sortedSPs;
299 for (auto& SP : m_spacePoints) {
300 auto forwardIt = std::lower_bound(sortedSPs.begin(), sortedSPs.end(), SP,
301 [this](const SpacePoint * lhs, const SpacePoint * rhs) -> bool {
302 return this->comparePars(lhs, rhs);
303 });
304 sortedSPs.insert(forwardIt, SP);
305 }
306 m_spacePoints = sortedSPs;
307 }
308
309
317 bool comparePars(const SpacePoint* a, const SpacePoint* b)
318 {
319 Eigen::Matrix<double, 3, 1> posA(a->getPosition().X(), a->getPosition().Y(), a->getPosition().Z());
320 Eigen::Matrix<double, 3, 1> posB(b->getPosition().X(), b->getPosition().Y(), b->getPosition().Z());
321
322 Eigen::Matrix<double, 3, 1> direction(m_direction[0], m_direction[1], m_direction[2]);
323 Eigen::Matrix<double, 3, 1> origin(m_start[0], m_start[1], m_start[2]);
324
325 Eigen::ParametrizedLine<double, 3> line(origin, direction.normalized());
326 Eigen::Hyperplane<double, 3> planeA(direction.normalized(), posA);
327 Eigen::Hyperplane<double, 3> planeB(direction.normalized(), posB);
328
329 double parA = line.intersectionParameter(planeA);
330 double parB = line.intersectionParameter(planeB);
331 return parA < parB;
332 }
333
335 std::vector<double> m_start {0., 0., 0.};
336
338 std::vector<double> m_direction {0., 0., 0.};
339
341 std::vector<const SpacePoint*> m_spacePoints;
342
349 std::pair<double, int> m_largestChi2 = std::pair<double, int>(0., 0);
350
355 double m_reducedChi2 = 10;
356
362 unsigned short m_sortingMode = 1;
363
364 };
365
366}
367
SpacePoint typically is build from 1 PXDCluster or 1-2 SVDClusters.
Definition SpacePoint.h:42
void resortHits()
Function to resort the member vector of SpacePoints m_spacePoints based on the members m_start and m_...
unsigned short m_sortingMode
Storing identifier for sorting algorithm to be used for the function addSpacePoint.
~StandaloneCosmicsCollector()=default
Destructor.
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...
StandaloneCosmicsCollector()=default
Constructor.
std::vector< double > m_direction
Direction of the line obtained by the last performed line fit.
std::pair< double, int > m_largestChi2
Pair containing the index of the vector m_spacePoints for the SpacePoint with the largest contributio...
std::vector< double > m_start
Start point obtained by the last performed line fit.
void addSpacePoint(const SpacePoint *SP)
Adding single SpacePoint to the sorted member vector m_spacePoints, beginning with the SpacePoint wit...
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...
bool doFit(double qualityCut, int maxRejected, int minSPs)
Function to perform the actual line fit based on the StoreArray of SpacePoints provided.
std::vector< const SpacePoint * > m_spacePoints
Member vector of SpacePoints holding the SpacePoints considered for the track candidate.
double m_reducedChi2
Member variable containing the reduced chi squared value of the current line fit.
std::vector< const SpacePoint * > getSPTC()
Getter for the sorted list of SpacePoints used for the final fit which met the given requirements.
bool compareRads(const SpacePoint *a, const SpacePoint *b)
Compare function used by addSpacePoint to sort the member vector of SpacePoints m_spacePoints by the ...
std::pair< std::vector< double >, std::vector< double > > getResult()
Getter for the position and momentum seed resulting from the linear fit.
bool doLineFit(int minSPs)
Function performing the actual line fit via a principal component analysis method yielding a directio...
void setSortingMode(unsigned short index)
Set sorting mode used in addSpacePoints.
double getReducedChi2()
Getter for the final reduced chi squared value obtained for the set of SpacePoints used for the last ...
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
Abstract base class for different kinds of events.