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 
15 
16 #include <stdexcept>
17 
18 #include <TFile.h>
19 #include <TTree.h>
20 
22 
26  : WriterT(cfg.inputTrajectories, "TrackFitterPerformanceWriter", lvl),
27  m_cfg(std::move(cfg)),
28  m_resPlotTool(m_cfg.resPlotToolConfig, lvl),
29  m_effPlotTool(m_cfg.effPlotToolConfig, lvl),
30  m_trackSummaryPlotTool(m_cfg.trackSummaryPlotToolConfig, lvl)
31 
32 {
33  // Input track and truth collection name
34  if (m_cfg.inputTrajectories.empty()) {
35  throw std::invalid_argument("Missing input trajectories collection");
36  }
37  if (m_cfg.inputParticles.empty()) {
38  throw std::invalid_argument("Missing input particles collection");
39  }
40  if (m_cfg.outputFilename.empty()) {
41  throw std::invalid_argument("Missing output filename");
42  }
43 
44  // the output file can not be given externally since TFile accesses to the
45  // same file from multiple threads are unsafe.
46  // must always be opened internally
48  m_outputFile = TFile::Open(path.c_str(), "RECREATE");
49  if (not m_outputFile) {
50  throw std::invalid_argument("Could not open '" + path + "'");
51  }
52 
53  // initialize the residual and efficiency plots tool
57 }
58 
60  m_resPlotTool.clear(m_resPlotCache);
61  m_effPlotTool.clear(m_effPlotCache);
62  m_trackSummaryPlotTool.clear(m_trackSummaryPlotCache);
63 
64  if (m_outputFile) {
65  m_outputFile->Close();
66  }
67 }
68 
70  // fill residual and pull details into additional hists
71  m_resPlotTool.refinement(m_resPlotCache);
72 
73  if (m_outputFile) {
74  m_outputFile->cd();
75  m_resPlotTool.write(m_resPlotCache);
76  m_effPlotTool.write(m_effPlotCache);
77  m_trackSummaryPlotTool.write(m_trackSummaryPlotCache);
78 
79  ACTS_INFO("Wrote performance plots to '" << m_outputFile->GetPath() << "'");
80  }
81  return ProcessCode::SUCCESS;
82 }
83 
85  const AlgorithmContext& ctx, const TrajectoryContainer& trajectories) {
86  // Read truth particles from input collection
87  const auto& particles =
88  ctx.eventStore.get<SimParticleContainer>(m_cfg.inputParticles);
89 
90  // Exclusive access to the tree while writing
91  std::lock_guard<std::mutex> lock(m_writeMutex);
92 
93  // Truth particles with corresponding reconstructed tracks
94  std::vector<ActsFatras::Barcode> reconParticleIds;
95  reconParticleIds.reserve(particles.size());
96 
97  // Loop over all trajectories
98  for (const auto& traj : trajectories) {
99  // The trajectory entry indices and the multiTrajectory
100  const auto& [trackTips, mj] = traj.trajectory();
101  if (trackTips.empty()) {
102  ACTS_WARNING("Empty multiTrajectory.");
103  continue;
104  }
105 
106  // Check the size of the trajectory entry indices. For track fitting, there
107  // should be at most one trajectory
108  if (trackTips.size() > 1) {
109  ACTS_ERROR("Track fitting should not result in multiple trajectories.");
110  return ProcessCode::ABORT;
111  }
112  // Get the entry index for the single trajectory
113  auto& trackTip = trackTips.front();
114 
115  // Select reco track with fitted parameters
116  if (not traj.hasTrackParameters(trackTip)) {
117  ACTS_WARNING("No fitted track parameters.");
118  continue;
119  }
120  const auto& fittedParameters = traj.trackParameters(trackTip);
121 
122  // Get the majority truth particle for this trajectory
123  const auto particleHitCount = traj.identifyMajorityParticle(trackTip);
124  if (particleHitCount.empty()) {
125  ACTS_WARNING("No truth particle associated with this trajectory.");
126  continue;
127  }
128  // Find the truth particle for the majority barcode
129  const auto ip = particles.find(particleHitCount.front().particleId);
130  if (ip == particles.end()) {
131  ACTS_WARNING("Majority particle not found in the particles collection.");
132  continue;
133  }
134 
135  // Record this majority particle ID of this trajectory
136  reconParticleIds.push_back(ip->particleId());
137  // Fill the residual plots
138  m_resPlotTool.fill(m_resPlotCache, ctx.geoContext, *ip,
139  traj.trackParameters(trackTip));
140  // Collect the trajectory summary info
141  auto trajState =
143  // Fill the trajectory summary info
144  m_trackSummaryPlotTool.fill(m_trackSummaryPlotCache, fittedParameters,
145  trajState.nStates, trajState.nMeasurements,
146  trajState.nOutliers, trajState.nHoles);
147  }
148 
149  // Fill the efficiency, defined as the ratio between number of tracks with
150  // fitted parameter and total truth tracks (assumes one truth partilce has
151  // one truth track)
152  for (const auto& particle : particles) {
153  bool isReconstructed = false;
154  // Find if the particle has been reconstructed
155  auto it = std::find(reconParticleIds.begin(), reconParticleIds.end(),
156  particle.particleId());
157  if (it != reconParticleIds.end()) {
158  isReconstructed = true;
159  }
160  m_effPlotTool.fill(m_effPlotCache, particle, isReconstructed);
161  }
162 
163  return ProcessCode::SUCCESS;
164 }