8 #include "trg/cdc/modules/mcmatcher/CDCTriggerMCMatcherModule.h"
10 #include <framework/gearbox/Const.h>
12 #include <Eigen/Dense>
18 struct iter_pair_range : std::pair<Iter, Iter> {
19 explicit iter_pair_range(std::pair<Iter, Iter>
const& x) : std::pair<Iter, Iter>(x) {}
20 Iter begin()
const {
return this->first;}
21 Iter end()
const {
return this->second;}
25 inline iter_pair_range<Iter> as_range(std::pair<Iter, Iter>
const& x)
27 return iter_pair_range<Iter>(x);
33 typedef float Efficiency;
47 setDescription(
"A module to match CDCTriggerTracks to MCParticles.\n"
48 "Creates an array MCTracks of trackable MCParticles "
49 "and makes relations from MCTracks to CDCTriggerTracks "
52 addParam(
"MCParticleCollectionName", m_MCParticleCollectionName,
53 "Name of the MCParticle StoreArray to be matched.",
54 string(
"MCParticles"));
55 addParam(
"TrgTrackCollectionName", m_TrgTrackCollectionName,
56 "Name of the CDCTriggerTrack StoreArray to be matched.",
57 string(
"TRGCDC2DFinderTracks"));
58 addParam(
"MCTrackableCollectionName", m_MCTrackableCollectionName,
59 "Name of a new StoreArray holding MCParticles considered as trackable.",
61 addParam(
"hitCollectionName", m_hitCollectionName,
62 "Name of the StoreArray of CDCTriggerSegmentHits used for the matching.",
64 addParam(
"minAxial", m_minAxial,
65 "Minimum number of axial hits in different super layers.",
67 addParam(
"minStereo", m_minStereo,
68 "Minimum number of stereo hits in different super layers.",
70 addParam(
"axialOnly", m_axialOnly,
71 "Switch to ignore stereo hits (= 2D matching).",
73 addParam(
"minPurity", m_minPurity,
74 "Minimum purity for reconstructed tracks.",
76 addParam(
"minEfficiency", m_minEfficiency,
77 "Minimum efficiency for MC tracks.",
79 addParam(
"onlyPrimaries", m_onlyPrimaries,
80 "If true, MCTracks are only made from primary particles.",
82 addParam(
"relateClonesAndMerged", m_relateClonesAndMerged,
83 "If true, create relations for clones and merged tracks "
84 "(will get negative weight).",
92 m_segmentHits.isRequired(m_hitCollectionName);
93 m_prTracks.isRequired(m_TrgTrackCollectionName);
94 m_mcParticles.isRequired(m_MCParticleCollectionName);
95 m_mcTracks.registerInDataStore(m_MCTrackableCollectionName);
97 m_mcParticles.requireRelationTo(m_segmentHits);
98 m_prTracks.requireRelationTo(m_segmentHits);
99 m_mcParticles.registerRelationTo(m_mcTracks);
100 m_mcParticles.registerRelationTo(m_prTracks);
101 m_mcTracks.registerRelationTo(m_segmentHits);
102 m_mcTracks.registerRelationTo(m_prTracks);
103 m_prTracks.registerRelationTo(m_mcParticles);
104 m_prTracks.registerRelationTo(m_mcTracks);
112 for (
int imc = 0; imc < m_mcParticles.getEntries(); ++imc) {
126 vector<bool> SLcounted;
127 SLcounted.assign(9,
false);
131 for (
unsigned ihit = 0; ihit < relHits.
size(); ++ihit) {
132 unsigned iSL = relHits[ihit]->getISuperLayer();
133 if (SLcounted[iSL])
continue;
134 if (iSL % 2) ++nStereo;
136 SLcounted[iSL] =
true;
139 if (nAxial < m_minAxial || nStereo < m_minStereo)
continue;
142 MCParticle* mcTrack = m_mcTracks.appendNew(m_mcTracks.getPtr(), *mcParticle);
144 for (
unsigned ihit = 0; ihit < relHits.
size(); ++ihit) {
152 B2DEBUG(100,
"########## start MC matching ############");
154 int nMCTracks = m_mcTracks.getEntries();
155 int nPRTracks = m_prTracks.getEntries();
157 B2DEBUG(100,
"Number of pattern recognition tracks is " << nPRTracks);
158 B2DEBUG(100,
"Number of Monte-Carlo tracks is " << nMCTracks);
160 if (not nMCTracks or not nPRTracks) {
168 std::map<HitId, TrackId> mcTrackId_by_hitId;
170 std::map<HitId, TrackId>::iterator itMCInsertHit = mcTrackId_by_hitId.end();
171 TrackId mcTrackId = -1;
172 for (
const MCParticle& mcTrack : m_mcTracks) {
176 for (
unsigned iHit = 0; iHit < relHits.
size(); ++iHit) {
177 const HitId hitId = relHits[iHit]->getArrayIndex();
178 itMCInsertHit = mcTrackId_by_hitId.insert(itMCInsertHit,
179 make_pair(hitId, mcTrackId));
180 B2DEBUG(250,
"hitId " << hitId <<
" in SL " << relHits[iHit]->getISuperLayer()
181 <<
", mcTrackId " << mcTrackId);
187 std::multimap<HitId, TrackId> prTrackId_by_hitId;
189 std::multimap<HitId, TrackId>::iterator itPRInsertHit = prTrackId_by_hitId.end();
190 TrackId prTrackId = -1;
195 for (
unsigned int iHit = 0; iHit < relHits.
size(); ++iHit) {
196 const HitId hitId = relHits[iHit]->getArrayIndex();
197 itPRInsertHit = prTrackId_by_hitId.insert(itPRInsertHit,
198 make_pair(hitId, prTrackId));
199 B2DEBUG(250,
"hitId " << hitId <<
" in SL " << relHits[iHit]->getISuperLayer()
200 <<
", prTrackId " << prTrackId);
209 Eigen::MatrixXi confusionMatrix = Eigen::MatrixXi::Zero(nPRTracks, nMCTracks + 1);
214 Eigen::RowVectorXi totalHits_by_mcTrackId = Eigen::RowVectorXi::Zero(nMCTracks + 1);
217 const int mcBkgId = nMCTracks;
221 for (HitId hitId = 0; hitId < m_segmentHits.getEntries(); ++hitId) {
223 if (m_axialOnly && m_segmentHits[hitId]->getISuperLayer() % 2)
continue;
227 auto it_mcTrackId = mcTrackId_by_hitId.find(hitId);
229 (it_mcTrackId == mcTrackId_by_hitId.end()) ? mcBkgId : it_mcTrackId->second;
232 totalHits_by_mcTrackId(mcTrackId) += 1;
235 auto range_prTrackIds = prTrackId_by_hitId.equal_range(hitId);
238 for (
const pair<HitId, TrackId> hitId_and_prTrackId :
239 as_range(range_prTrackIds)) {
240 TrackId prTrackId = hitId_and_prTrackId.second;
241 B2DEBUG(200,
" prTrackId : " << prTrackId <<
"; mcTrackId : " << mcTrackId);
242 confusionMatrix(prTrackId, mcTrackId) += 1;
246 Eigen::VectorXi totalHits_by_prTrackId = confusionMatrix.rowwise().sum();
248 B2DEBUG(200,
"Confusion matrix of the event : " << endl << confusionMatrix);
250 B2DEBUG(200,
"totalHits_by_prTrackId : " << endl << totalHits_by_prTrackId);
251 B2DEBUG(200,
"totalHits_by_mcTrackId : " << endl << totalHits_by_mcTrackId);
254 vector<pair<TrackId, Purity>> purestMCTrackId_by_prTrackId(nPRTracks);
256 for (TrackId prTrackId = 0; prTrackId < nPRTracks; ++prTrackId) {
257 Eigen::RowVectorXi prTrackRow = confusionMatrix.row(prTrackId);
258 Eigen::RowVectorXi::Index purestMCTrackId;
261 int highestHits = prTrackRow.maxCoeff(&purestMCTrackId);
262 int totalHits = totalHits_by_prTrackId(prTrackId);
264 Purity highestPurity = Purity(highestHits) / totalHits;
266 purestMCTrackId_by_prTrackId[prTrackId] =
267 pair<TrackId, Purity>(purestMCTrackId, highestPurity);
273 TrackId prTrackId = -1;
274 B2DEBUG(200,
"PRTrack to highest purity MCTrack relation");
275 for (
const pair< TrackId, Purity>& purestMCTrackId :
276 purestMCTrackId_by_prTrackId) {
278 const Purity& purity = purestMCTrackId.second;
279 const TrackId& mcTrackId = purestMCTrackId.first;
280 B2DEBUG(200,
"prTrackId : " << prTrackId <<
" -> mcTrackId : " << mcTrackId
281 <<
" with purity " << purity);
286 vector<pair<TrackId, Efficiency>> mostEfficientPRTrackId_by_mcTrackId(nMCTracks);
288 for (TrackId mcTrackId = 0; mcTrackId < nMCTracks; ++mcTrackId) {
289 Eigen::VectorXi mcTrackCol = confusionMatrix.col(mcTrackId);
290 Eigen::VectorXi::Index highestHitsPRTrackId;
293 int highestHits = mcTrackCol.maxCoeff(&highestHitsPRTrackId);
294 int totalHits = totalHits_by_mcTrackId(mcTrackId);
296 Efficiency highestEfficiency = Efficiency(highestHits) / totalHits;
298 mostEfficientPRTrackId_by_mcTrackId[mcTrackId] =
299 pair<TrackId, Efficiency> (highestHitsPRTrackId, highestEfficiency);
305 TrackId mcTrackId = -1;
306 B2DEBUG(200,
"MCTrack to highest efficiency PRTrack relation");
307 for (
const pair<TrackId, Efficiency>& mostEfficientPRTrackId :
308 mostEfficientPRTrackId_by_mcTrackId) {
310 const Efficiency& efficiency = mostEfficientPRTrackId.second;
311 const TrackId& prTrackId = mostEfficientPRTrackId.first;
312 B2DEBUG(200,
"mcTrackId : " << mcTrackId <<
" -> prTrackId : " << prTrackId
313 <<
" with efficiency " << efficiency);
318 for (TrackId prTrackId = 0; prTrackId < nPRTracks; ++prTrackId) {
321 const pair<TrackId, Purity>& purestMCTrackId = purestMCTrackId_by_prTrackId[prTrackId];
322 const TrackId& mcTrackId = purestMCTrackId.first;
323 const Purity& purity = purestMCTrackId.second;
325 if (!(purity >= m_minPurity)) {
327 B2DEBUG(100,
"Classified PRTrack " << prTrackId <<
" as ghost because of too low purity.");
328 }
else if (mcTrackId == mcBkgId) {
330 B2DEBUG(100,
"Classified PRTrack " << prTrackId <<
" as background.");
336 const pair<TrackId, Efficiency>& mostEfficientPRTrackId =
337 mostEfficientPRTrackId_by_mcTrackId[mcTrackId];
339 const TrackId& prTrackIdCompare = mostEfficientPRTrackId.first;
340 const Efficiency& efficiency = mostEfficientPRTrackId.second;
342 if (prTrackId != prTrackIdCompare) {
343 if (efficiency >= m_minEfficiency) {
345 if (m_relateClonesAndMerged) {
347 prTrack->addRelationTo(mcTrack, -purity);
350 B2DEBUG(100,
"Classified PRTrack " << prTrackId <<
" as clone -> mcTrackId "
351 << mcTrackId <<
" : " << -purity);
354 B2DEBUG(100,
"Classified PRTrack " << prTrackId
355 <<
" as ghost because of too low efficiency in purest MCTrack "
356 <<
"(mcTrackId=" << mcTrackId <<
").");
361 prTrack->addRelationTo(mcTrack, purity);
363 B2DEBUG(100,
"Classified PRTrack " << prTrackId <<
" as match -> mcTrackId "
364 << mcTrackId <<
" : " << purity);
371 for (TrackId mcTrackId = 0; mcTrackId < nMCTracks; ++mcTrackId) {
374 const pair<TrackId, Efficiency>& mostEfficiencyPRTrackId =
375 mostEfficientPRTrackId_by_mcTrackId[mcTrackId];
376 const TrackId& prTrackId = mostEfficiencyPRTrackId.first;
377 const Efficiency& efficiency = mostEfficiencyPRTrackId.second;
379 if (!(efficiency >= m_minEfficiency)) {
381 B2DEBUG(100,
"Classified MCTrack " << mcTrackId <<
" as missing.");
387 const pair<TrackId, Purity>& purestMCTrackId = purestMCTrackId_by_prTrackId[prTrackId];
388 const TrackId& mcTrackIdCompare = purestMCTrackId.first;
390 if (mcTrackId != mcTrackIdCompare) {
392 if (m_relateClonesAndMerged) {
397 B2DEBUG(100,
"Classifid MCTrack " << mcTrackId <<
" as merge -> prTrackId "
398 << prTrackId <<
" : " << -efficiency);
405 B2DEBUG(100,
"Classified MCTrack " << mcTrackId <<
" as match -> prTrackId "
406 << prTrackId <<
" : " << efficiency);
411 B2DEBUG(100,
"########## end MC matching ############");
A module to match CDCTriggerTracks to MCParticles.
virtual void initialize() override
Initialize the module.
virtual void event() override
Called once for each event.
Combination of several CDCHits to a track segment hit for the trigger.
Track created by the CDC trigger.
A Class to store the Monte Carlo particle information.
@ c_PrimaryParticle
bit 0: Particle is primary particle.
bool hasSeenInDetector(Const::DetectorSet set) const
Return if the seen-in flag for a specific subdetector is set or not.
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
float getCharge() const
Return the particle charge defined in TDatabasePDG.
int getPDG() const
Return PDG code of particle.
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.