28 #include <unordered_map>
29 #include <unordered_set>
32 namespace ActsExamples {
36 using namespace ActsExamples;
41 "CsvMultiTrajectoryWriter", level),
44 throw std::invalid_argument(
"Missing input trajectories collection");
58 throw std::ios_base::failure(
"Could not open '" + path +
"' to write");
63 std::unordered_map<Acts::MultiTrajectoryTraits::IndexType, trackInfo> infoMap;
67 std::map<ActsFatras::Barcode, std::vector<RecoTrackInfo>> matched;
70 for (
const auto& traj : trajectories) {
72 const auto& trackTips = traj.tips();
73 const auto& mj = traj.multiTrajectory();
74 if (trackTips.empty()) {
80 for (
auto trackTip : trackTips) {
92 if (not traj.hasTrackParameters(trackTip)) {
94 "No fitted track parameters for trajectory with entry index = "
100 std::vector<ParticleHitCount> particleHitCount;
105 "No truth particle associated with this trajectory with entry "
112 const auto& params = traj.trackParameters(trackTip);
113 const auto momentum = params.momentum();
118 size_t nMajorityHits = 0;
120 if (!particleHitCount.empty()) {
122 majorityParticleId = particleHitCount.front().particleId;
124 nMajorityHits = particleHitCount.front().hitCount;
130 toAdd.
nStates = trajState.nStates;
134 toAdd.
nHoles = trajState.nHoles;
136 toAdd.
chi2Sum = trajState.chi2Sum;
137 toAdd.
NDF = trajState.NDF;
142 mj.visitBackwards(trackTip, [&](
const auto&
state) {
146 state.getUncalibratedSourceLink().template get<IndexSourceLink>();
147 auto hitIndex = sl.index();
159 infoMap[toAdd.
trackId] = toAdd;
166 std::unordered_set<size_t> listGoodTracks;
167 for (
auto& [particleId, matchedTracks] : matched) {
168 std::sort(matchedTracks.begin(), matchedTracks.end(),
175 if (lhs.first.nOutliers !=
rhs.first.nOutliers) {
176 return (lhs.first.nOutliers <
rhs.first.nOutliers);
179 return (lhs.first.chi2Sum <
rhs.first.chi2Sum);
182 listGoodTracks.insert(matchedTracks.front().first.trackId);
186 mos <<
"track_id,particleId,"
187 <<
"nStates,nMajorityHits,nMeasurements,nOutliers,nHoles,nSharedHits,"
188 <<
"chi2,ndf,chi2/ndf,"
190 <<
"truthMatchProbability,"
191 <<
"good/duplicate/fake,"
198 for (
auto& [
id, trajState] : infoMap) {
199 if (listGoodTracks.find(
id) != listGoodTracks.end()) {
200 trajState.trackType =
"good";
201 }
else if (trajState.trackType !=
"fake") {
202 trajState.trackType =
"duplicate";
205 const auto& params = *trajState.fittedParameters;
206 const auto momentum = params.momentum();
209 mos << trajState.trackId <<
",";
210 mos << trajState.particleId <<
",";
211 mos << trajState.nStates <<
",";
212 mos << trajState.nMajorityHits <<
",";
213 mos << trajState.nMeasurements <<
",";
214 mos << trajState.nOutliers <<
",";
215 mos << trajState.nHoles <<
",";
216 mos << trajState.nSharedHits <<
",";
217 mos << trajState.chi2Sum <<
",";
218 mos << trajState.NDF <<
",";
219 mos << trajState.chi2Sum * 1.0 / trajState.NDF <<
",";
223 mos << trajState.truthMatchProb <<
",";
224 mos << trajState.trackType <<
",";
226 for (
auto& ID : trajState.measurementsID) {