8#include "trg/cdc/modules/mcmatcher/CDCTriggerMCMatcherModule.h"
10#include <framework/gearbox/Const.h>
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 "
53 "Name of the MCParticle StoreArray to be matched.",
54 string(
"MCParticles"));
56 "Name of the CDCTriggerTrack StoreArray to be matched.",
57 string(
"TRGCDC2DFinderTracks"));
59 "Name of a new StoreArray holding MCParticles considered as trackable.",
62 "Name of the StoreArray of CDCTriggerSegmentHits used for the matching.",
65 "Minimum number of axial hits in different super layers.",
68 "Minimum number of stereo hits in different super layers.",
71 "Switch to ignore stereo hits (= 2D matching).",
74 "Minimum purity for reconstructed tracks.",
77 "Minimum efficiency for MC tracks.",
80 "If true, MCTracks are only made from primary particles.",
83 "If true, create relations for clones and merged tracks "
84 "(will get negative weight).",
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;
144 for (
unsigned ihit = 0; ihit < relHits.
size(); ++ihit) {
152 B2DEBUG(100,
"########## start MC matching ############");
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;
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;
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;
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) {
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;
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) {
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 ############");
CDCTriggerMCMatcherModule()
Constructor, for setting module description and parameters.
std::string m_MCParticleCollectionName
Name of the MCParticle StoreArray to be matched.
std::string m_MCTrackableCollectionName
Name of a new StoreArray holding MCParticles considered as trackable.
StoreArray< MCParticle > m_mcTracks
list of MCParticles considered as trackable
virtual void initialize() override
Initialize the module.
virtual void event() override
Called once for each event.
StoreArray< CDCTriggerSegmentHit > m_segmentHits
list of hits that are used for the matching
double m_minPurity
minimum purity
bool m_axialOnly
switch for 2D matching
std::string m_TrgTrackCollectionName
Name of the CDCTriggerTrack Store Array to be matched.
int m_minStereo
minimum number of stereo hits to consider a MCParticle as trackable
double m_minEfficiency
minimum efficiency
StoreArray< MCParticle > m_mcParticles
list of MCParticles to be matched
bool m_onlyPrimaries
switch for ignoring secondary particles
int m_minAxial
minimum number of axial hits to consider a MCParticle as trackable
StoreArray< CDCTriggerTrack > m_prTracks
list of CDCTriggerTracks to be matched
std::string m_hitCollectionName
Name of the StoreArray containing the hits that are used for the matching.
bool m_relateClonesAndMerged
switch for creating relations for clones and merged tracks
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.
void setDescription(const std::string &description)
Sets the description of the module.
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).
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool assign(TObject *object, bool replace=false)
Assign 'object' to this accessor.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool requireRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, const std::string &namedRelation="") const
Produce error if no relation from this array to 'toArray' has been registered.
T * appendNew()
Construct a new T object at the end of the array.
TClonesArray * getPtr() const
Raw access to the underlying TClonesArray.
int getEntries() const
Get the number of objects in the array.
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.