ATLAS Offline Software
Loading...
Searching...
No Matches
JSONDeviceDetectorDescriptionProviderSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
6
11
12#include "detray/geometry/tracking_surface.hpp"
13#include "traccc/geometry/detector.hpp"
14#include "Acts/Geometry/GeometryIdentifier.hpp"
15
16#include "traccc/io/read_detector_description.hpp"
17#include "traccc/io/read_detector.hpp"
18#include "traccc/io/data_format.hpp"
19
20#include "vecmem/utils/copy.hpp"
21
22#include <stdexcept>
23#include <algorithm>
24#include <fstream>
25#include <sstream>
26
27namespace ActsTrk {
28
30{
31 ATH_MSG_DEBUG("Initializing device detector description provider service ");
32
33 ATH_CHECK(m_MRs.retrieve());
34 ATH_CHECK(m_copy.retrieve());
35
36 auto hostDesign = std::make_unique<traccc::detector_design_description::host>(*m_MRs->hostMR());
37 auto hostCond = std::make_unique<traccc::detector_conditions_description::host>(*m_MRs->hostMR());
38
39 std::unique_ptr<traccc::detector_design_description::buffer> deviceDesign;
40 std::unique_ptr<traccc::detector_conditions_description::buffer> deviceCond;
41
42 auto copy = m_copy->copy(EventContext{});
43
44 if (m_geometryFile.value().empty() ||
45 m_digitizationFile.value().empty() ||
46 m_conditionsFile.value().empty()) {
47 ATH_MSG_FATAL("GeometryFile, " << m_geometryFile.value() <<
48 ", DigitizationFile, " << m_digitizationFile.value() << " or ConditionsFile, " << m_conditionsFile.value() << ", is empty!");
49 return StatusCode::FAILURE;
50 }
51
52 ATH_MSG_INFO("Reading detector description from files:"
53 << " geometry: " << m_geometryFile.value()
54 << ", digitization: " << m_digitizationFile.value()
55 << ", conditions: " << m_conditionsFile.value());
56
57 // Construct detector geometry
58 ATH_MSG_INFO("Loading traccc detector");
59 auto hostDetector = std::make_unique<traccc::host_detector>();
60 traccc::io::read_detector(
61 *hostDetector, *m_MRs->hostMR(),
65
66 auto deviceDetector =
67 std::make_unique<traccc::detector_buffer>(traccc::buffer_from_host_detector(*hostDetector, m_MRs->mainMR(), const_cast<vecmem::copy&>(*copy)));
68
69 ATH_CHECK(loadIdMaps(hostDetector));
70
71 // Construct detector description
72 traccc::io::read_detector_description(
73 *hostDesign, *hostCond,
77 traccc::data_format::json);
78
79 ATH_MSG_DEBUG(hostDesign->size() << " design entries, "
80 << hostCond->size() << " conditions entries");
81
82 // Copy design to device
83 std::vector<unsigned int> sizes;
84 sizes.reserve(hostDesign->size());
85 for (std::size_t i = 0; i < hostDesign->size(); ++i) {
86 const auto& e = hostDesign->at(i);
87 sizes.push_back(static_cast<unsigned int>(
88 std::max(e.bin_edges_x().size(), e.bin_edges_y().size())));
89 }
90
91 deviceDesign =
92 std::make_unique<traccc::detector_design_description::buffer>(
93 sizes, m_MRs->mainMR(), m_MRs->hostMR(),
94 vecmem::data::buffer_type::resizable);
95 (*copy).setup(*deviceDesign)->wait();
96 (*copy)(vecmem::get_data(*hostDesign), *deviceDesign)->wait();
97
98 // Copy conditions to device
99 deviceCond =
100 std::make_unique<traccc::detector_conditions_description::buffer>(
101 static_cast<traccc::detector_conditions_description::buffer::size_type>(
102 hostCond->size()),
103 m_MRs->mainMR());
104 (*copy).setup(*deviceCond)->wait();
105 (*copy)(vecmem::get_data(*hostCond), *deviceCond)->wait();
106
107 ATH_MSG_INFO("Detector description built from files");
108
109 // Record device and host objects
110 // Host objects are needed for EDM conversions
111 constexpr bool allowMods = false;
112 ATH_CHECK(m_detStore->record(std::move(deviceDesign), m_deviceDesignObjectName.value(), allowMods));
113 ATH_CHECK(m_detStore->record(std::move(deviceCond), m_deviceCondObjectName.value(), allowMods));
114 ATH_CHECK(m_detStore->record(std::move(hostDesign), m_hostDesignObjectName.value(), allowMods));
115 ATH_CHECK(m_detStore->record(std::move(hostCond), m_hostCondObjectName.value(), allowMods));
116
117 ATH_CHECK(m_detStore->record(std::move(deviceDetector), m_deviceDetectorName.value(), allowMods));
118 ATH_CHECK(m_detStore->record(std::move(hostDetector), m_hostDetectorName.value(), allowMods));
119
120 ATH_MSG_DEBUG("Successfully initialized");
121 return StatusCode::SUCCESS;
122}
123
124StatusCode JSONDeviceDetectorDescriptionProviderSvc::loadIdMaps(const std::unique_ptr<traccc::host_detector>& hostDetector)
125{
126 if (m_mapFile.value().empty()) {
127 ATH_MSG_FATAL("MapFile not set — detray<->Athena maps will be empty");
128 return StatusCode::FAILURE;
129 }
130
131 ATH_MSG_INFO("Loading detray<->Athena map from "
132 << m_mapFile.value());
133 std::ifstream mapFile(PathResolverFindCalibFile(m_mapFile.value()));
134 if (!mapFile.is_open()) {
135 ATH_MSG_FATAL("Cannot open map file: " << m_mapFile.value());
136 return StatusCode::FAILURE;
137 }
138
139 // Pass 1: the Athena <-> detray map
140 // Fill it into a temporary lookup keyed by detray id.
141 std::unordered_map<uint64_t, Identifier> detrayToAthenaFromFile;
142
143 std::string line;
144 while (std::getline(mapFile, line)) {
145 if (line.empty()) continue;
146 std::stringstream ss(line);
147 std::string athenaStr, detrayStr;
148 if (!std::getline(ss, athenaStr, ',') ||
149 !std::getline(ss, detrayStr, ',')) continue;
150
151 if (athenaStr.empty()) {
152 ATH_MSG_ERROR("Empty Athena identifier string in map file — skipping");
153 return StatusCode::FAILURE;
154 }
155
156 Identifier athenaId;
157 athenaId.set(athenaStr); // handles the 0x-prefixed hex correctly
158
159 uint64_t detrayId = 0;
160 try {
161 detrayId = std::stoull(detrayStr);
162 } catch (const std::exception& e) {
163 ATH_MSG_ERROR("Failed to parse detray identifier '" << detrayStr << "': " << e.what());
164 return StatusCode::FAILURE;
165 }
166
167 detrayToAthenaFromFile.emplace(detrayId, athenaId);
168 }
169
170 ATH_MSG_INFO("Read " << detrayToAthenaFromFile.size()
171 << " detray<->Athena entries from file");
172
173 // Pass 2: walk the detray surfaces, read off the ACTS geometry id
174 // and combine with the file-based Athena lookup to fill the
175 // full three-way GeometryIdMapping.
176 m_idMapping = std::make_unique<ActsTrk::GeometryIdMapping>();
177 const auto& itkDetector = hostDetector->as<traccc::itk_detector>();
178 const std::size_t nSurfaces = itkDetector.surfaces().size();
179 m_idMapping->reserve(nSurfaces);
180
181 std::size_t nMatched = 0;
182 for (const auto& surface : itkDetector.surfaces()) {
183 const Acts::GeometryIdentifier acts_geom_id{surface.source};
184
185 auto sf = detray::tracking_surface{itkDetector, surface};
186 const auto detrayId = sf.identifier().value();
187
188 std::optional<Identifier> athenaId;
189 if (auto it = detrayToAthenaFromFile.find(detrayId);
190 it != detrayToAthenaFromFile.end()) {
191 athenaId = it->second;
192 ++nMatched;
193 }
194
195 m_idMapping->addEntry(detrayId, acts_geom_id.value(), athenaId);
196 }
197
198 ATH_MSG_INFO("Built GeometryIdMapping with " << m_idMapping->size()
199 << " detray/ACTS surfaces, " << nMatched
200 << " matched to an Athena module");
201
202 ATH_CHECK(m_detStore->record(std::move(m_idMapping), m_geoIdMappingObjectName.value(), false));
203
204 return StatusCode::SUCCESS;
205}
206
207} // namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
static Double_t ss
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
ToolHandle< AthDevice::ICopyTool > m_copy
The copy tool used for copying data to device.
virtual StatusCode initialize() override
Function initializing and executing the file loading.
StatusCode loadIdMaps(const std::unique_ptr< traccc::host_detector > &hostDetector)
Helper function to load Athena<->detray ID maps from csv.
void set(std::string_view id)
build from a string form - hexadecimal
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...