Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 08:18:03

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Seeding/GbtsLayerConnectionTool.hpp"
0010 
0011 #include <cmath>
0012 #include <stdexcept>
0013 
0014 namespace Acts::Experimental {
0015 
0016 GbtsLayerConnectionTool::LayerDescription::LayerDescription(
0017     float minR_, float maxR_, float minZ_, float maxZ_, std::int32_t gbtsId_)
0018     : minR(minR_), maxR(maxR_), minZ(minZ_), maxZ(maxZ_), gbtsId(gbtsId_) {}
0019 
0020 GbtsLayerConnectionTool::GbtsLayerConnectionTool(
0021     const Config& config, std::unique_ptr<const Logger> logger)
0022     : m_cfg(config), m_logger(std::move(logger)) {
0023   if (m_cfg.detectorGeometry.empty()) {
0024     throw std::runtime_error("File does not exist or could not be opened");
0025   }
0026 
0027   // reserves
0028   const std::uint32_t pairReserve = m_cfg.detectorGeometry.size();
0029   m_layerPairs.reserve(pairReserve * (pairReserve - 1));
0030 
0031   // create map linked pairs of GBTS ids with number of transitions between
0032   // layers
0033   for (std::uint32_t i = 0; i < m_cfg.detectorGeometry.size(); i++) {
0034     for (std::uint32_t j = 0; j < m_cfg.detectorGeometry.size(); j++) {
0035       if (i == j) {
0036         continue;
0037       }
0038 
0039       LayerIdPair pair;
0040       pair.first = m_cfg.detectorGeometry[i].gbtsId;
0041       pair.second = m_cfg.detectorGeometry[j].gbtsId;
0042 
0043       // key = GBTS ids of pair, value = number of transitions
0044       m_layerPairs.emplace(pair, 0);
0045     }
0046   }
0047 }
0048 
0049 void GbtsLayerConnectionTool::addTrack(std::span<const HitCoordinates> track) {
0050   if (track.size() < 2) {
0051     ACTS_WARNING("Track only has one measurement, skipping");
0052     return;
0053   }
0054 
0055   // container for gbts IDs of the track
0056   std::vector<std::optional<std::int32_t>> layerGbtsIds{};
0057   layerGbtsIds.reserve(track.size());
0058 
0059   // find GBTS ids for all measurements in a track
0060   for (const auto& measurement : track) {
0061     const auto gbtsId = findGbtsIdByCoord(measurement);
0062     if (!gbtsId) {
0063       ACTS_WARNING("No Gbts Layer for coordinates with r: "
0064                    << measurement.r << " and z: " << measurement.z);
0065     }
0066     layerGbtsIds.emplace_back(gbtsId);
0067   }
0068 
0069   // update map with track layer transitions
0070   for (std::uint32_t id = 0; id + 1 < layerGbtsIds.size(); id++) {
0071     const auto& index1 = layerGbtsIds[id];
0072     const auto& index2 = layerGbtsIds[id + 1];
0073 
0074     // skip nonexistent layers ids
0075     if (!index1 || !index2) {
0076       continue;
0077     }
0078 
0079     if (index1.value() == index2.value()) {
0080       ACTS_WARNING("Track transitions between same layer, skipping");
0081 
0082       continue;
0083     }
0084 
0085     m_layerPairs[{index1.value(), index2.value()}] += 1;
0086   }
0087 
0088   m_totalTracks++;
0089 }
0090 
0091 GbtsLayerConnectionTool::LayerIdPairs
0092 GbtsLayerConnectionTool::createConnectionTable() const {
0093   if (m_totalTracks == 0) {
0094     throw std::runtime_error(
0095         "Warning: no tracks were added when creating connection table");
0096   }
0097 
0098   // obtain total incoming transitions for each src layer (used as denominator
0099   // of probability)
0100   std::vector<std::uint32_t> srcTotals;
0101   srcTotals.resize(m_cfg.detectorGeometry.size(), 0);
0102 
0103   for (const auto& [layerPair, nTransitions] : m_layerPairs) {
0104     std::uint32_t layerIndex = getIndexByGbtsId(layerPair.first);
0105     srcTotals[layerIndex] += nTransitions;
0106   }
0107 
0108   // find transitions that pass probability cut and add to temp container
0109   LayerIdPairs tempPairs;
0110   for (const auto& [layerPair, nTransitions] : m_layerPairs) {
0111     const std::uint32_t srcIndex = getIndexByGbtsId(layerPair.first);
0112 
0113     float probability{};
0114 
0115     if (srcTotals[srcIndex] == 0) {
0116       // avoid NAN error with 0/0
0117       probability = 0;
0118     } else {
0119       probability = static_cast<float>(nTransitions) / srcTotals[srcIndex];
0120     }
0121 
0122     const bool passCut = (m_cfg.probThreshold == -1)
0123                              ? (probability != 0)
0124                              : (probability >= m_cfg.probThreshold);
0125 
0126     if (passCut) {
0127       tempPairs.emplace(layerPair.first, layerPair.second);
0128     }
0129   }
0130 
0131   // if symmetrizing connection table, add transitions that mirror found ones
0132   if (m_cfg.doSymmetrization) {
0133     for (const auto& layerPair : tempPairs) {
0134       // find swapped ids
0135       const auto srcSwappedId = oppositeSideLayer(layerPair.first);
0136       const auto dstSwappedId = oppositeSideLayer(layerPair.second);
0137 
0138       if (!srcSwappedId || !dstSwappedId) {
0139         ACTS_WARNING("Cannot find oppisite side layer, skipping");
0140         continue;
0141       }
0142       // search set to see if swapped pair has already been added
0143       const bool notAdded =
0144           (tempPairs.count({srcSwappedId.value(), dstSwappedId.value()}) == 0);
0145 
0146       // if not already added, add to output file
0147       if (notAdded) {
0148         tempPairs.emplace(srcSwappedId.value(), dstSwappedId.value());
0149       }
0150     }
0151   }
0152 
0153   return tempPairs;
0154 }
0155 
0156 std::optional<std::int32_t> GbtsLayerConnectionTool::findGbtsIdByCoord(
0157     const HitCoordinates& hit) const {
0158   for (const auto& layer : m_cfg.detectorGeometry) {
0159     const float zMin = layer.minZ - m_cfg.zMinTol;
0160     const float zMax = layer.maxZ + m_cfg.zMaxTol;
0161     const float rMin = layer.minR - m_cfg.rMinTol;
0162     const float rMax = layer.maxR + m_cfg.rMaxTol;
0163 
0164     if (zMin <= hit.z && hit.z <= zMax) {
0165       if (rMin <= hit.r && hit.r <= rMax) {
0166         return layer.gbtsId;
0167       }
0168     }
0169   }
0170 
0171   return std::nullopt;
0172 }
0173 
0174 std::uint32_t GbtsLayerConnectionTool::getIndexByGbtsId(
0175     std::int32_t gbtsId) const {
0176   for (std::uint32_t idx = 0; idx < m_cfg.detectorGeometry.size(); idx++) {
0177     if (gbtsId == m_cfg.detectorGeometry[idx].gbtsId) {
0178       return idx;
0179     }
0180   }
0181 
0182   throw std::runtime_error("index not found for GBTS ID");
0183 }
0184 
0185 std::optional<std::int32_t> GbtsLayerConnectionTool::oppositeSideLayer(
0186     std::int32_t layerId) const {
0187   const std::uint32_t layerIndex = getIndexByGbtsId(layerId);
0188 
0189   const auto& layer = m_cfg.detectorGeometry[layerIndex];
0190 
0191   bool switchedMinZ{};
0192   bool switchedMaxZ{};
0193 
0194   bool sameMaxR{};
0195   bool sameMinR{};
0196 
0197   for (const auto& switchedLayer : m_cfg.detectorGeometry) {
0198     switchedMinZ = (switchedLayer.minZ == -layer.maxZ);
0199     switchedMaxZ = (switchedLayer.maxZ == -layer.minZ);
0200 
0201     sameMaxR = (switchedLayer.maxR == layer.maxR);
0202     sameMinR = (switchedLayer.minR == layer.minR);
0203 
0204     if (switchedMinZ && switchedMaxZ && sameMaxR && sameMinR) {
0205       return switchedLayer.gbtsId;
0206     }
0207   }
0208 
0209   return std::nullopt;
0210 }
0211 
0212 }  // namespace Acts::Experimental