Skip to content

Commit d43105e

Browse files
authored
[PWGEM] Fix potential mismatches between data and MC table size (#17411)
1 parent 7baedef commit d43105e

2 files changed

Lines changed: 162 additions & 132 deletions

File tree

PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx

Lines changed: 128 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ struct AssociateMCInfoPhoton {
7373
kElectron = 0x8,
7474
};
7575

76+
static constexpr uint16_t kNoMcParticleMask = (1 << 14); // isNoise bit: no genuine MC particle for this leg/track
77+
7678
Produces<o2::aod::EMMCEvents> mcevents;
7779
Produces<o2::aod::EMMCEventLabels> mceventlabels;
7880
Produces<o2::aod::EMMCParticles> emmcparticles;
@@ -90,6 +92,7 @@ struct AssociateMCInfoPhoton {
9092
Configurable<float> maxPt{"maxPt", 20.f, "max pT for BinnedGenPts table"};
9193
Configurable<float> maxY{"maxY", 0.9f, "max |rapidity| for BinnedGenPts table"};
9294
Configurable<bool> doStoreAllDaughters{"doStoreAllDaughters", false, "flag to enable storing of all photon, pi0, eta, eta' and omega daughters. This will increase the dervied data size!"};
95+
Configurable<bool> useIsSelected{"useIsSelected", true, "flag to enable the usage of isSelected from our EM event selection. Disabling this will increase the derived data size!"};
9396

9497
HistogramRegistry registry{"EMMCEvent"};
9598

@@ -164,15 +167,34 @@ struct AssociateMCInfoPhoton {
164167
}
165168
}
166169

170+
template <soa::is_iterator TCollision>
171+
bool passesCollisionGate(TCollision const& collisionIter)
172+
{
173+
if (!collisionIter.has_mcCollision()) {
174+
return false;
175+
}
176+
if (useIsSelected.value && !collisionIter.isSelected()) {
177+
return false;
178+
}
179+
return true;
180+
}
181+
167182
template <o2::soa::is_iterator TMCParticle, o2::soa::is_iterator TMCCollision>
168183
void selectMothersToStore(int motherId, int64_t mcParticleSize, TMCParticle& motherParticle, TMCParticle& daughterIter, TMCCollision const& mcCollisionIter, std::unordered_map<uint64_t, int>& fNewLabels, std::map<uint64_t, int>& fNewLabelsReversed, std::unordered_map<uint64_t, int>& fEventIdx, std::unordered_map<uint64_t, int>& fEventLabels, Counter& fCounter)
169184
{
170185
while (motherId > -1) {
171-
if (motherId < mcParticleSize) { // protect against bad mother indices. why is this needed?
186+
if (motherId < mcParticleSize) {
172187
motherParticle.setCursor(motherId);
173-
int eventIdx = fEventLabels.find(mcCollisionIter.globalIndex())->second;
174188

175-
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
189+
auto evIt = fEventLabels.find(mcCollisionIter.globalIndex());
190+
if (evIt == fEventLabels.end()) {
191+
// Can't attribute this ancestor to a known event; stop walking rather than risk UB.
192+
LOG(warning) << "selectMothersToStore: mcCollision " << mcCollisionIter.globalIndex()
193+
<< " not found in fEventLabels, aborting mother-chain walk.";
194+
break;
195+
}
196+
int eventIdx = evIt->second;
197+
176198
if (!fNewLabels.contains(motherParticle.globalIndex())) {
177199
fNewLabels[motherParticle.globalIndex()] = fCounter.particles;
178200
fNewLabelsReversed[fCounter.particles] = motherParticle.globalIndex();
@@ -232,12 +254,7 @@ struct AssociateMCInfoPhoton {
232254
for (const auto& collision : collisions) {
233255
registry.fill(HIST("hEventCounter"), 1);
234256

235-
// TODO: investigate the collisions without corresponding mcCollision
236-
if (!collision.has_mcCollision()) {
237-
continue;
238-
}
239-
240-
if (!collision.isSelected()) {
257+
if (!passesCollisionGate(collision)) {
241258
continue;
242259
}
243260

@@ -359,122 +376,135 @@ struct AssociateMCInfoPhoton {
359376
auto o2TrackIter = o2tracks.begin();
360377
for (const auto& v0 : v0photons) {
361378
collisionIter.setCursor(v0.collisionId());
362-
if (!collisionIter.has_mcCollision()) {
363-
continue;
364-
}
365-
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
366379

367-
ele.setCursor(v0.negTrackId());
368-
pos.setCursor(v0.posTrackId());
380+
// check if the collision is valid AND the legs have valid MC particles
381+
bool validMc = false;
382+
if (passesCollisionGate(collisionIter)) {
383+
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
369384

370-
o2TrackEle.setCursor(ele.trackId());
371-
o2TrackPos.setCursor(pos.trackId());
385+
ele.setCursor(v0.negTrackId());
386+
pos.setCursor(v0.posTrackId());
387+
o2TrackEle.setCursor(ele.trackId());
388+
o2TrackPos.setCursor(pos.trackId());
372389

373-
if (!o2TrackEle.has_mcParticle() || !o2TrackPos.has_mcParticle()) {
374-
continue; // If no MC particle is found, skip the v0
390+
validMc = o2TrackEle.has_mcParticle() && o2TrackPos.has_mcParticle();
375391
}
376392

377-
for (const auto& leg : {pos, ele}) { // be carefull of order {pos, ele}!
378-
o2TrackIter.setCursor(leg.trackId());
379-
mcParticleIter.setCursor(o2TrackIter.mcParticleId());
380-
// LOGF(info, "mcParticleIter.globalIndex() = %d, mcParticleIter.index() = %d", mcParticleIter.globalIndex(), mcParticleIter.index()); // these are exactly the same.
381-
382-
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
383-
auto [iter, isNew] = fNewLabels.try_emplace(mcParticleIter.globalIndex(), fCounter.particles);
384-
if (isNew) {
385-
fNewLabelsReversed[fCounter.particles] = mcParticleIter.globalIndex();
386-
fEventIdx[mcParticleIter.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second;
387-
fCounter.particles++;
388-
}
389-
v0legmclabels(iter->second, o2TrackIter.mcMask());
393+
for (const auto& leg : {pos, ele}) { // careful: order {pos, ele}, must stay fixed either way
394+
if (validMc) {
395+
o2TrackIter.setCursor(leg.trackId());
396+
mcParticleIter.setCursor(o2TrackIter.mcParticleId());
397+
398+
auto [iter, isNew] = fNewLabels.try_emplace(mcParticleIter.globalIndex(), fCounter.particles);
399+
if (isNew) {
400+
fNewLabelsReversed[fCounter.particles] = mcParticleIter.globalIndex();
401+
auto evIt = fEventLabels.find(mcCollisionIter.globalIndex());
402+
if (evIt != fEventLabels.end()) {
403+
fEventIdx[mcParticleIter.globalIndex()] = evIt->second;
404+
}
405+
fCounter.particles++;
406+
}
407+
v0legmclabels(iter->second, o2TrackIter.mcMask());
390408

391-
// Next, store mother-chain of this reconstructed track.
392-
int motherid = -999; // first mother index
393-
if (mcParticleIter.has_mothers()) {
394-
motherid = mcParticleIter.mothersIds()[0]; // first mother index
409+
int motherid = -999;
410+
if (mcParticleIter.has_mothers()) {
411+
motherid = mcParticleIter.mothersIds()[0];
412+
}
413+
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter,
414+
fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
415+
} else {
416+
v0legmclabels(-1, kNoMcParticleMask); // no MC match for this leg, but the row must still exist
395417
}
396-
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter, fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
397-
} // end of leg loop
418+
} // end of loop over legs {pos, ele}
398419
} // end of v0 loop
399420
}
400421

401422
if constexpr (static_cast<bool>(system & kElectron)) {
402423
auto o2TrackIter = o2tracks.begin();
403-
// auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollisionEl, collision.globalIndex());
404424
for (const auto& emprimaryelectron : emprimaryelectrons) {
405425
collisionIter.setCursor(emprimaryelectron.collisionId());
406-
if (!collisionIter.has_mcCollision()) {
407-
continue;
408-
}
409-
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
410426

411-
o2TrackIter.setCursor(emprimaryelectron.trackId());
412-
if (!o2TrackIter.has_mcParticle()) {
413-
continue; // If no MC particle is found, skip the dilepton
414-
}
415-
mcParticleIter.setCursor(o2TrackIter.mcParticleId());
427+
int32_t mcLabel = -1;
428+
uint16_t mcMask = kNoMcParticleMask;
416429

417-
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
418-
auto [iter, isNew] = fNewLabels.try_emplace(mcParticleIter.globalIndex(), fCounter.particles);
419-
if (isNew) {
420-
fNewLabelsReversed[fCounter.particles] = mcParticleIter.globalIndex();
421-
fEventIdx[mcParticleIter.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second;
422-
fCounter.particles++;
423-
}
424-
emprimaryelectronmclabels(iter->second, o2TrackIter.mcMask());
430+
if (passesCollisionGate(collisionIter)) {
431+
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
432+
o2TrackIter.setCursor(emprimaryelectron.trackId());
433+
434+
if (o2TrackIter.has_mcParticle()) {
435+
mcParticleIter.setCursor(o2TrackIter.mcParticleId());
436+
437+
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
438+
auto [iter, isNew] = fNewLabels.try_emplace(mcParticleIter.globalIndex(), fCounter.particles);
439+
if (isNew) {
440+
fNewLabelsReversed[fCounter.particles] = mcParticleIter.globalIndex();
441+
auto evIt = fEventLabels.find(mcCollisionIter.globalIndex());
442+
if (evIt != fEventLabels.end()) {
443+
fEventIdx[mcParticleIter.globalIndex()] = evIt->second;
444+
}
445+
fCounter.particles++;
446+
}
447+
mcLabel = iter->second;
448+
mcMask = o2TrackIter.mcMask();
425449

426-
// Next, store mother-chain of this reconstructed track.
427-
int motherid = -999; // first mother index
428-
if (mcParticleIter.has_mothers()) {
429-
motherid = mcParticleIter.mothersIds()[0]; // first mother index
450+
int motherid = -999;
451+
if (mcParticleIter.has_mothers()) {
452+
motherid = mcParticleIter.mothersIds()[0];
453+
}
454+
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter,
455+
fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
456+
} // if (o2TrackIter.has_mcParticle())
430457
}
431-
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter, fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
458+
emprimaryelectronmclabels(mcLabel, mcMask); // always exactly one row per emprimaryelectron
432459
} // end of em primary electron loop
433460
}
434461

435462
if constexpr (static_cast<bool>(system & kEMC)) { // for emc photons
436-
// auto ememcclusters_coll = emcclusters.sliceBy(perCollisionEMC, collision.globalIndex());
437463
for (const auto& emccluster : emcclusters) {
438464
collisionIter.setCursor(emccluster.collisionId());
439-
if (!collisionIter.has_mcCollision()) {
440-
continue;
441-
}
442-
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
443465

444-
// TODO: test
445-
if (emccluster.mcParticleIds().size() <= 0) {
446-
continue;
447-
}
448466
std::vector<int32_t> vEmcMcParticleIds;
449467
std::vector<float> vAmplitudes;
450468

451-
vEmcMcParticleIds.reserve(emccluster.mcParticleIds().size());
452-
vAmplitudes.reserve(emccluster.mcParticleIds().size());
453-
454-
for (size_t iCont = 0; iCont < emccluster.mcParticleIds().size(); iCont++) {
455-
mcPhoton.setCursor(emccluster.mcParticleIds()[iCont]);
469+
if (passesCollisionGate(collisionIter)) {
470+
mcCollisionIter.setCursor(collisionIter.mcCollisionId());
456471

457-
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
458-
auto [iter, isNew] = fNewLabels.try_emplace(mcPhoton.globalIndex(), fCounter.particles);
459-
if (isNew) {
460-
fNewLabelsReversed[fCounter.particles] = mcPhoton.globalIndex();
461-
fEventIdx[mcPhoton.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second;
462-
fCounter.particles++;
472+
if (emccluster.mcParticleIds().size() != emccluster.amplitude().size()) {
473+
LOG(warning) << "Cluster " << emccluster.globalIndex()
474+
<< ": mcParticleIds/amplitude size mismatch ("
475+
<< emccluster.mcParticleIds().size() << " vs " << emccluster.amplitude().size() << ")";
463476
}
464-
vEmcMcParticleIds.emplace_back(iter->second);
465-
vAmplitudes.emplace_back(emccluster.amplitude()[iCont]);
466-
// ememcclustermclabels(fNewLabels.find(mcPhoton.index())->second);
467-
468-
// Next, store mother-chain of this reconstructed track.
469-
int motherid = -999; // first mother index
470-
if (mcPhoton.has_mothers()) {
471-
motherid = mcPhoton.mothersIds()[0]; // first mother index
477+
size_t nCont = std::min(emccluster.mcParticleIds().size(), emccluster.amplitude().size());
478+
479+
vEmcMcParticleIds.reserve(nCont);
480+
vAmplitudes.reserve(nCont);
481+
482+
for (size_t iCont = 0; iCont < nCont; iCont++) {
483+
mcPhoton.setCursor(emccluster.mcParticleIds()[iCont]);
484+
// if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack
485+
auto [iter, isNew] = fNewLabels.try_emplace(mcPhoton.globalIndex(), fCounter.particles);
486+
if (isNew) {
487+
fNewLabelsReversed[fCounter.particles] = mcPhoton.globalIndex();
488+
auto evIt = fEventLabels.find(mcCollisionIter.globalIndex());
489+
if (evIt != fEventLabels.end()) { // keep your earlier guard here too
490+
fEventIdx[mcPhoton.globalIndex()] = evIt->second;
491+
}
492+
fCounter.particles++;
493+
}
494+
vEmcMcParticleIds.emplace_back(iter->second);
495+
vAmplitudes.emplace_back(emccluster.amplitude()[iCont]);
496+
497+
int motherid = -999;
498+
if (mcPhoton.has_mothers()) {
499+
motherid = mcPhoton.mothersIds()[0];
500+
}
501+
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter,
502+
fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
472503
}
473-
selectMothersToStore(motherid, mcParticles.size(), motherParticle, daughterIter, mcCollisionIter, fNewLabels, fNewLabelsReversed, fEventIdx, fEventLabels, fCounter);
474504
} // end of loop over mc particles of the current emc cluster
505+
// whether or not the collision was okay, exactly one row is always written here so later the tables are ensured to have same size!
475506
ememcclustermclabels(vEmcMcParticleIds, vAmplitudes);
476-
477-
} // end of em emc cluster loop
507+
}
478508
}
479509

480510
// Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack
@@ -517,7 +547,12 @@ struct AssociateMCInfoPhoton {
517547
}
518548
}
519549

520-
emmcparticles(fEventIdx.find(oldLabel)->second, mcParticleIter.pdgCode(), mcParticleIter.flags(), mcParticleIter.statusCode(),
550+
auto evIt = fEventIdx.find(oldLabel);
551+
if (evIt == fEventIdx.end()) {
552+
LOG(warning) << "emmcparticles: no event index for particle label " << oldLabel << ", skipping.";
553+
continue;
554+
}
555+
emmcparticles(evIt->second, mcParticleIter.pdgCode(), mcParticleIter.flags(), mcParticleIter.statusCode(),
521556
mothers, daughters,
522557
mcParticleIter.px(), mcParticleIter.py(), mcParticleIter.pz(), mcParticleIter.e(),
523558
mcParticleIter.vx(), mcParticleIter.vy(), mcParticleIter.vz());

0 commit comments

Comments
 (0)