35 static inline int quant(
double min,
double max,
unsigned nSteps,
double val);
36 static inline double unquant(
double min,
double max,
unsigned nSteps,
int step);
42 : ActsExamples::
IAlgorithm(
"HoughTransformSeeder", lvl),
47 bool foundInput =
false;
49 if (!(spName.empty())) {
57 handle->initialize(spName);
64 throw std::invalid_argument(
65 "HoughTransformSeeder: Missing some kind of input (measurements of "
70 throw std::invalid_argument(
71 "HoughTransformSeeder: Missing hough tracks output collection");
74 throw std::invalid_argument(
75 "HoughTransformSeeder: Missing hough track seeds output collection");
79 throw std::invalid_argument(
80 "HoughTransformSeeder: Missing source link input collection");
88 throw std::invalid_argument(
89 "HoughTransformSeeder: Missing tracking geometry");
93 throw std::invalid_argument(
94 "HoughTransformSeeder: Missing geometry selection");
98 if ((geoId.approach() != 0
u) or (geoId.boundary() != 0
u) or
99 (geoId.sensitive() != 0
u)) {
100 throw std::invalid_argument(
101 "HoughTransformSeeder: Invalid geometry selection: only volume and "
102 "layer are allowed to be set");
122 return (ref.
layer() ==
cmp.layer());
128 auto geoSelLastUnique = std::unique(geoSelBeg, geoSelEnd, isDuplicate);
129 if (geoSelLastUnique != geoSelEnd) {
131 <<
" geometry selection duplicates");
168 addMeasurements(ctx);
174 for (
int subregion :
m_cfg.subRegions) {
175 ACTS_DEBUG(
"Processing subregion " << subregion);
178 for (
unsigned y = 0;
y <
m_cfg.houghHistSize_y;
y++) {
179 for (
unsigned x = 0;
x <
m_cfg.houghHistSize_x;
x++) {
180 if (passThreshold(m_houghHist,
x,
y)) {
185 std::vector<std::vector<std::vector<Index>>> hitIndicesAll(
187 std::vector<size_t> nHitsPerLayer(
m_cfg.nLayers);
188 for (
auto measurementIndex : m_houghHist(
y,
x).second) {
192 nHitsPerLayer[meas->
layer]++;
194 std::vector<std::vector<int>> combs = getComboIndices(nHitsPerLayer);
196 for (
auto [icomb, hit_indices] :
201 if (hit_indices[
layer] >= 0) {
203 protoTrack.push_back(
index);
207 protoTracks.push_back(protoTrack);
213 ACTS_DEBUG(
"Created " << protoTracks.size() <<
" proto track");
223 int subregion)
const {
225 m_cfg.houghHistSize_x);
229 if (meas->
layer != layer) {
237 for (
unsigned y_ = 0;
y_ <
m_cfg.houghHistSize_y;
y_++) {
238 unsigned y_bin_min =
y_;
239 unsigned y_bin_max = (
y_ + 1);
243 yToXBins(y_bin_min, y_bin_max, meas->
radius, meas->
phi, meas->
layer);
245 for (
unsigned y = y_bin_min;
y < y_bin_max;
y++) {
246 for (
unsigned x = xBins.first;
x < xBins.second;
x++) {
247 houghHist(
y,
x).first++;
248 houghHist(
y,
x).second.insert(
index);
258 int subregion)
const {
260 m_cfg.houghHistSize_x);
262 for (
unsigned i = 0;
i <
m_cfg.nLayers;
i++) {
263 HoughHist layerHoughHist = createLayerHoughHist(
i, subregion);
264 for (
unsigned x = 0;
x <
m_cfg.houghHistSize_x; ++
x) {
265 for (
unsigned y = 0;
y <
m_cfg.houghHistSize_y; ++
y) {
266 if (layerHoughHist(
y,
x).first > 0) {
267 houghHist(
y,
x).first++;
268 houghHist(
y,
x).second.insert(layerHoughHist(
y,
x).second.begin(),
269 layerHoughHist(
y,
x).second.end());
279 HoughHist const& houghHist,
unsigned x,
unsigned y)
const {
282 if (x < width || (houghHist.
size(1) -
x) < width) {
285 for (
unsigned i = 0;
i <
m_cfg.threshold.size();
i++) {
286 if (houghHist(y, x - width +
i).first <
m_cfg.threshold[
i]) {
292 if (
m_cfg.localMaxWindowSize != 0) {
293 for (
int j = -
m_cfg.localMaxWindowSize;
j <=
m_cfg.localMaxWindowSize;
295 for (
int i = -
m_cfg.localMaxWindowSize;
i <=
m_cfg.localMaxWindowSize;
297 if (
i == 0 &&
j == 0) {
300 if (y +
j < houghHist.
size(0) && x +
i < houghHist.
size(1)) {
301 if (houghHist(y +
j, x +
i).first > houghHist(y, x).first) {
304 if (houghHist(y +
j, x +
i).first == houghHist(y, x).first) {
305 if (houghHist(y +
j, x +
i).second.
size() >
306 houghHist(y, x).second.
size()) {
309 if (houghHist(y +
j, x +
i).second.
size() ==
310 houghHist(y, x).second.
size() &&
328 static inline int quant(
double min,
double max,
unsigned nSteps,
double val) {
329 return static_cast<int>((val -
min) / (max - min) * nSteps);
333 static inline double unquant(
double min,
double max,
unsigned nSteps,
335 return min + (max -
min) * step / nSteps;
338 template <
typename T>
340 std::ostringstream oss;
343 std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(oss,
", "));
356 if (
m_cfg.fieldCorrector.connected()) {
367 size_t yBin_min,
size_t yBin_max,
double r,
double phi,
368 unsigned layer)
const {
369 double x_min = yToX(m_bins_y[yBin_min], r, phi);
370 double x_max = yToX(m_bins_y[yBin_max], r, phi);
374 if (x_max < m_cfg.xMin || x_min >
m_cfg.xMax) {
384 unsigned extend = getExtension(yBin_min, layer);
392 if (x_bin_max > static_cast<int>(
m_cfg.houghHistSize_x)) {
393 x_bin_max =
m_cfg.houghHistSize_x;
396 return {x_bin_min, x_bin_max};
402 unsigned y,
unsigned layer)
const {
403 if (
m_cfg.hitExtend_x.size() ==
m_cfg.nLayers) {
407 if (
m_cfg.hitExtend_x.size() ==
m_cfg.nLayers * 2) {
411 if (y < m_cfg.houghHistSize_y / 4 || y > 3 *
m_cfg.houghHistSize_y / 4) {
435 std::vector<std::vector<int>>
437 std::vector<size_t>& sizes)
const {
439 std::vector<size_t> nCombs_prior(sizes.size());
440 std::vector<int> temp(sizes.size(), 0);
442 for (
size_t i = 0;
i < sizes.size();
i++) {
444 nCombs_prior[
i] = nCombs;
451 std::vector<std::vector<int>> combos(nCombs, temp);
453 for (
size_t icomb = 0; icomb < nCombs; icomb++) {
454 size_t index = icomb;
455 for (
size_t isize = sizes.size() - 1; isize < sizes.size(); isize--) {
456 if (sizes[isize] == 0) {
459 combos[icomb][isize] =
static_cast<int>(index / nCombs_prior[isize]);
460 index = index % nCombs_prior[isize];
471 for (
const auto& isp : m_inputSpacePoints) {
472 const auto& spContainer = (*isp)(ctx);
473 ACTS_DEBUG(
"Inserting " << spContainer.size() <<
" space points from "
475 for (
auto& sp : spContainer) {
476 double r = std::hypot(sp.x(), sp.y());
478 float phi = std::atan2(sp.y(), sp.x());
480 if (!(hitlayer.ok())) {
483 std::vector<Index> indices;
484 for (
const auto& slink : sp.sourceLinks()) {
486 indices.push_back(islink.index());
499 const auto& measurements = m_inputMeasurements(ctx);
500 const auto& sourceLinks = m_inputSourceLinks(ctx);
502 ACTS_DEBUG(
"Inserting " << measurements.size() <<
" space points from "
503 <<
m_cfg.inputMeasurements);
512 for (
auto [moduleGeoId, moduleSourceLinks] : groupedByModule) {
515 m_cfg.trackingGeometry->findSurface(moduleGeoId);
516 if (surface ==
nullptr) {
517 ACTS_ERROR(
"Could not find surface " << moduleGeoId);
521 for (
auto& sourceLink : moduleSourceLinks) {
528 auto [localPos, localCov] = std::visit(
529 [](
const auto& meas) {
530 auto expander = meas.expander();
533 expander * meas.covariance() * expander.transpose();
539 return std::make_pair(lpar, lcov);
541 measurements[sourceLink.index()]);
548 double phi = std::atan2(globalPos[Acts::ePos1], globalPos[Acts::ePos0]);
552 std::vector<Index>
index;
553 index.push_back(sourceLink.index());
554 auto meas = std::shared_ptr<HoughMeasurementStruct>(