102 for (
int ireco = 0; ireco < m_recoTracks.getEntries(); ++ireco) {
103 RecoTrack* recoTrack = m_recoTracks[ireco];
108 if (m_relateHitsByID) {
110 if (tsHit.getID() == cdcHit->getID()) {
116 auto relHits = cdcHit->template getRelationsFrom<CDCTriggerSegmentHit>(m_hitCollectionName);
117 for (
size_t i = 0; i < relHits.size(); ++i) {
119 if (relHits.weight(i) > 1)
127 int nRecoTracks = m_recoTracks.getEntries();
128 int nTrgTracks = m_trgTracks.getEntries();
129 if (nRecoTracks == 0 || nTrgTracks == 0)
return;
132 auto buildHitToTrackMap = [&](
auto & tracks) {
133 std::multimap<HitId, TrackId> result;
134 for (TrackId
id = 0;
id < tracks.getEntries(); ++id) {
135 auto relHits = tracks[id]->template getRelationsTo<CDCTriggerSegmentHit>(m_hitCollectionName);
136 for (
auto& hit : relHits) {
137 result.insert(std::make_pair(hit.getArrayIndex(),
id));
143 auto recoTrackIdByHitId = buildHitToTrackMap(m_recoTracks);
144 auto trgTrackIdByHitId = buildHitToTrackMap(m_trgTracks);
146 Eigen::MatrixXi confusionMatrix = Eigen::MatrixXi::Zero(nTrgTracks, nRecoTracks);
147 Eigen::RowVectorXi totalHitsByRecoTrackId = Eigen::RowVectorXi::Zero(nRecoTracks);
148 Eigen::VectorXi totalHitsByTrgTrackId = Eigen::VectorXi::Zero(nTrgTracks);
151 for (HitId hitId = 0; hitId < m_segmentHits.getEntries(); ++hitId) {
152 if (m_axialOnly && m_segmentHits[hitId]->getISuperLayer() % 2)
continue;
154 auto trgRange = trgTrackIdByHitId.equal_range(hitId);
155 auto recoRange = recoTrackIdByHitId.equal_range(hitId);
157 for (
auto& [_, tId] : as_range(trgRange)) totalHitsByTrgTrackId(tId) += 1;
158 for (
auto& [_, rId] : as_range(recoRange)) totalHitsByRecoTrackId(rId) += 1;
160 for (
auto& [_, rId] : as_range(recoRange)) {
161 for (
auto& [_, tId] : as_range(trgRange)) {
162 confusionMatrix(tId, rId) += 1;
168 auto bestRecoForTrg = [&](TrackId trgId) {
169 Eigen::RowVectorXi row = confusionMatrix.row(trgId);
170 Eigen::RowVectorXi::Index bestRecoId;
171 int hits = row.maxCoeff(&bestRecoId);
172 Purity purity = Purity(hits) / totalHitsByTrgTrackId(trgId);
173 return std::pair<TrackId, Purity>(bestRecoId, purity);
177 auto bestTrgForReco = [&](TrackId recoId) {
178 Eigen::VectorXi col = confusionMatrix.col(recoId);
179 Eigen::VectorXi::Index bestTrgId;
180 int hits = col.maxCoeff(&bestTrgId);
181 Efficiency eff = Efficiency(hits) / totalHitsByRecoTrackId(recoId);
182 return std::pair<TrackId, Efficiency>(bestTrgId, eff);
186 std::vector<std::pair<TrackId, Purity>> purestRecoByTrg(nTrgTracks);
187 for (TrackId t = 0; t < nTrgTracks; ++t) purestRecoByTrg[t] = bestRecoForTrg(t);
189 std::vector<std::pair<TrackId, Efficiency>> mostEffTrgByReco(nRecoTracks);
190 for (TrackId r = 0; r < nRecoTracks; ++r) mostEffTrgByReco[r] = bestTrgForReco(r);
193 for (TrackId t = 0; t < nTrgTracks; ++t) {
194 auto [r, purity] = purestRecoByTrg[t];
195 TrgTrackType* trg = m_trgTracks[t];
197 if (purity < m_minPurity)
continue;
199 auto [bestTrg, eff] = mostEffTrgByReco[r];
203 trg->addRelationTo(reco, purity);
204 }
else if (m_relateClonesAndMerged) {
205 trg->addRelationTo(reco, -purity);
210 for (TrackId r = 0; r < nRecoTracks; ++r) {
211 auto [t, eff] = mostEffTrgByReco[r];
214 if (eff < m_minEfficiency)
continue;
216 auto [bestReco, purity] = purestRecoByTrg[t];
217 TrgTrackType* trg = m_trgTracks[t];
221 }
else if (m_relateClonesAndMerged) {