ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TrackFitterPerformanceWriter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TrackFitterPerformanceWriter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
12 #include <TFile.h>
13 #include <TTree.h>
14 #include <stdexcept>
15 
18 
20 
23  : WriterT(cfg.inputTrajectories, "TrackFitterPerformanceWriter", lvl),
24  m_cfg(std::move(cfg)),
25  m_resPlotTool(m_cfg.resPlotToolConfig, lvl),
26  m_effPlotTool(m_cfg.effPlotToolConfig, lvl),
27  m_trackSummaryPlotTool(m_cfg.trackSummaryPlotToolConfig, lvl)
28 
29 {
30  // Input track and truth collection name
31  if (m_cfg.inputTrajectories.empty()) {
32  throw std::invalid_argument("Missing input trajectories collection");
33  }
34  if (m_cfg.inputParticles.empty()) {
35  throw std::invalid_argument("Missing input particles collection");
36  }
37  if (m_cfg.outputFilename.empty()) {
38  throw std::invalid_argument("Missing output filename");
39  }
40 
41  // the output file can not be given externally since TFile accesses to the
42  // same file from multiple threads are unsafe.
43  // must always be opened internally
45  m_outputFile = TFile::Open(path.c_str(), "RECREATE");
46  if (not m_outputFile) {
47  throw std::invalid_argument("Could not open '" + path + "'");
48  }
49 
50  // initialize the residual and efficiency plots tool
54 }
55 
57  m_resPlotTool.clear(m_resPlotCache);
58  m_effPlotTool.clear(m_effPlotCache);
59  m_trackSummaryPlotTool.clear(m_trackSummaryPlotCache);
60 
61  if (m_outputFile) {
62  m_outputFile->Close();
63  }
64 }
65 
67  // fill residual and pull details into additional hists
68  m_resPlotTool.refinement(m_resPlotCache);
69 
70  if (m_outputFile) {
71  m_outputFile->cd();
72  m_resPlotTool.write(m_resPlotCache);
73  m_effPlotTool.write(m_effPlotCache);
74  m_trackSummaryPlotTool.write(m_trackSummaryPlotCache);
75 
76  ACTS_INFO("Wrote performance plots to '" << m_outputFile->GetPath() << "'");
77  }
78  return ProcessCode::SUCCESS;
79 }
80 
82  const AlgorithmContext& ctx, const TrajectoryContainer& trajectories) {
83  // Read truth particles from input collection
84  const auto& particles =
85  ctx.eventStore.get<SimParticleContainer>(m_cfg.inputParticles);
86 
87  // Exclusive access to the tree while writing
88  std::lock_guard<std::mutex> lock(m_writeMutex);
89 
90  // All reconstructed trajectories with truth info
91  std::map<ActsFatras::Barcode, TruthFitTrack> reconTrajectories;
92 
93  // Loop over all trajectories
94  for (const auto& traj : trajectories) {
95  if (not traj.hasTrajectory()) {
96  continue;
97  }
98  const auto& [trackTip, track] = traj.trajectory();
99 
100  // get the majority truth particle to this track
101  const auto particleHitCount = traj.identifyMajorityParticle();
102  if (particleHitCount.empty()) {
103  continue;
104  }
105 
106  // find the truth particle for the majority barcode
107  const auto ip = particles.find(particleHitCount.front().particleId);
108  if (ip == particles.end()) {
109  continue;
110  }
111 
112  // record this trajectory with its truth info
113  reconTrajectories.emplace(ip->particleId(), traj);
114 
115  // count the total number of hits and hits from the majority truth
116  // particle
117  size_t nTotalStates = 0, nHits = 0, nOutliers = 0, nHoles = 0;
118  track.visitBackwards(trackTip, [&](const auto& state) {
119  nTotalStates++;
120  auto typeFlags = state.typeFlags();
121  if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) {
122  nHits++;
123  } else if (typeFlags.test(Acts::TrackStateFlag::OutlierFlag)) {
124  nOutliers++;
125  } else if (typeFlags.test(Acts::TrackStateFlag::HoleFlag)) {
126  nHoles++;
127  }
128  });
129 
130  // fill the track detailed info
131  m_trackSummaryPlotTool.fill(m_trackSummaryPlotCache, *ip, nTotalStates,
132  nHits, nOutliers, nHoles);
133 
134  // fill the residual plots it the track has fitted parameter
135  if (traj.hasTrackParameters()) {
136  m_resPlotTool.fill(m_resPlotCache, ctx.geoContext, *ip,
137  traj.trackParameters());
138  }
139  }
140 
141  // Fill the efficiency, defined as the ratio between number of tracks with
142  // fitted parameter and total truth tracks (assumes one truth partilce means
143  // one truth track)
144  // @Todo: add fake rate plots
145  for (const auto& particle : particles) {
146  const auto it = reconTrajectories.find(particle.particleId());
147  if (it != reconTrajectories.end()) {
148  // when the trajectory is reconstructed
149  m_effPlotTool.fill(m_effPlotCache, particle,
150  it->second.hasTrackParameters());
151  } else {
152  // when the trajectory is NOT reconstructed
153  m_effPlotTool.fill(m_effPlotCache, particle, false);
154  }
155  }
156 
157  return ProcessCode::SUCCESS;
158 }