File indexing completed on 2025-08-06 08:10:47
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Csv/CsvSeedWriter.hpp"
0010
0011 #include "Acts/EventData/TrackParameters.hpp"
0012 #include "Acts/Seeding/Seed.hpp"
0013 #include "Acts/Utilities/Helpers.hpp"
0014 #include "ActsExamples/EventData/AverageSimHits.hpp"
0015 #include "ActsExamples/EventData/Index.hpp"
0016 #include "ActsExamples/EventData/Measurement.hpp"
0017 #include "ActsExamples/EventData/SimHit.hpp"
0018 #include "ActsExamples/EventData/SimParticle.hpp"
0019 #include "ActsExamples/EventData/SimSeed.hpp"
0020 #include "ActsExamples/Utilities/EventDataTransforms.hpp"
0021 #include "ActsExamples/Utilities/Paths.hpp"
0022 #include "ActsExamples/Utilities/Range.hpp"
0023 #include "ActsExamples/Validation/TrackClassification.hpp"
0024
0025 #include <ios>
0026 #include <iostream>
0027 #include <stdexcept>
0028 #include <string>
0029 #include <unordered_map>
0030 #include <unordered_set>
0031
0032 using Acts::VectorHelpers::eta;
0033 using Acts::VectorHelpers::phi;
0034 using Acts::VectorHelpers::theta;
0035
0036 ActsExamples::CsvSeedWriter::CsvSeedWriter(
0037 const ActsExamples::CsvSeedWriter::Config& config,
0038 Acts::Logging::Level level)
0039 : WriterT<TrackParametersContainer>(config.inputTrackParameters,
0040 "CsvSeedWriter", level),
0041 m_cfg(config) {
0042 if (m_cfg.inputSimSeeds.empty()) {
0043 throw std::invalid_argument("Missing space points input collection");
0044 }
0045 if (m_cfg.inputSimHits.empty()) {
0046 throw std::invalid_argument("Missing simulated hits input collection");
0047 }
0048 if (m_cfg.inputMeasurementParticlesMap.empty()) {
0049 throw std::invalid_argument("Missing hit-particles map input collection");
0050 }
0051 if (m_cfg.inputMeasurementSimHitsMap.empty()) {
0052 throw std::invalid_argument(
0053 "Missing hit-simulated-hits map input collection");
0054 }
0055 if (m_cfg.fileName.empty()) {
0056 throw std::invalid_argument("Missing output filename");
0057 }
0058 if (m_cfg.outputDir.empty()) {
0059 throw std::invalid_argument("Missing output directory");
0060 }
0061
0062 m_inputSimSeeds.initialize(m_cfg.inputSimSeeds);
0063 m_inputSimHits.initialize(m_cfg.inputSimHits);
0064 m_inputMeasurementParticlesMap.initialize(m_cfg.inputMeasurementParticlesMap);
0065 m_inputMeasurementSimHitsMap.initialize(m_cfg.inputMeasurementSimHitsMap);
0066 }
0067
0068 ActsExamples::ProcessCode ActsExamples::CsvSeedWriter::writeT(
0069 const ActsExamples::AlgorithmContext& ctx,
0070 const TrackParametersContainer& trackParams) {
0071
0072 const auto& seeds = m_inputSimSeeds(ctx);
0073 const auto& simHits = m_inputSimHits(ctx);
0074 const auto& hitParticlesMap = m_inputMeasurementParticlesMap(ctx);
0075 const auto& hitSimHitsMap = m_inputMeasurementSimHitsMap(ctx);
0076
0077 std::string path =
0078 perEventFilepath(m_cfg.outputDir, m_cfg.fileName, ctx.eventNumber);
0079
0080 std::ofstream mos(path, std::ofstream::out | std::ofstream::trunc);
0081 if (!mos) {
0082 throw std::ios_base::failure("Could not open '" + path + "' to write");
0083 }
0084
0085 std::unordered_map<std::size_t, SeedInfo> infoMap;
0086 std::unordered_map<ActsFatras::Barcode, std::pair<std::size_t, float>>
0087 goodSeed;
0088
0089
0090 for (std::size_t iparams = 0; iparams < trackParams.size(); ++iparams) {
0091
0092 const auto params = trackParams[iparams].parameters();
0093
0094 float seedPhi = params[Acts::eBoundPhi];
0095 float seedEta = std::atanh(std::cos(params[Acts::eBoundTheta]));
0096
0097
0098 const auto& seed = seeds[iparams];
0099 const auto& ptrack = seedToPrototrack(seed);
0100
0101 std::vector<ParticleHitCount> particleHitCounts;
0102 identifyContributingParticles(hitParticlesMap, ptrack, particleHitCounts);
0103 bool truthMatched = false;
0104 float truthDistance = -1;
0105 auto majorityParticleId = particleHitCounts.front().particleId;
0106
0107
0108 if (particleHitCounts.size() == 1) {
0109 truthMatched = true;
0110
0111 const auto& hitIdx = ptrack.front();
0112
0113 auto indices = makeRange(hitSimHitsMap.equal_range(hitIdx));
0114
0115 Acts::Vector3 truthUnitDir = {0, 0, 0};
0116 for (auto [_, simHitIdx] : indices) {
0117 const auto& simHit = *simHits.nth(simHitIdx);
0118 if (simHit.particleId() == majorityParticleId) {
0119 truthUnitDir = simHit.direction();
0120 }
0121 }
0122
0123 float truthPhi = phi(truthUnitDir);
0124 float truthEta = std::atanh(std::cos(theta(truthUnitDir)));
0125 float dEta = fabs(truthEta - seedEta);
0126 float dPhi = fabs(truthPhi - seedPhi) < M_PI
0127 ? fabs(truthPhi - seedPhi)
0128 : fabs(truthPhi - seedPhi) - M_PI;
0129 truthDistance = sqrt(dPhi * dPhi + dEta * dEta);
0130
0131
0132 if (goodSeed.find(majorityParticleId) != goodSeed.end()) {
0133 if (goodSeed[majorityParticleId].second > truthDistance) {
0134 goodSeed[majorityParticleId] = std::make_pair(iparams, truthDistance);
0135 }
0136 } else {
0137 goodSeed[majorityParticleId] = std::make_pair(iparams, truthDistance);
0138 }
0139 }
0140
0141 boost::container::small_vector<Acts::Vector3, 3> globalPosition;
0142 for (auto spacePointPtr : seed.sp()) {
0143 Acts::Vector3 pos(spacePointPtr->x(), spacePointPtr->y(),
0144 spacePointPtr->z());
0145 globalPosition.push_back(pos);
0146 }
0147
0148
0149 SeedInfo toAdd;
0150 toAdd.seedID = iparams;
0151 toAdd.particleId = majorityParticleId;
0152 toAdd.seedPt = std::abs(1.0 / params[Acts::eBoundQOverP]) *
0153 std::sin(params[Acts::eBoundTheta]);
0154 toAdd.seedPhi = seedPhi;
0155 toAdd.seedEta = seedEta;
0156 toAdd.vertexZ = seed.z();
0157 toAdd.quality = seed.seedQuality();
0158 toAdd.globalPosition = globalPosition;
0159 toAdd.truthDistance = truthDistance;
0160 toAdd.seedType = truthMatched ? "duplicate" : "fake";
0161 toAdd.measurementsID = ptrack;
0162
0163 infoMap[toAdd.seedID] = toAdd;
0164 }
0165
0166 mos << "seed_id,particleId,"
0167 << "pT,eta,phi,"
0168 << "bX,bY,bZ,"
0169 << "mX,mY,mZ,"
0170 << "tX,tY,tZ,"
0171 << "good/duplicate/fake,"
0172 << "vertexZ,quality,"
0173 << "Hits_ID" << '\n';
0174
0175 for (auto& [id, info] : infoMap) {
0176 if (goodSeed[info.particleId].first == id) {
0177 info.seedType = "good";
0178 }
0179
0180 mos << info.seedID << ",";
0181 mos << info.particleId << ",";
0182 mos << info.seedPt << ",";
0183 mos << info.seedEta << ",";
0184 mos << info.seedPhi << ",";
0185 for (auto& point : info.globalPosition) {
0186 mos << point.x() << ",";
0187 mos << point.y() << ",";
0188 mos << point.z() << ",";
0189 }
0190 mos << info.seedType << ",";
0191 mos << info.vertexZ << ",";
0192 mos << info.quality << ",";
0193 mos << "\"[";
0194 for (auto& ID : info.measurementsID) {
0195 mos << ID << ",";
0196 }
0197 mos << "]\"";
0198 mos << '\n';
0199 }
0200
0201 return ProcessCode::SUCCESS;
0202 }