24 :
WriterT(cfg.inputTrajectories,
"CKFPerformanceWriter", lvl),
25 m_cfg(std::move(cfg)),
26 m_effPlotTool(m_cfg.effPlotToolConfig, lvl),
27 m_fakeRatePlotTool(m_cfg.fakeRatePlotToolConfig, lvl),
28 m_duplicationPlotTool(m_cfg.duplicationPlotToolConfig, lvl),
29 m_trackSummaryPlotTool(m_cfg.trackSummaryPlotToolConfig, lvl) {
32 throw std::invalid_argument(
"Missing input trajectories collection");
35 throw std::invalid_argument(
"Missing input particles collection");
38 throw std::invalid_argument(
"Missing output filename");
47 throw std::invalid_argument(
"Could not open '" + path +
"'");
58 m_effPlotTool.clear(m_effPlotCache);
59 m_fakeRatePlotTool.clear(m_fakeRatePlotCache);
60 m_duplicationPlotTool.clear(m_duplicationPlotCache);
61 m_trackSummaryPlotTool.clear(m_trackSummaryPlotCache);
63 m_outputFile->Close();
70 m_effPlotTool.write(m_effPlotCache);
71 m_fakeRatePlotTool.write(m_fakeRatePlotCache);
72 m_duplicationPlotTool.write(m_duplicationPlotCache);
73 m_trackSummaryPlotTool.write(m_trackSummaryPlotCache);
74 ACTS_INFO(
"Wrote performance plots to '" << m_outputFile->GetPath() <<
"'");
82 using RecoTrackInfo = std::pair<size_t, Acts::BoundTrackParameters>;
85 const auto& particles =
89 std::lock_guard<std::mutex> lock(m_writeMutex);
92 std::map<ActsFatras::Barcode, std::vector<RecoTrackInfo>> matched;
94 std::map<ActsFatras::Barcode, size_t> unmatched;
97 for (
const auto& traj : trajectories) {
99 const auto& [trackTips, mj] = traj.trajectory();
100 if (trackTips.empty()) {
106 for (
const size_t& trackTip : trackTips) {
113 if (trajState.nMeasurements < m_cfg.nMeasurementsMin) {
117 if (not traj.hasTrackParameters(trackTip)) {
119 "No fitted track parameters for trajectory with entry index = "
123 const auto& fittedParameters = traj.trackParameters(trackTip);
125 m_trackSummaryPlotTool.fill(m_trackSummaryPlotCache, fittedParameters,
126 trajState.nStates, trajState.nMeasurements,
127 trajState.nOutliers, trajState.nHoles);
130 std::vector<ParticleHitCount> particleHitCount =
131 traj.identifyMajorityParticle(trackTip);
132 if (particleHitCount.empty()) {
134 "No truth particle associated with this trajectory with entry "
143 particleHitCount.front().particleId;
144 size_t nMajorityHits = particleHitCount.front().hitCount;
149 if (nMajorityHits * 1. / trajState.nMeasurements >=
150 m_cfg.truthMatchProbMin) {
151 matched[majorityParticleId].push_back(
152 {nMajorityHits, fittedParameters});
155 unmatched[majorityParticleId]++;
158 m_fakeRatePlotTool.fill(m_fakeRatePlotCache, fittedParameters, isFake);
163 for (
auto& [particleId, matchedTracks] : matched) {
166 std::sort(matchedTracks.begin(), matchedTracks.end(),
167 [](
const RecoTrackInfo& lhs,
const RecoTrackInfo& rhs) {
168 return lhs.first > rhs.first;
170 for (
size_t itrack = 0; itrack < matchedTracks.size(); itrack++) {
171 const auto& [nMajorityHits, fittedParameters] = matchedTracks.at(itrack);
174 bool isDuplicated = (itrack != 0);
176 m_duplicationPlotTool.fill(m_duplicationPlotCache, fittedParameters,
183 for (
const auto&
particle : particles) {
184 auto particleId =
particle.particleId();
186 size_t nMatchedTracks = 0;
187 bool isReconstructed =
false;
188 auto imatched = matched.find(particleId);
189 if (imatched != matched.end()) {
190 nMatchedTracks = imatched->second.size();
191 isReconstructed =
true;
194 m_effPlotTool.fill(m_effPlotCache,
particle, isReconstructed);
196 m_duplicationPlotTool.fill(m_duplicationPlotCache,
particle,
200 size_t nFakeTracks = 0;
201 auto ifake = unmatched.find(particleId);
202 if (ifake != unmatched.end()) {
203 nFakeTracks = ifake->second;
206 m_fakeRatePlotTool.fill(m_fakeRatePlotCache,
particle, nMatchedTracks,