ATLAS Offline Software
Loading...
Searching...
No Matches
xAODToTracccMeasurementConverterAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5
8
11
12#include <algorithm>
13#include <limits>
14#include <memory>
15#include <numeric>
16
17namespace ActsTrk {
18
20{
21 ATH_MSG_DEBUG("Initializing.");
22
25
26 ATH_CHECK(m_outputMeasKey.initialize());
29
30 ATH_CHECK(m_MRs.retrieve());
31 ATH_CHECK(m_copiesTool.retrieve());
32
33 ATH_CHECK(detStore()->retrieve(m_pixelID, "PixelID"));
34 ATH_CHECK(detStore()->retrieve(m_stripID, "SCT_ID"));
38
39 // NOTE: m_detrayIdToCondIndex is built once here;
40 // meaning it is only valid as long as the geometry does not change.
41 const auto& gids = m_hostCond->geometry_id();
42 m_detrayIdToCondIndex.reserve(gids.size());
43 for (unsigned int i = 0; i < gids.size(); ++i) {
44 m_detrayIdToCondIndex[gids[i].value()] = i;
45 }
46 ATH_MSG_INFO("Built detray->detcond map with "
47 << m_detrayIdToCondIndex.size() << " entries");
48
49 ATH_MSG_DEBUG("Successfully initialized");
50 return StatusCode::SUCCESS;
51}
52
54 const Identifier& moduleId, unsigned int& condIndex) const
55{
56 const auto detrayIdOpt = m_geoIdMapping->athenaToDetray(moduleId);
57 if (!detrayIdOpt.has_value()) {
58 ATH_MSG_ERROR("No detray id found for Athena identifier " << moduleId);
59 return StatusCode::FAILURE;
60 }
61 const auto it = m_detrayIdToCondIndex.find(*detrayIdOpt);
62 if (it == m_detrayIdToCondIndex.end()) {
63 ATH_MSG_ERROR("No detray conditions entry found for detray id " << *detrayIdOpt);
64 return StatusCode::FAILURE;
65 }
66 condIndex = it->second;
67 return StatusCode::SUCCESS;
68}
69
70StatusCode xAODToTracccMeasurementConverterAlg::execute(const EventContext& ctx) const
71{
72 using size_type = traccc::edm::measurement_collection::buffer::size_type;
73 constexpr unsigned int invalidIndex = std::numeric_limits<unsigned int>::max();
74
75 auto pixelClusters = SG::makeHandle(m_inputPixelClustersKey, ctx);
76 ATH_CHECK(pixelClusters.isValid());
77 auto stripClusters = SG::makeHandle(m_inputStripClustersKey, ctx);
78 ATH_CHECK(stripClusters.isValid());
79
80 const unsigned int nPixel = pixelClusters->size();
81 const unsigned int nStrip = stripClusters->size();
82 const size_type nMeas = nPixel + nStrip;
83 ATH_MSG_DEBUG("Found " << nPixel << " pixel clusters and " << nStrip
84 << " strip clusters, total " << nMeas << " clusters");
85
86 std::vector<MeasurementRecord> records;
87 records.reserve(nMeas);
88
89 for (const xAOD::PixelCluster* cl : *pixelClusters) {
91 rec.isPixel = true;
92 rec.hostIndex = cl->index();
93 const Identifier moduleId = m_pixelID->wafer_id(IdentifierHash{cl->identifierHash()});
94 ATH_CHECK(condIndexFor(moduleId, rec.condIndex));
95 rec.geometryId = m_hostCond->geometry_id()[rec.condIndex].value();
96 const auto locPos = cl->localPosition<2>();
97 const auto locCov = cl->localCovariance<2>();
98 rec.localPosition = {locPos(0, 0), locPos(1, 0)};
99 rec.localVariance = {locCov(0, 0), locCov(1, 1)};
100 rec.diameter = cl->widthInEta();
101 records.push_back(rec);
102 }
103
104 for (const xAOD::StripCluster* cl : *stripClusters) {
106 rec.isPixel = false;
107 rec.hostIndex = cl->index();
108 const Identifier moduleId = m_stripID->wafer_id(IdentifierHash{cl->identifierHash()});
109 ATH_CHECK(condIndexFor(moduleId, rec.condIndex));
110 rec.geometryId = m_hostCond->geometry_id()[rec.condIndex].value();
111
112 // The measured coordinate is given by the module subspace, the other
113 // coordinate is set to the centre of the module design
114 const unsigned int designIdx = m_hostCond->module_to_design_id()[rec.condIndex];
115 const unsigned int measuredAxis = static_cast<unsigned int>(m_hostDesign->subspace()[designIdx][0]);
116 const unsigned int otherAxis = (measuredAxis == 0u) ? 1u : 0u;
117 const auto& otherEdges = (otherAxis == 0u) ? m_hostDesign->bin_edges_x()[designIdx]
118 : m_hostDesign->bin_edges_y()[designIdx];
119 float otherCentre = 0.f;
120 float otherVariance = 0.f;
121 if (!otherEdges.empty()) {
122 const float width = otherEdges.back() - otherEdges.front();
123 otherCentre = 0.5f * (otherEdges.front() + otherEdges.back());
124 otherVariance = width * width / 12.f;
125 }
126
127 const auto locPos = cl->localPosition<1>();
128 const auto locCov = cl->localCovariance<1>();
129 rec.localPosition[measuredAxis] = locPos(0, 0);
130 rec.localVariance[measuredAxis] = locCov(0, 0);
131 rec.localPosition[otherAxis] = otherCentre;
132 rec.localVariance[otherAxis] = otherVariance;
133 records.push_back(rec);
134 }
135
136 // The traccc track finding requires the measurements to be sorted by surface
137 std::vector<unsigned int> order(records.size());
138 std::iota(order.begin(), order.end(), 0u);
139 std::sort(order.begin(), order.end(), [&records](unsigned int lhs, unsigned int rhs) {
140 const MeasurementRecord& a = records[lhs];
141 const MeasurementRecord& b = records[rhs];
142 if (a.geometryId != b.geometryId) return a.geometryId < b.geometryId;
143 if (a.localPosition[0] != b.localPosition[0]) return a.localPosition[0] < b.localPosition[0];
144 return a.localPosition[1] < b.localPosition[1];
145 });
146
147 std::pmr::memory_resource* hostMR = m_MRs->hostMR();
148 auto hostCopy = m_copiesTool->hostCopy(ctx);
149 auto measHostBuffer = std::make_unique<traccc::edm::measurement_collection::buffer>(
150 nMeas, hostMR ? *hostMR : m_MRs->mainMR());
151 hostCopy->setup(*measHostBuffer)->wait();
152
153 // Create a "device" collection around the buffer to work on it
154 traccc::edm::measurement_collection::device measurements{*measHostBuffer};
155
156 auto measToPixel = std::make_unique<std::vector<unsigned int>>(nMeas, invalidIndex);
157 auto measToStrip = std::make_unique<std::vector<unsigned int>>(nMeas, invalidIndex);
158
159 // The traccc buffers are not default initialized: all members must be set.
160 for (size_type i = 0; i < nMeas; ++i) {
161 const MeasurementRecord& rec = records[order[i]];
162 const unsigned int designIdx = m_hostCond->module_to_design_id()[rec.condIndex];
163
164 auto meas = measurements.at(i);
165 meas.local_position() = rec.localPosition;
166 meas.local_variance() = rec.localVariance;
167 meas.dimensions() = static_cast<unsigned int>(m_hostDesign->dimensions()[designIdx]);
168 meas.time() = 0.f;
169 meas.diameter() = rec.diameter;
170 meas.identifier() = i;
171 meas.surface_link() = m_hostCond->geometry_id()[rec.condIndex];
172 meas.set_subspace(m_hostDesign->subspace()[designIdx]);
173 meas.cluster_index() = rec.hostIndex;
174
175 if (rec.isPixel) {
176 (*measToPixel)[i] = rec.hostIndex;
177 } else {
178 (*measToStrip)[i] = rec.hostIndex;
179 }
180 }
181
182 auto measHandle = SG::makeHandle(m_outputMeasKey, ctx);
183 if (hostMR) {
184 auto deviceCopy = m_copiesTool->deviceCopy(ctx);
185 auto measDeviceBuffer = std::make_unique<traccc::edm::measurement_collection::buffer>(
186 measHostBuffer->capacity(), m_MRs->mainMR());
187
188 // We ignore() the setup and wait() on the copy to allow parallelism.
189 deviceCopy->setup(*measDeviceBuffer)->ignore();
190 (*deviceCopy)(*measHostBuffer, *measDeviceBuffer)->wait();
191 ATH_CHECK(measHandle.record(std::move(measDeviceBuffer)));
192 } else {
193 ATH_CHECK(measHandle.record(std::move(measHostBuffer)));
194 }
195
196 auto measToPixelHandle = SG::makeHandle(m_outputMeasToPixelKey, ctx);
197 ATH_CHECK(measToPixelHandle.record(std::move(measToPixel)));
198 auto measToStripHandle = SG::makeHandle(m_outputMeasToStripKey, ctx);
199 ATH_CHECK(measToStripHandle.record(std::move(measToStrip)));
200
201 m_nPixel += nPixel;
202 m_nStrip += nStrip;
203
204 ATH_MSG_DEBUG("Wrote " << nMeas << " measurements to '"
205 << m_outputMeasKey.key() << "'");
206 return StatusCode::SUCCESS;
207}
208
210{
211 ATH_MSG_DEBUG("Finalizing.");
212
213 ATH_MSG_INFO("Converted total number of pixel clusters = " << m_nPixel
214 << " and total number of strip clusters = " << m_nStrip);
215
216 return StatusCode::SUCCESS;
217}
218
219} // 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,...)
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
const double width
StatusCode condIndexFor(const Identifier &moduleId, unsigned int &condIndex) const
Look up the traccc conditions index for an Athena module identifier.
ToolHandle< AthDevice::IMemoryResourcesTool > m_MRs
virtual StatusCode finalize() override
Function finalizing the algorithm.
SG::ReadHandleKey< xAOD::StripClusterContainer > m_inputStripClustersKey
virtual StatusCode initialize() override
Function initializing the algorithm.
SG::WriteHandleKey< std::vector< unsigned int > > m_outputMeasToPixelKey
SG::ReadHandleKey< xAOD::PixelClusterContainer > m_inputPixelClustersKey
std::unordered_map< std::uint64_t, unsigned int > m_detrayIdToCondIndex
SG::WriteHandleKey< traccc::edm::measurement_collection::buffer > m_outputMeasKey
const traccc::detector_design_description::host * m_hostDesign
SG::WriteHandleKey< std::vector< unsigned int > > m_outputMeasToStripKey
const traccc::detector_conditions_description::host * m_hostCond
virtual StatusCode execute(const EventContext &ctx) const override
Function executing the algorithm.
std::atomic< unsigned long > m_nPixel
The object counters for debug prints in finalize method {.
const ServiceHandle< StoreGateSvc > & detStore() const
This is a "hash" representation of an Identifier.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
PixelCluster_v1 PixelCluster
Define the version of the pixel cluster class.
Host side description of a measurement before it is written to the traccc collection.