File indexing completed on 2026-09-05 08:18:03
0001
0002
0003
0004
0005
0006
0007
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
0028 const std::uint32_t pairReserve = m_cfg.detectorGeometry.size();
0029 m_layerPairs.reserve(pairReserve * (pairReserve - 1));
0030
0031
0032
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
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
0056 std::vector<std::optional<std::int32_t>> layerGbtsIds{};
0057 layerGbtsIds.reserve(track.size());
0058
0059
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
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
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
0099
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
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
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
0132 if (m_cfg.doSymmetrization) {
0133 for (const auto& layerPair : tempPairs) {
0134
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
0143 const bool notAdded =
0144 (tempPairs.count({srcSwappedId.value(), dstSwappedId.value()}) == 0);
0145
0146
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 }