19 #include <type_traits>
22 template <
typename external_spacepo
int_t>
25 float colMin = m_config.collisionRegionMin;
26 float colMax = m_config.collisionRegionMax;
28 float rL = low.radius();
37 res[DimPhi].shrinkMin(m_config.phiMin);
38 res[DimPhi].shrinkMax(m_config.phiMax);
44 res[DimR].shrinkMax(m_config.rMax);
50 res[DimZ].shrinkMin(m_config.zMin);
51 res[DimZ].shrinkMax(m_config.zMax);
57 res[DimR].shrinkMin(rL + m_config.deltaRMinTopSP);
58 res[DimR].shrinkMax(rL + m_config.deltaRMaxTopSP);
64 float zMax = (res[DimR].max() / rL) * (zL - colMin) + colMin;
65 float zMin = colMax - (res[DimR].max() / rL) * (colMax - zL);
71 res[DimZ].shrinkMax(zMax);
72 }
else if (zL < colMax) {
73 res[DimZ].shrinkMin(zMin);
79 res[DimZ].shrinkMin(zL - m_config.cotThetaMax * (res[DimR].max() - rL));
80 res[DimZ].shrinkMax(zL + m_config.cotThetaMax * (res[DimR].max() - rL));
85 res[DimPhi].shrinkMin(pL - m_config.deltaPhiMax);
86 res[DimPhi].shrinkMax(pL + m_config.deltaPhiMax);
91 template <
typename external_spacepo
int_t>
94 float pM = high.phi();
95 float rM = high.radius();
103 res[DimPhi].shrinkMin(m_config.phiMin);
104 res[DimPhi].shrinkMax(m_config.phiMax);
110 res[DimR].shrinkMax(m_config.rMax);
116 res[DimZ].shrinkMin(m_config.zMin);
117 res[DimZ].shrinkMax(m_config.zMax);
123 res[DimR].shrinkMin(rM - m_config.deltaRMaxBottomSP);
124 res[DimR].shrinkMax(rM - m_config.deltaRMinBottomSP);
130 float fracR = res[DimR].min() / rM;
132 float zMin = (high.z() - m_config.collisionRegionMin) * fracR +
133 m_config.collisionRegionMin;
134 float zMax = (high.z() - m_config.collisionRegionMax) * fracR +
135 m_config.collisionRegionMax;
137 res[DimZ].shrinkMin(
std::min(zMin, high.z()));
138 res[DimZ].shrinkMax(std::max(zMax, high.z()));
143 res[DimPhi].shrinkMin(pM - m_config.deltaPhiMax);
144 res[DimPhi].shrinkMax(pM + m_config.deltaPhiMax);
149 template <
typename external_spacepo
int_t>
161 float deltaZ = (zH - zL);
162 float cotTheta = deltaZ /
deltaR;
167 float zOrigin = zL - rL * cotTheta;
168 if (zOrigin < m_config.collisionRegionMin ||
169 zOrigin > m_config.collisionRegionMax) {
179 if (m_config.interactionPointCut) {
180 float xVal = (high.
x() - low.
x()) * (low.
x() / rL) +
181 (high.
y() - low.
y()) * (low.
y() / rL);
182 float yVal = (high.
y() - low.
y()) * (low.
x() / rL) -
183 (high.
x() - low.
x()) * (low.
y() / rL);
185 const int sign = isMiddleInverted ? -1 : 1;
187 if (std::abs(rL * yVal) > sign * m_config.impactMax * xVal) {
192 float uT = xVal / (xVal * xVal + yVal * yVal);
193 float vT = yVal / (xVal * xVal + yVal * yVal);
196 float uIP = -1. / rL;
197 float vIP = m_config.impactMax / (rL * rL);
198 if (sign * yVal > 0.) {
204 float aCoef = (vT - vIP) / (uT - uIP);
205 float bCoef = vIP - aCoef * uIP;
219 if (std::fabs(cotTheta) > m_config.cotThetaMax) {
225 if (std::abs(deltaZ) > m_config.deltaZMax) {
232 template <
typename external_spacepo
int_t>
237 throw std::runtime_error(
238 "SeedFinderOrthogonalConfig not in ACTS internal units in "
239 "SeedFinderOrthogonal");
243 template <
typename external_spacepo
int_t>
246 std::vector<internal_sp_t *> &bottom, std::vector<internal_sp_t *> &top,
249 &candidates_collector,
251 float rM = middle.
radius();
252 float zM = middle.
z();
257 if (m_config.seedConfirmation ==
true) {
260 (zM > m_config.centralSeedConfirmationRange.zMaxSeedConf ||
261 zM < m_config.centralSeedConfirmationRange.zMinSeedConf)
262 ? m_config.forwardSeedConfirmationRange
263 : m_config.centralSeedConfirmationRange;
277 std::vector<const internal_sp_t *> top_valid;
278 std::vector<float> curvatures;
279 std::vector<float> impactParameters;
283 std::vector<LinCircle> linCircleBottom;
285 std::vector<LinCircle> linCircleTop;
292 std::vector<std::size_t> sorted_bottoms(linCircleBottom.size());
293 for (std::size_t
i(0);
i < sorted_bottoms.size(); ++
i) {
294 sorted_bottoms[
i] =
i;
297 std::vector<std::size_t> sorted_tops(linCircleTop.size());
298 for (std::size_t
i(0);
i < sorted_tops.size(); ++
i) {
303 sorted_bottoms.begin(), sorted_bottoms.end(),
304 [&linCircleBottom](
const std::size_t
a,
const std::size_t
b) ->
bool {
305 return linCircleBottom[
a].cotTheta < linCircleBottom[
b].cotTheta;
308 std::sort(sorted_tops.begin(), sorted_tops.end(),
309 [&linCircleTop](
const std::size_t
a,
const std::size_t
b) ->
bool {
310 return linCircleTop[
a].cotTheta < linCircleTop[
b].cotTheta;
313 std::vector<float> tanMT;
314 tanMT.reserve(top.size());
316 size_t numTopSP = top.size();
317 for (
size_t t = 0;
t < numTopSP;
t++) {
319 std::atan2(top[
t]->radius() - middle.
radius(), top[
t]->z() - zM));
324 for (
const std::size_t
b : sorted_bottoms) {
326 if (t0 == numTopSP) {
330 auto lb = linCircleBottom[
b];
333 float iSinTheta2 = (1. + lb.cotTheta * lb.cotTheta);
349 size_t minCompatibleTopSPs = 2;
350 if (!m_config.seedConfirmation or
352 minCompatibleTopSPs = 1;
355 minCompatibleTopSPs++;
361 impactParameters.clear();
363 float tanLM = std::atan2(rM - bottom[
b]->radius(), zM - bottom[
b]->
z());
365 for (
size_t index_t = t0; index_t < numTopSP; index_t++) {
366 const std::size_t
t = sorted_tops[index_t];
367 auto lt = linCircleTop[
t];
369 if (std::abs(tanLM - tanMT[t]) > 0.005) {
375 float error2 = lt.Er + lb.Er +
376 2 * (lb.cotTheta * lt.cotTheta * varianceRM + varianceZM) *
377 lb.iDeltaR * lt.iDeltaR;
379 float deltaCotTheta = lb.cotTheta - lt.cotTheta;
380 float deltaCotTheta2 = deltaCotTheta * deltaCotTheta;
392 if (deltaCotTheta2 > (error2 + scatteringInRegion2)) {
396 if (deltaCotTheta < 0) {
403 float dU = lt.U - lb.U;
407 float A = (lt.V - lb.V) / dU;
408 float S2 = 1. + A *
A;
409 float B = lb.V - A * lb.U;
420 float p2scatterSigma = B2 / S2 * sigmaSquaredPtDependent;
421 if (!std::isinf(m_config.maxPtScattering)) {
425 2. * m_config.maxPtScattering) {
426 float pTscatterSigma =
427 (m_config.highland / m_config.maxPtScattering) *
428 m_config.sigmaScattering;
429 p2scatterSigma = pTscatterSigma * pTscatterSigma * iSinTheta2;
433 if (deltaCotTheta2 > (error2 + p2scatterSigma)) {
434 if (deltaCotTheta < 0) {
444 float Im = std::abs((A - B * rM) * rM);
446 if (Im <= m_config.impactMax) {
447 top_valid.push_back(top[t]);
450 curvatures.push_back(B / std::sqrt(S2));
451 impactParameters.push_back(Im);
456 if (top.size() < minCompatibleTopSPs) {
460 seedFilterState.
zOrigin = zM - rM * lb.cotTheta;
462 m_config.seedFilter->filterSeeds_2SpFixed(
463 spacePointData, *bottom[
b], middle, top_valid, curvatures,
464 impactParameters, seedFilterState, candidates_collector);
469 template <
typename external_spacepo
int_t>
470 template <
typename output_container_t>
473 output_container_t &out_cont,
const typename tree_t::pair_t &middle_p,
488 std::vector<internal_sp_t *> bottom_lh_v, bottom_hl_v, top_lh_v, top_hl_v;
493 std::size_t max_num_quality_seeds_per_spm =
494 m_config.seedFilter->getSeedFilterConfig().maxQualitySeedsPerSpMConf;
495 std::size_t max_num_seeds_per_spm =
496 m_config.seedFilter->getSeedFilterConfig().maxSeedsPerSpMConf;
499 candidates_collector;
501 max_num_quality_seeds_per_spm);
507 range_t bottom_r = validTupleOrthoRangeHL(middle);
508 range_t top_r = validTupleOrthoRangeLH(middle);
514 std::max(std::abs(middle.
z() / middle.
radius()), m_config.cotThetaMax);
520 float deltaRMaxTop = top_r[DimR].max() - middle.
radius();
521 float deltaRMaxBottom = middle.
radius() - bottom_r[DimR].min();
530 range_t bottom_lh_r = bottom_r;
531 bottom_lh_r[DimZ].shrink(middle.
z() - myCotTheta * deltaRMaxBottom,
538 range_t top_lh_r = top_r;
539 top_lh_r[DimZ].shrink(middle.
z(), middle.
z() + myCotTheta * deltaRMaxTop);
541 range_t bottom_hl_r = bottom_r;
542 bottom_hl_r[DimZ].shrink(middle.
z(),
543 middle.
z() + myCotTheta * deltaRMaxBottom);
544 range_t top_hl_r = top_r;
545 top_hl_r[DimZ].shrink(middle.
z() - myCotTheta * deltaRMaxTop, middle.
z());
563 if (!bottom_lh_r.degenerate() && !top_lh_r.degenerate()) {
568 [
this, &options, &middle, &top_lh_v](
571 if (validTuple(options, *top, middle,
true)) {
572 top_lh_v.push_back(top);
581 if (!bottom_hl_r.degenerate() && !top_hl_r.degenerate()) {
583 [
this, &options, &middle, &top_hl_v](
586 if (validTuple(options, middle, *top,
false)) {
587 top_hl_v.push_back(top);
594 bool search_bot_hl =
true;
595 bool search_bot_lh =
true;
596 if (m_config.seedConfirmation) {
599 (middle.
z() > m_config.centralSeedConfirmationRange.zMaxSeedConf ||
600 middle.
z() < m_config.centralSeedConfirmationRange.zMinSeedConf)
601 ? m_config.forwardSeedConfirmationRange
602 : m_config.centralSeedConfirmationRange;
612 search_bot_lh =
false;
615 search_bot_hl =
false;
623 if (!top_lh_v.empty() and search_bot_lh) {
625 bottom_lh_r, [
this, &options, &middle, &bottom_lh_v](
628 if (validTuple(options, *bottom, middle,
false)) {
629 bottom_lh_v.push_back(bottom);
637 if (!top_hl_v.empty() and search_bot_hl) {
639 bottom_hl_r, [
this, &options, &middle, &bottom_hl_v](
642 if (validTuple(options, middle, *bottom,
true)) {
643 bottom_hl_v.push_back(bottom);
651 if (!bottom_lh_v.empty() && !top_lh_v.empty()) {
652 filterCandidates(options, middle, bottom_lh_v, top_lh_v, seedFilterState,
653 candidates_collector, spacePointData);
658 if (!bottom_hl_v.empty() && !top_hl_v.empty()) {
659 filterCandidates(options, middle, bottom_hl_v, top_hl_v, seedFilterState,
660 candidates_collector, spacePointData);
665 if ((!bottom_lh_v.empty() && !top_lh_v.empty()) or
666 (!bottom_hl_v.empty() && !top_hl_v.empty())) {
667 m_config.seedFilter->filterSeeds_1SpFixed(
669 std::back_inserter(out_cont));
673 template <
typename external_spacepo
int_t>
675 const std::vector<internal_sp_t *> &spacePoints)
const ->
tree_t {
676 std::vector<typename tree_t::pair_t> points;
686 point[DimPhi] = sp->phi();
687 point[DimR] = sp->radius();
688 point[DimZ] = sp->z();
690 points.emplace_back(point, sp);
696 template <
typename external_spacepo
int_t>
697 template <
typename input_container_t,
typename output_container_t,
701 const input_container_t &spacePoints, output_container_t &out_cont,
702 callable_t &&extract_coordinates)
const {
704 throw std::runtime_error(
705 "SeedFinderOptions not in ACTS internal units in "
706 "SeedFinderOrthogonal");
715 "Output iterator container type must accept seeds.");
717 const external_spacepoint_t *>,
718 "Input container must contain external spacepoints.");
727 std::size_t counter = 0;
728 std::vector<internal_sp_t *> internalSpacePoints;
730 spacePointData.
resize(spacePoints.size());
732 for (
const external_spacepoint_t *
p : spacePoints) {
733 auto [
position, variance] = extract_coordinates(
p);
742 m_config.deltaRMiddleMinSPRange,
744 m_config.deltaRMiddleMaxSPRange);
750 tree_t tree = createTree(internalSpacePoints);
757 auto rM = middle.
radius();
763 if (m_config.useVariableMiddleSPRange) {
764 if (rM < rMiddleSPRange.
min() || rM > rMiddleSPRange.
max()) {
768 if (rM > m_config.rMaxMiddle || rM < m_config.rMinMiddle) {
774 if (middle.
z() < m_config.zOutermostLayers.first or
775 middle.
z() > m_config.zOutermostLayers.second) {
778 float spPhi = middle.
phi();
779 if (spPhi > m_config.phiMax or spPhi < m_config.phiMin) {
783 processFromMiddleSP(options, tree, out_cont, middle_p, spacePointData);
794 template <
typename external_spacepo
int_t>
795 template <
typename input_container_t,
typename callable_t>
796 std::vector<Seed<external_spacepoint_t>>
799 const input_container_t &spacePoints,
800 callable_t &&extract_coordinates)
const {
801 std::vector<seed_t>
r;
802 createSeeds(options, spacePoints, r,
803 std::forward<callable_t>(extract_coordinates));