File indexing completed on 2025-01-18 09:11:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/TrackFitterPerformanceWriter.hpp"
0010
0011 #include "Acts/EventData/MultiTrajectoryHelpers.hpp"
0012 #include "Acts/EventData/TrackParameters.hpp"
0013 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0014 #include "Acts/Utilities/Helpers.hpp"
0015 #include "Acts/Utilities/MultiIndex.hpp"
0016 #include "ActsExamples/EventData/SimParticle.hpp"
0017 #include "ActsExamples/EventData/Track.hpp"
0018 #include "ActsExamples/Framework/AlgorithmContext.hpp"
0019 #include "ActsExamples/Validation/TrackClassification.hpp"
0020 #include "ActsFatras/EventData/Barcode.hpp"
0021 #include "ActsFatras/EventData/Particle.hpp"
0022
0023 #include <algorithm>
0024 #include <cstddef>
0025 #include <memory>
0026 #include <ostream>
0027 #include <stdexcept>
0028 #include <utility>
0029 #include <vector>
0030
0031 #include <TFile.h>
0032
0033 using Acts::VectorHelpers::eta;
0034 using Acts::VectorHelpers::phi;
0035
0036 ActsExamples::TrackFitterPerformanceWriter::TrackFitterPerformanceWriter(
0037 ActsExamples::TrackFitterPerformanceWriter::Config config,
0038 Acts::Logging::Level level)
0039 : WriterT(config.inputTracks, "TrackFitterPerformanceWriter", level),
0040 m_cfg(std::move(config)),
0041 m_resPlotTool(m_cfg.resPlotToolConfig, level),
0042 m_effPlotTool(m_cfg.effPlotToolConfig, level),
0043 m_trackSummaryPlotTool(m_cfg.trackSummaryPlotToolConfig, level) {
0044
0045 if (m_cfg.inputParticles.empty()) {
0046 throw std::invalid_argument("Missing particles input collection");
0047 }
0048 if (m_cfg.inputTrackParticleMatching.empty()) {
0049 throw std::invalid_argument("Missing input track particles matching");
0050 }
0051 if (m_cfg.filePath.empty()) {
0052 throw std::invalid_argument("Missing output filename");
0053 }
0054
0055 m_inputParticles.initialize(m_cfg.inputParticles);
0056 m_inputTrackParticleMatching.initialize(m_cfg.inputTrackParticleMatching);
0057
0058
0059
0060
0061 auto path = m_cfg.filePath;
0062 m_outputFile = TFile::Open(path.c_str(), "RECREATE");
0063 if (m_outputFile == nullptr) {
0064 throw std::invalid_argument("Could not open '" + path + "'");
0065 }
0066
0067
0068 m_resPlotTool.book(m_resPlotCache);
0069 m_effPlotTool.book(m_effPlotCache);
0070 m_trackSummaryPlotTool.book(m_trackSummaryPlotCache);
0071 }
0072
0073 ActsExamples::TrackFitterPerformanceWriter::~TrackFitterPerformanceWriter() {
0074 m_resPlotTool.clear(m_resPlotCache);
0075 m_effPlotTool.clear(m_effPlotCache);
0076 m_trackSummaryPlotTool.clear(m_trackSummaryPlotCache);
0077
0078 if (m_outputFile != nullptr) {
0079 m_outputFile->Close();
0080 }
0081 }
0082
0083 ActsExamples::ProcessCode
0084 ActsExamples::TrackFitterPerformanceWriter::finalize() {
0085
0086 m_resPlotTool.refinement(m_resPlotCache);
0087
0088 if (m_outputFile != nullptr) {
0089 m_outputFile->cd();
0090 m_resPlotTool.write(m_resPlotCache);
0091 m_effPlotTool.write(m_effPlotCache);
0092 m_trackSummaryPlotTool.write(m_trackSummaryPlotCache);
0093
0094 ACTS_INFO("Wrote performance plots to '" << m_outputFile->GetPath() << "'");
0095 }
0096 return ProcessCode::SUCCESS;
0097 }
0098
0099 ActsExamples::ProcessCode ActsExamples::TrackFitterPerformanceWriter::writeT(
0100 const AlgorithmContext& ctx, const ConstTrackContainer& tracks) {
0101
0102 const auto& particles = m_inputParticles(ctx);
0103 const auto& trackParticleMatching = m_inputTrackParticleMatching(ctx);
0104
0105
0106 std::vector<ActsFatras::Barcode> reconParticleIds;
0107 reconParticleIds.reserve(particles.size());
0108
0109 std::vector<ParticleHitCount> particleHitCounts;
0110
0111
0112 std::lock_guard<std::mutex> lock(m_writeMutex);
0113
0114
0115 for (const auto& track : tracks) {
0116
0117 if (!track.hasReferenceSurface()) {
0118 ACTS_WARNING("No fitted track parameters.");
0119 continue;
0120 }
0121 Acts::BoundTrackParameters fittedParameters =
0122 track.createParametersAtReference();
0123
0124
0125 auto imatched = trackParticleMatching.find(track.index());
0126 if (imatched == trackParticleMatching.end()) {
0127 ACTS_DEBUG("No truth particle associated with this track, index = "
0128 << track.index() << " tip index = " << track.tipIndex());
0129 continue;
0130 }
0131 const auto& particleMatch = imatched->second;
0132
0133 if (!particleMatch.particle.has_value()) {
0134 ACTS_DEBUG("No truth particle associated with this track.");
0135 continue;
0136 }
0137
0138
0139 SimBarcode majorityParticleId = particleMatch.particle.value();
0140
0141
0142 auto ip = particles.find(majorityParticleId);
0143 if (ip == particles.end()) {
0144 ACTS_WARNING("Majority particle not found in the particles collection.");
0145 continue;
0146 }
0147
0148
0149 reconParticleIds.push_back(ip->particleId());
0150
0151 m_resPlotTool.fill(m_resPlotCache, ctx.geoContext, ip->initial(),
0152 fittedParameters);
0153
0154 m_trackSummaryPlotTool.fill(m_trackSummaryPlotCache, fittedParameters,
0155 track.nTrackStates(), track.nMeasurements(),
0156 track.nOutliers(), track.nHoles(),
0157 track.nSharedHits());
0158 }
0159
0160
0161
0162
0163 for (const auto& particle : particles) {
0164 bool isReconstructed = false;
0165
0166 if (rangeContainsValue(reconParticleIds, particle.particleId())) {
0167 isReconstructed = true;
0168 }
0169
0170
0171 double minDeltaR = -1;
0172 for (const auto& closeParticle : particles) {
0173 if (closeParticle.particleId() == particle.particleId()) {
0174 continue;
0175 }
0176 double p_phi = phi(particle.direction());
0177 double p_eta = eta(particle.direction());
0178 double c_phi = phi(closeParticle.direction());
0179 double c_eta = eta(closeParticle.direction());
0180 double distance = sqrt(pow(p_phi - c_phi, 2) + pow(p_eta - c_eta, 2));
0181 if (minDeltaR == -1 || distance < minDeltaR) {
0182 minDeltaR = distance;
0183 }
0184 }
0185 m_effPlotTool.fill(m_effPlotCache, particle.initial(), minDeltaR,
0186 isReconstructed);
0187 }
0188
0189 return ProcessCode::SUCCESS;
0190 }