41 : ActsExamples::
IAlgorithm(
"DigitizationAlgorithm", level),
44 throw std::invalid_argument(
"Missing simulated hits input collection");
47 throw std::invalid_argument(
"Missing measurements output collection");
50 throw std::invalid_argument(
"Missing source links output collection");
53 throw std::invalid_argument(
54 "Missing hit-to-particles map output collection");
57 throw std::invalid_argument(
58 "Missing hit-to-simulated-hits map output collection");
61 throw std::invalid_argument(
"Missing tracking geometry");
64 throw std::invalid_argument(
"Missing random numbers tool");
68 throw std::invalid_argument(
"Missing digitization configuration");
81 std::vector<std::pair<Acts::GeometryIdentifier, Digitizer>> digitizerInput;
88 geoCfg = digiCfg.geometricDigiConfig;
92 std::vector<Acts::BoundIndices> indices;
93 for (
auto&
gcf : smCfg) {
94 indices.push_back(
gcf.index);
96 indices.insert(indices.begin(), geoCfg.
indices.begin(),
100 std::sort(indices.begin(), indices.end());
102 auto dup = std::adjacent_find(indices.begin(), indices.end());
103 if (dup != indices.end()) {
104 std::invalid_argument(
105 "Digitization configuration contains duplicate parameter indices");
108 switch (smCfg.size()) {
110 digitizerInput.emplace_back(geoId, makeDigitizer<0u>(digiCfg));
113 digitizerInput.emplace_back(geoId, makeDigitizer<1u>(digiCfg));
116 digitizerInput.emplace_back(geoId, makeDigitizer<2u>(digiCfg));
119 digitizerInput.emplace_back(geoId, makeDigitizer<3u>(digiCfg));
122 digitizerInput.emplace_back(geoId, makeDigitizer<4u>(digiCfg));
125 throw std::invalid_argument(
"Unsupported smearer size");
135 const auto& simHits = m_simContainerReadHandle(ctx);
136 ACTS_DEBUG(
"Loaded " << simHits.size() <<
" sim hits");
145 sourceLinks.reserve(simHits.size());
146 measurements.reserve(simHits.size());
147 measurementParticlesMap.reserve(simHits.size());
148 measurementSimHitsMap.reserve(simHits.size());
151 auto rng =
m_cfg.randomNumbers->spawnGenerator(ctx);
154 std::size_t skippedHits = 0;
163 const auto& moduleSimHits = simHitsGroup.second;
166 m_cfg.trackingGeometry->findSurface(moduleGeoId);
168 if (surfacePtr ==
nullptr) {
171 ACTS_ERROR(
"Could not find surface " << moduleGeoId
172 <<
" for configured smearer");
173 return ProcessCode::ABORT;
176 auto digitizerItr = m_digitizers.find(moduleGeoId);
177 if (digitizerItr == m_digitizers.end()) {
178 ACTS_VERBOSE(
"No digitizer present for module " << moduleGeoId);
181 ACTS_VERBOSE(
"Digitizer found for module " << moduleGeoId);
187 [&](
const auto& digitizer) {
189 digitizer.geometric.segmentation, digitizer.geometric.indices,
192 for (
auto h = moduleSimHits.begin();
h != moduleSimHits.end(); ++
h) {
193 const auto& simHit = *
h;
194 const auto simHitIdx = simHits.index_of(
h);
198 if (simHit.depositedEnergy() <
m_cfg.minEnergyDeposit) {
199 ACTS_VERBOSE(
"Skip hit because energy deposit to small")
204 if (not digitizer.geometric.indices.empty()) {
206 << digitizer.geometric.indices.size()
208 auto channels = channelizing(digitizer.geometric, simHit,
210 if (channels.empty()) {
212 "Geometric channelization did not work, skipping this hit.")
216 <<
" channels for this hit.");
217 dParameters = localParameters(digitizer.geometric, channels,
rng);
221 if (not digitizer.smearing.indices.empty()) {
223 << digitizer.smearing.indices.size()
226 digitizer.smearing(
rng, simHit, *surfacePtr, ctx.
geoContext);
229 ACTS_DEBUG(
"Problem in hit smearing, skip hit ("
230 << res.error().message() <<
")");
233 const auto& [par,
cov] = res.value();
235 dParameters.
indices.push_back(digitizer.smearing.indices[ip]);
236 dParameters.
values.push_back(par[ip]);
242 if (dParameters.
values.empty()) {
244 "Parameter digitization did not yield a measurement.")
251 for (
auto& [dParameters, simhits] :
255 Index measurementIdx = measurements.size();
262 sourceLinks.insert(sourceLinks.end(), sourceLink);
264 measurements.emplace_back(
266 clusters.emplace_back(
std::move(dParameters.cluster));
269 for (
auto simHitIdx : simhits) {
270 measurementParticlesMap.emplace_hint(
271 measurementParticlesMap.end(), measurementIdx,
272 simHits.nth(simHitIdx)->particleId());
273 measurementSimHitsMap.emplace_hint(measurementSimHitsMap.end(),
274 measurementIdx, simHitIdx);
281 if (skippedHits > 0) {
284 <<
" skipped in Digitization. Enable DEBUG mode to see more details.");
287 m_sourceLinkWriteHandle(ctx,
std::move(sourceLinks));
288 m_measurementWriteHandle(ctx,
std::move(measurements));
289 m_clusterWriteHandle(ctx,
std::move(clusters));
290 m_measurementParticlesMapWriteHandle(ctx,
std::move(measurementParticlesMap));
291 m_measurementSimHitsMapWriteHandle(ctx,
std::move(measurementSimHitsMap));
295 std::vector<ActsFatras::Channelizer::ChannelSegment>
302 auto driftedSegment =
305 auto maskedSegmentRes = m_surfaceMask.apply(surface, driftedSegment);
306 if (maskedSegmentRes.ok()) {
307 auto maskedSegment = maskedSegmentRes.value();
309 return m_channelizer.segments(gctx, surface, geoCfg.
segmentation,
318 const std::vector<ActsFatras::Channelizer::ChannelSegment>& channels,
326 size_t b0min = SIZE_MAX;
328 size_t b1min = SIZE_MAX;
331 for (
const auto& ch : channels) {
340 charge * binningData[1].center(b1));
342 b0max = std::max(b0max, b0);
344 b1max = std::max(b1max, b1);
348 chdig.activation =
charge;
352 if (totalWeight > 0.) {
353 m *= 1. / totalWeight;
358 size_t size0 =
static_cast<size_t>(b0max - b0min + 1);
359 size_t size1 =
static_cast<size_t>(b1max - b1min + 1);
360 auto variances = geoCfg.
variances(size0, size1, rng);
361 if (variances.size() == dParameters.
indices.size()) {
365 std::vector<Acts::ActsScalar>(dParameters.
indices.size(), -1.);
369 size_t ictr = b0min + size0 / 2;
370 dParameters.
variances[0] = std::pow(binningData[0].
width(ictr), 2) / 12.0;
373 size_t ictr = b1min + size1 / 2;
374 dParameters.
variances[1] = std::pow(binningData[1].
width(ictr), 2) / 12.0;