@@ -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