Warning, file /acts/Examples/Io/Csv/src/CsvMeasurementReader.cpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Csv/CsvMeasurementReader.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/Geometry/GeometryIdentifier.hpp"
0014 #include "ActsExamples/Digitization/MeasurementCreation.hpp"
0015 #include "ActsExamples/EventData/Cluster.hpp"
0016 #include "ActsExamples/EventData/GeometryContainers.hpp"
0017 #include "ActsExamples/EventData/Measurement.hpp"
0018 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0019 #include "ActsExamples/Io/Csv/CsvInputOutput.hpp"
0020 #include "ActsExamples/Utilities/Paths.hpp"
0021
0022 #include <algorithm>
0023 #include <array>
0024 #include <cstdint>
0025 #include <iterator>
0026 #include <stdexcept>
0027 #include <vector>
0028
0029 #include "CsvOutputData.hpp"
0030
0031 namespace ActsExamples {
0032
0033 CsvMeasurementReader::CsvMeasurementReader(const Config& config,
0034 Acts::Logging::Level level)
0035 : m_cfg(config),
0036 m_eventsRange(
0037 determineEventFilesRange(m_cfg.inputDir, "measurements.csv")),
0038 m_logger(Acts::getDefaultLogger("CsvMeasurementReader", level)) {
0039 if (m_cfg.outputMeasurements.empty()) {
0040 throw std::invalid_argument("Missing measurement output collection");
0041 }
0042
0043 m_outputMeasurements.initialize(m_cfg.outputMeasurements);
0044 m_outputMeasurementSimHitsMap.initialize(m_cfg.outputMeasurementSimHitsMap);
0045 m_outputClusters.maybeInitialize(m_cfg.outputClusters);
0046 m_outputMeasurementParticlesMap.maybeInitialize(
0047 m_cfg.outputMeasurementParticlesMap);
0048 m_inputHits.maybeInitialize(m_cfg.inputSimHits);
0049
0050
0051 auto checkRange = [&](const std::string& fileStem) {
0052 const auto hitmapRange = determineEventFilesRange(m_cfg.inputDir, fileStem);
0053 if (hitmapRange.first > m_eventsRange.first ||
0054 hitmapRange.second < m_eventsRange.second) {
0055 throw std::runtime_error("event range mismatch for 'event**-" + fileStem +
0056 "'");
0057 }
0058 };
0059
0060 checkRange("measurement-simhit-map.csv");
0061 if (!m_cfg.outputClusters.empty()) {
0062 checkRange("cells.csv");
0063 }
0064 }
0065
0066 std::string CsvMeasurementReader::CsvMeasurementReader::name() const {
0067 return "CsvMeasurementReader";
0068 }
0069
0070 std::pair<std::size_t, std::size_t> CsvMeasurementReader::availableEvents()
0071 const {
0072 return m_eventsRange;
0073 }
0074
0075 namespace {
0076 struct CompareHitId {
0077
0078 using is_transparent = void;
0079 template <typename T>
0080 constexpr bool operator()(const T& left, const T& right) const {
0081 return left.hit_id < right.hit_id;
0082 }
0083 template <typename T>
0084 constexpr bool operator()(std::uint64_t left_id, const T& right) const {
0085 return left_id < right.hit_id;
0086 }
0087 template <typename T>
0088 constexpr bool operator()(const T& left, std::uint64_t right_id) const {
0089 return left.hit_id < right_id;
0090 }
0091 };
0092
0093 struct CompareGeometryId {
0094 bool operator()(const MeasurementData& left,
0095 const MeasurementData& right) const {
0096 return left.geometry_id < right.geometry_id;
0097 }
0098 };
0099
0100 template <typename Data>
0101 inline std::vector<Data> readEverything(
0102 const std::string& inputDir, const std::string& filename,
0103 const std::vector<std::string>& optionalColumns, std::size_t event) {
0104 std::string path = perEventFilepath(inputDir, filename, event);
0105 BoostDescribeCsvReader<Data> reader(path, optionalColumns);
0106
0107 std::vector<Data> everything;
0108 Data one;
0109 while (reader.read(one)) {
0110 everything.push_back(one);
0111 }
0112
0113 return everything;
0114 }
0115
0116 std::vector<MeasurementData> readMeasurementsByGeometryId(
0117 const std::string& inputDir, std::size_t event) {
0118
0119 auto measurements = readEverything<MeasurementData>(
0120 inputDir, "measurements.csv", {"geometry_id", "t"}, event);
0121
0122 std::ranges::sort(measurements, CompareGeometryId{});
0123 return measurements;
0124 }
0125
0126 ClusterContainer makeClusters(
0127 const std::unordered_multimap<std::size_t, CellData>& cellDataMap,
0128 std::size_t nMeasurements) {
0129 using namespace ActsExamples;
0130 ClusterContainer clusters;
0131
0132 for (auto index = 0ul; index < nMeasurements; ++index) {
0133 auto [begin, end] = cellDataMap.equal_range(index);
0134
0135
0136 Cluster cluster;
0137 cluster.channels.reserve(std::distance(begin, end));
0138
0139 for (auto it = begin; it != end; ++it) {
0140 const auto& cellData = it->second;
0141 ActsFatras::Segmentizer::Segment2D dummySegment = {Acts::Vector2::Zero(),
0142 Acts::Vector2::Zero()};
0143
0144 ActsFatras::Segmentizer::Bin2D bin{
0145 static_cast<unsigned int>(cellData.channel0),
0146 static_cast<unsigned int>(cellData.channel1)};
0147
0148 cluster.channels.emplace_back(bin, dummySegment, cellData.value);
0149 }
0150
0151
0152
0153
0154 if (!cluster.channels.empty()) {
0155 auto compareX = [](const auto& a, const auto& b) {
0156 return a.bin[0] < b.bin[0];
0157 };
0158 auto compareY = [](const auto& a, const auto& b) {
0159 return a.bin[1] < b.bin[1];
0160 };
0161
0162 auto [minX, maxX] = std::minmax_element(cluster.channels.begin(),
0163 cluster.channels.end(), compareX);
0164 auto [minY, maxY] = std::minmax_element(cluster.channels.begin(),
0165 cluster.channels.end(), compareY);
0166 cluster.sizeLoc0 = 1 + maxX->bin[0] - minX->bin[0];
0167 cluster.sizeLoc1 = 1 + maxY->bin[1] - minY->bin[1];
0168 }
0169
0170 clusters.push_back(cluster);
0171 }
0172 return clusters;
0173 }
0174
0175 }
0176
0177 ProcessCode CsvMeasurementReader::read(const AlgorithmContext& ctx) {
0178
0179
0180
0181
0182
0183
0184
0185 auto measurementData =
0186 readMeasurementsByGeometryId(m_cfg.inputDir, ctx.eventNumber);
0187
0188
0189 MeasurementContainer tmpMeasurements;
0190 GeometryIdMultimap<ConstVariableBoundMeasurementProxy> orderedMeasurements;
0191 MeasurementSimHitsMap measurementSimHitsMap;
0192
0193 tmpMeasurements.reserve(measurementData.size());
0194 orderedMeasurements.reserve(measurementData.size());
0195
0196 measurementSimHitsMap.reserve(measurementData.size());
0197
0198 auto measurementSimHitLinkData = readEverything<MeasurementSimHitLink>(
0199 m_cfg.inputDir, "measurement-simhit-map.csv", {}, ctx.eventNumber);
0200 for (auto mshLink : measurementSimHitLinkData) {
0201 measurementSimHitsMap.emplace_hint(measurementSimHitsMap.end(),
0202 mshLink.measurement_id, mshLink.hit_id);
0203 }
0204
0205 for (const MeasurementData& m : measurementData) {
0206 Acts::GeometryIdentifier geoId{m.geometry_id};
0207
0208
0209 DigitizedParameters dParameters;
0210 for (unsigned int ipar = 0;
0211 ipar < static_cast<unsigned int>(Acts::eBoundSize); ++ipar) {
0212 if (((m.local_key) & (1 << (ipar + 1))) != 0) {
0213 dParameters.indices.push_back(static_cast<Acts::BoundIndices>(ipar));
0214 switch (ipar) {
0215 case static_cast<unsigned int>(Acts::eBoundLoc0): {
0216 dParameters.values.push_back(m.local0);
0217 dParameters.variances.push_back(m.var_local0);
0218 }; break;
0219 case static_cast<unsigned int>(Acts::eBoundLoc1): {
0220 dParameters.values.push_back(m.local1);
0221 dParameters.variances.push_back(m.var_local1);
0222 }; break;
0223 case static_cast<unsigned int>(Acts::eBoundPhi): {
0224 dParameters.values.push_back(m.phi);
0225 dParameters.variances.push_back(m.var_phi);
0226 }; break;
0227 case static_cast<unsigned int>(Acts::eBoundTheta): {
0228 dParameters.values.push_back(m.theta);
0229 dParameters.variances.push_back(m.var_theta);
0230 }; break;
0231 case static_cast<unsigned int>(Acts::eBoundTime): {
0232 dParameters.values.push_back(m.time);
0233 dParameters.variances.push_back(m.var_time);
0234 }; break;
0235 default:
0236 break;
0237 }
0238 }
0239 }
0240
0241
0242
0243 auto measurement = createMeasurement(tmpMeasurements, geoId, dParameters);
0244
0245
0246
0247
0248
0249 auto inserted = orderedMeasurements.emplace_hint(orderedMeasurements.end(),
0250 geoId, measurement);
0251 if (std::next(inserted) != orderedMeasurements.end()) {
0252 ACTS_FATAL("Something went horribly wrong with the hit sorting");
0253 return ProcessCode::ABORT;
0254 }
0255 }
0256
0257 MeasurementContainer measurements;
0258 for (auto& [_, meas] : orderedMeasurements) {
0259 measurements.emplaceMeasurement(meas.size(), meas.geometryId(), meas);
0260 }
0261
0262
0263 if (m_inputHits.isInitialized() &&
0264 m_outputMeasurementParticlesMap.isInitialized()) {
0265 const auto hits = m_inputHits(ctx);
0266
0267 MeasurementParticlesMap outputMap;
0268
0269 for (const auto& [measIdx, hitIdx] : measurementSimHitsMap) {
0270 const auto& hit = hits.nth(hitIdx);
0271 outputMap.emplace(measIdx, hit->particleId());
0272 }
0273
0274 m_outputMeasurementParticlesMap(ctx, std::move(outputMap));
0275 }
0276
0277
0278 m_outputMeasurements(ctx, std::move(measurements));
0279 m_outputMeasurementSimHitsMap(ctx, std::move(measurementSimHitsMap));
0280
0281
0282
0283
0284
0285 if (m_cfg.outputClusters.empty()) {
0286 return ProcessCode::SUCCESS;
0287 }
0288
0289 std::vector<CellData> cellData;
0290
0291
0292
0293 try {
0294 cellData = readEverything<CellData>(m_cfg.inputDir, "cells.csv",
0295 {"timestamp"}, ctx.eventNumber);
0296 } catch (std::runtime_error& e) {
0297
0298 if (std::string(e.what()).find("Missing header column 'measurement_id'") ==
0299 std::string::npos) {
0300 throw;
0301 }
0302
0303 const auto oldCellData = readEverything<CellDataLegacy>(
0304 m_cfg.inputDir, "cells.csv", {"timestamp"}, ctx.eventNumber);
0305
0306 auto fromLegacy = [](const CellDataLegacy& old) {
0307 return CellData{old.geometry_id, old.hit_id, old.channel0,
0308 old.channel1, old.timestamp, old.value};
0309 };
0310
0311 cellData.resize(oldCellData.size());
0312 std::transform(oldCellData.begin(), oldCellData.end(), cellData.begin(),
0313 fromLegacy);
0314 }
0315
0316 std::unordered_multimap<std::size_t, CellData> cellDataMap;
0317 for (const auto& cd : cellData) {
0318 cellDataMap.emplace(cd.measurement_id, cd);
0319 }
0320
0321 auto clusters = makeClusters(cellDataMap, orderedMeasurements.size());
0322 m_outputClusters(ctx, std::move(clusters));
0323
0324 return ProcessCode::SUCCESS;
0325 }
0326
0327 }