10 #include <system_error>
12 #include <Eigen/Eigenvalues>
14 template <
typename spacepo
int_t>
17 std::unique_ptr<const Logger> lgr)
22 <<
", which is less than 3. There will be duplicate triplets.");
27 <<
", allowed values are between 0 and 1");
36 <<
", allowed values are \"planes\" or \"rays\" ");
44 template <
typename spacepo
int_t>
47 const std::vector<spacepoint_t>& spacepoints)
const {
50 sortedSpacepoints = sortSpacepoints(spacepoints);
53 std::vector<Acts::SingleSeedVertexFinder<spacepoint_t>::Triplet> triplets =
57 if (triplets.empty()) {
62 if (
m_cfg.minimalizeWRT ==
"planes") {
64 vtx = findClosestPointFromPlanes(triplets);
65 }
else if (
m_cfg.minimalizeWRT ==
"rays") {
67 vtx = findClosestPointFromRays(triplets);
70 <<
m_cfg.minimalizeWRT
71 <<
", allowed values are \"planes\" or \"rays\" ");
77 template <
typename spacepo
int_t>
80 const std::vector<spacepoint_t>& spacepoints)
const {
82 sortedSpacepoints(
m_cfg.numPhiSlices,
m_cfg.numZSlices);
84 for (
const auto& sp : spacepoints) {
87 std::uint32_t phislice =
88 (std::uint32_t)(phi / (2 * M_PI) *
m_cfg.numPhiSlices);
89 if (phislice >=
m_cfg.numPhiSlices) {
93 if (std::abs(sp.z()) >=
m_cfg.maxAbsZ) {
96 std::uint32_t zslice = (std::uint32_t)(
100 if (sp.r() <
m_cfg.rMinMiddle) {
101 if (
m_cfg.rMinNear < sp.r() && sp.r() <
m_cfg.rMaxNear) {
102 if (std::fmod(
m_cfg.useFracPhiSlices * phislice, 1.0) >=
103 m_cfg.useFracPhiSlices) {
106 sortedSpacepoints.
addSP(0, phislice, zslice)
107 .emplace_back((spacepoint_t
const*)&sp, phi);
109 }
else if (sp.r() <
m_cfg.rMinFar) {
110 if (sp.r() <
m_cfg.rMaxMiddle) {
111 if (std::fmod(
m_cfg.useFracZSlices * zslice, 1.0) >=
112 m_cfg.useFracZSlices) {
115 sortedSpacepoints.
addSP(1, phislice, zslice)
116 .emplace_back((spacepoint_t
const*)&sp, phi);
118 }
else if (sp.r() <
m_cfg.rMaxFar) {
119 sortedSpacepoints.
addSP(2, phislice, zslice)
120 .emplace_back((spacepoint_t
const*)&sp, phi);
124 return sortedSpacepoints;
127 template <
typename spacepo
int_t>
128 std::vector<typename Acts::SingleSeedVertexFinder<spacepoint_t>::Triplet>
131 sortedSpacepoints)
const {
132 std::vector<Acts::SingleSeedVertexFinder<spacepoint_t>::Triplet> triplets;
134 std::uint32_t phiStep =
135 (std::uint32_t)(
m_cfg.maxPhideviation / (2 * M_PI /
m_cfg.numPhiSlices)) +
142 vecB /= std::tan(
m_cfg.maxXYZdeviation);
148 (posR[1] -
m_cfg.rMaxNear) * (posR[1] -
m_cfg.rMaxNear) - R *
R;
150 -1. * (-constB - sqrt(constB * constB - 4. * constC)) / 2.;
151 if (maxZMiddle <= 0) {
153 "maximum position of middle spacepoints is not positive, maxZMiddle = "
154 << maxZMiddle <<
", check your config; setting maxZMiddle to "
156 maxZMiddle =
m_cfg.maxAbsZ;
170 std::uint32_t limitMiddleSliceFrom =
171 (std::uint32_t)((-maxZMiddle +
m_cfg.maxAbsZ) / zBinLength);
172 std::uint32_t limitMiddleSliceTo =
173 (std::uint32_t)((maxZMiddle +
m_cfg.maxAbsZ) / zBinLength + 1);
174 std::uint32_t limitAbsZSliceFrom = (std::uint32_t)(
175 (-
m_cfg.maxZPosition +
m_cfg.maxAbsZ) / zBinLength + 0.01);
176 std::uint32_t limitAbsZSliceTo =
177 (std::uint32_t)((
m_cfg.maxZPosition +
m_cfg.maxAbsZ) / zBinLength + 1.01);
179 for (std::uint32_t middleZ = limitMiddleSliceFrom;
180 middleZ < limitMiddleSliceTo; ++middleZ) {
182 if (std::fmod(
m_cfg.useFracZSlices * middleZ, 1.0) >=
183 m_cfg.useFracZSlices) {
189 bool isLessFrom = (middleZ <= limitAbsZSliceFrom);
191 (middleZ - limitAbsZSliceFrom - 1) * zBinLength;
193 std::atan2(rMiddle[isLessFrom], deltaZfrom) +
m_cfg.maxXYZdeviation;
194 std::uint32_t nearZFrom = 0;
195 if (angleZfrom < M_PI) {
197 rMiddle[isLessFrom] / std::tan(angleZfrom) / zBinLength;
198 nearZFrom = (std::uint32_t)std::max(
199 new_deltaZfrom * rNearRatio[isLessFrom] + limitAbsZSliceFrom, 0.);
202 bool isLessTo = (middleZ < limitAbsZSliceTo);
205 std::atan2(rMiddle[!isLessTo], deltaZto) -
m_cfg.maxXYZdeviation;
206 std::uint32_t nearZTo =
m_cfg.numZSlices;
209 rMiddle[!isLessTo] / std::tan(angleZto) / zBinLength;
210 nearZTo = (std::uint32_t)std::max(
211 new_deltaZto * rNearRatio[!isLessTo] + limitAbsZSliceTo, 0.);
212 if (nearZTo >
m_cfg.numZSlices) {
213 nearZTo =
m_cfg.numZSlices;
217 for (std::uint32_t nearZ = nearZFrom; nearZ < nearZTo; ++nearZ) {
220 bool isMiddleLess = (middleZ <= nearZ);
224 std::atan2(rFarDelta[isMiddleLess], delta2Zfrom) +
225 m_cfg.maxXYZdeviation;
226 std::uint32_t farZFrom = 0;
227 if (angle2Zfrom < M_PI) {
228 farZFrom = (std::uint32_t)std::max(
229 (rFarDelta[isMiddleLess] / std::tan(angle2Zfrom) / zBinLength) +
232 if (farZFrom >=
m_cfg.numZSlices) {
237 isMiddleLess = (middleZ < nearZ);
240 std::atan2(rFarDelta[!isMiddleLess], delta2Zto) -
241 m_cfg.maxXYZdeviation;
242 std::uint32_t farZTo =
m_cfg.numZSlices;
244 farZTo = (std::uint32_t)std::max(
245 (rFarDelta[!isMiddleLess] / std::tan(angle2Zto) / zBinLength) +
248 if (farZTo >
m_cfg.numZSlices) {
249 farZTo =
m_cfg.numZSlices;
250 }
else if (farZTo == 0) {
255 for (std::uint32_t farZ = farZFrom; farZ < farZTo; farZ++) {
257 for (std::uint32_t nearPhi = 0; nearPhi <
m_cfg.numPhiSlices;
260 if (std::fmod(
m_cfg.useFracPhiSlices * nearPhi, 1.0) >=
261 m_cfg.useFracPhiSlices) {
266 for (std::uint32_t middlePhi_h =
267 m_cfg.numPhiSlices + nearPhi - phiStep;
268 middlePhi_h <=
m_cfg.numPhiSlices + nearPhi + phiStep;
270 std::uint32_t middlePhi = middlePhi_h %
m_cfg.numPhiSlices;
273 for (std::uint32_t farPhi_h =
274 m_cfg.numPhiSlices + middlePhi - phiStep;
275 farPhi_h <=
m_cfg.numPhiSlices + middlePhi + phiStep;
277 std::uint32_t farPhi = farPhi_h %
m_cfg.numPhiSlices;
280 for (
const auto& nearSP :
281 sortedSpacepoints.
getSP(0, nearPhi, nearZ)) {
285 for (
const auto& middleSP :
286 sortedSpacepoints.
getSP(1, middlePhi, middleZ)) {
290 if (std::abs(deltaPhiAB) >
m_cfg.maxPhideviation) {
295 for (
const auto& farSP :
296 sortedSpacepoints.
getSP(2, farPhi, farZ)) {
300 if (std::abs(deltaPhiBC) >
m_cfg.maxPhideviation) {
305 *nearSP.first, *middleSP.first, *farSP.first);
307 if (tripletValidationAndUpdate(tr)) {
308 triplets.push_back(tr);
323 template <
typename spacepo
int_t>
328 std::atan2(triplet.a.y() - triplet.
b.y(), triplet.a.x() - triplet.
b.x());
331 std::atan2(triplet.
b.y() - triplet.
c.y(), triplet.
b.x() - triplet.
c.x());
335 if (std::abs(deltaAlpha) >
m_cfg.maxXYdeviation) {
340 Acts::Vector3 ab{triplet.a.x() - triplet.
b.x(), triplet.a.y() - triplet.
b.y(),
341 triplet.a.z() - triplet.
b.z()};
344 triplet.
b.z() - triplet.
c.z()};
348 if (theta >
m_cfg.maxXYZdeviation) {
361 if (std::abs(tanTheta) < std::tan(
m_cfg.minTheta)) {
367 if (dist >
m_cfg.maxRPosition) {
373 direction.cross(
norm).dot(startPoint) / (norm_size * norm_size);
374 if (std::abs(zDist) >
m_cfg.maxZPosition) {
378 if (
m_cfg.minimalizeWRT ==
"rays") {
386 template <
typename spacepo
int_t>
387 std::pair<Acts::Vector3, Acts::ActsScalar>
405 template <
typename spacepo
int_t>
425 tripletsWithPlanes.reserve(triplets.size());
427 for (
const auto& triplet : triplets) {
429 tripletsWithPlanes.emplace_back(abgd, -1.);
435 for (
const auto& triplet : tripletsWithPlanes) {
436 const auto& abg = triplet.first.first;
437 const auto&
delta = triplet.first.second;
439 A += 2. * (abg * abg.transpose());
440 B -= 2. *
delta * abg;
443 for (std::uint32_t iter = 0; iter <=
m_cfg.maxIterations; iter++) {
445 vtx = A.lu().solve(B);
449 if (vtxDiff.norm() <
m_cfg.minVtxShift) {
454 if (iter !=
m_cfg.maxIterations) {
458 for (
auto& triplet : tripletsWithPlanes) {
459 const auto& abg = triplet.first.first;
460 const auto&
delta = triplet.first.second;
465 std::sort(tripletsWithPlanes.begin(), tripletsWithPlanes.end(),
466 [](
const auto&
lhs,
const auto&
rhs) {
467 return lhs.second <
rhs.second;
470 std::uint32_t threshold = (std::uint32_t)(tripletsWithPlanes.size() *
471 (1. -
m_cfg.removeFraction));
473 for (std::uint32_t tr = threshold + 1; tr < tripletsWithPlanes.size();
475 const auto& abg = tripletsWithPlanes[tr].first.first;
476 const auto&
delta = tripletsWithPlanes[tr].first.second;
479 A -= 2. * (abg * abg.transpose());
480 B += 2. *
delta * abg;
484 tripletsWithPlanes.resize(threshold);
491 template <
typename spacepo
int_t>
495 mat.row(0) =
Acts::Vector3(triplet.a.x(), triplet.a.y(), triplet.a.z());
501 (mat.rowwise() - mean.transpose()) / 3.;
504 Eigen::SelfAdjointEigenSolver<Acts::SquareMatrix3> saes(cov);
508 return {
mean, eivec};
511 template <
typename spacepo
int_t>
531 tripletsWithRays.reserve(triplets.size());
533 for (
const auto& triplet : triplets) {
534 tripletsWithRays.emplace_back(
535 std::make_pair(triplet.ray.origin(), triplet.ray.dir()), -1.);
540 Acts::SquareMatrix3::Identity() * 2. * triplets.size();
542 for (
const auto& triplet : tripletsWithRays) {
544 const auto& startPoint = triplet.first.first;
545 const auto& direction = triplet.first.second;
547 A -= 2. * (direction * direction.transpose());
548 B += -2. * direction * (direction.dot(startPoint)) + 2. * startPoint;
551 for (std::uint32_t iter = 0; iter <=
m_cfg.maxIterations; iter++) {
553 vtx = A.lu().solve(B);
557 if (vtxDiff.norm() <
m_cfg.minVtxShift) {
562 if (iter !=
m_cfg.maxIterations) {
566 for (
auto& triplet : tripletsWithRays) {
567 const auto& startPoint = triplet.first.first;
568 const auto& direction = triplet.first.second;
573 std::sort(tripletsWithRays.begin(), tripletsWithRays.end(),
574 [](
const auto&
lhs,
const auto&
rhs) {
575 return lhs.second <
rhs.second;
578 std::uint32_t threshold = (std::uint32_t)(tripletsWithRays.size() *
579 (1. -
m_cfg.removeFraction));
581 for (std::uint32_t tr = threshold + 1; tr < tripletsWithRays.size();
583 const auto& startPoint = tripletsWithRays[tr].first.first;
584 const auto& direction = tripletsWithRays[tr].first.second;
587 A -= Acts::SquareMatrix3::Identity() * 2.;
588 A += 2. * (direction * direction.transpose());
589 B -= -2. * direction * (direction.dot(startPoint)) + 2. * startPoint;
593 tripletsWithRays.resize(threshold);