@@ -153,6 +153,7 @@ struct FilterCF {
153153
154154 // Own local histograms independently of their input file. CCDB owns its objects.
155155 std::unique_ptr<THn> localMultiplicityEfficiency;
156+ THn* mEfficiency = nullptr ;
156157 static constexpr int MultiplicityEfficiencyDimensions = 4 ;
157158
158159 // persistent caches
@@ -179,7 +180,9 @@ struct FilterCF {
179180 return ;
180181 }
181182 auto * efficiency = dynamic_cast <THn*>(file->Get (" ccdb_object" ));
182- validateMultiplicityEfficiency (efficiency);
183+ if (!efficiency || efficiency->GetNdimensions () != MultiplicityEfficiencyDimensions) {
184+ LOGF (fatal, " Multiplicity efficiency from %s must be a 4D THn with axes (eta, pT, multiplicity, z-vtx)" , cfgEfficiencyMultiplicity.value .c_str ());
185+ }
183186 localMultiplicityEfficiency.reset (dynamic_cast <THn*>(efficiency->Clone ()));
184187 } else {
185188 ccdb->setURL (" http://alice-ccdb.cern.ch" );
@@ -336,67 +339,69 @@ struct FilterCF {
336339 return dcaXyConst + dcaXySlope / pt; // a + b/pT
337340 }
338341
339- void validateMultiplicityEfficiency (const THn* efficiency) const
340- {
341- if (!efficiency || efficiency->GetNdimensions () != MultiplicityEfficiencyDimensions) {
342- LOGF (fatal, " Multiplicity efficiency from %s must be a 4D THn with axes (eta, pT, multiplicity, z-vtx)" , cfgEfficiencyMultiplicity.value .c_str ());
343- }
344- }
345-
346342 THn* loadMultiplicityEfficiency (uint64_t timestamp)
347343 {
348344 if (cfgLocalEfficiency == 1 ) {
349345 return localMultiplicityEfficiency.get ();
350346 }
351- // Query each collision so the manager can refresh its cache at validity boundaries.
352- auto * efficiency = ccdb->getForTimeStamp <THnT<float >>(cfgEfficiencyMultiplicity.value , timestamp);
353- validateMultiplicityEfficiency (efficiency);
354- return efficiency;
347+ if (!mEfficiency || !ccdb->isCachedObjectValid (cfgEfficiencyMultiplicity.value , timestamp)) {
348+ mEfficiency = ccdb->getForTimeStamp <THnT<float >>(cfgEfficiencyMultiplicity.value , timestamp);
349+ }
350+ if (!mEfficiency || mEfficiency ->GetNdimensions () != MultiplicityEfficiencyDimensions) {
351+ LOGF (fatal, " Multiplicity efficiency from %s must be a 4D THn with axes (eta, pT, multiplicity, z-vtx)" , cfgEfficiencyMultiplicity.value .c_str ());
352+ }
353+ return mEfficiency ;
355354 }
356355
357- template <bool applyDCA, typename TCollision, typename TTracks>
356+ template <typename TCollision, typename TTracks>
358357 float getCorrectedMultiplicity (const TCollision& collision, const TTracks& tracks, uint64_t timestamp)
359358 {
360- if (collision.multiplicityEstimator () != aod::cfmultiplicity::Tracks ) {
361- LOGF (fatal, " Efficiency-corrected multiplicity requires MultiplicitySelector::processTracks, but estimator type %u was configured " , static_cast < unsigned int >(collision. multiplicityEstimator ()) );
359+ if (! collision.isTrackMultiplicity () ) {
360+ LOGF (fatal, " Efficiency-corrected multiplicity requires MultiplicitySelector::processTracks" );
362361 }
363362 auto * efficiency = loadMultiplicityEfficiency (timestamp);
364363 double correctedMultiplicity = 0 .;
364+ size_t skippedTracks = 0 ;
365365 for (const auto & track : tracks) {
366366 // Match the tracks written by the corresponding data/MC producer path.
367- if constexpr (applyDCA) {
368- if (std::abs (track.dcaXY ()) > getMaxDCAxy (track.pt ()) || std::abs (track.dcaZ ()) > dcazmax) {
369- continue ;
370- }
371- }
372- const auto mask = static_cast <uint8_t >(cfgMultiplicityTrackBitMask.value );
373- if (mask != 0 && (getTrackType (track) & mask) != mask) {
367+ if (!isTrackSelected (track, true )) {
374368 continue ;
375369 }
376-
377370 // The map contains RecoAll / MC, not inverse-efficiency weights.
378371 // Keep the original estimator as the map coordinate, including for centrality.
379372 const std::array<double , MultiplicityEfficiencyDimensions> values{track.eta (), track.pt (), collision.multiplicity (), collision.posZ ()};
380- std::array<int , MultiplicityEfficiencyDimensions> bins{};
381- for (int axis = 0 ; axis < MultiplicityEfficiencyDimensions; ++axis) {
382- auto * efficiencyAxis = efficiency->GetAxis (axis);
383- bins[axis] = efficiencyAxis->FindFixBin (values[axis]);
384- if (!std::isfinite (values[axis]) || bins[axis] < 1 || bins[axis] > efficiencyAxis->GetNbins ()) {
385- LOGF (fatal, " Multiplicity efficiency from %s does not cover axis %d value %g" , cfgEfficiencyMultiplicity.value .c_str (), axis, values[axis]);
386- }
387- }
388- const double eff = efficiency->GetBinContent (bins.data ());
373+ const double eff = efficiency->GetBinContent (efficiency->GetBin (values.data ()));
389374 if (!std::isfinite (eff) || eff <= 0 .) {
390- LOGF (fatal, " Invalid multiplicity efficiency %g from %s at bins (%d, %d, %d, %d)" , eff, cfgEfficiencyMultiplicity.value .c_str (), bins[0 ], bins[1 ], bins[2 ], bins[3 ]);
375+ ++skippedTracks;
376+ continue ;
391377 }
392378 correctedMultiplicity += 1 . / eff;
393379 }
380+ if (cfgVerbosity > 0 && skippedTracks > 0 ) {
381+ LOGF (warning, " Skipped %zu tracks with invalid efficiency while correcting collision %lld" , skippedTracks, static_cast <int64_t >(collision.globalIndex ()));
382+ }
394383 if (!std::isfinite (correctedMultiplicity) || correctedMultiplicity > std::numeric_limits<float >::max ()) {
395384 LOGF (fatal, " Corrected multiplicity cannot be represented as a float: %g" , correctedMultiplicity);
396385 }
397386 return static_cast <float >(correctedMultiplicity);
398387 }
399388
389+ template <typename TTrack>
390+ bool isTrackSelected (const TTrack& track, bool checkTrackBitMask = false )
391+ {
392+ const float maxDCAxy = getMaxDCAxy (track.pt ());
393+ if (std::abs (track.dcaXY ()) > maxDCAxy || std::abs (track.dcaZ ()) > dcazmax) {
394+ return false ;
395+ }
396+ if (checkTrackBitMask) {
397+ const auto mask = static_cast <uint8_t >(cfgMultiplicityTrackBitMask.value );
398+ if (mask != 0 && (getTrackType (track) & mask) != mask) {
399+ return false ;
400+ }
401+ }
402+ return true ;
403+ }
404+
400405 template <class T >
401406 using HasMultTables = decltype (std::declval<T&>().multNTracksPV());
402407
@@ -417,7 +422,7 @@ struct FilterCF {
417422 auto bc = collision.template bc_as <aod::BCsWithTimestamps>();
418423 outputCollisions (bc.runNumber (), collision.posZ (), collision.multiplicity (), bc.timestamp ());
419424 if (!cfgEfficiencyMultiplicity.value .empty ()) {
420- outputCollisionsExtra (getCorrectedMultiplicity< true > (collision, tracks, bc.timestamp ()));
425+ outputCollisionsExtra (getCorrectedMultiplicity (collision, tracks, bc.timestamp ()));
421426 }
422427
423428 if constexpr (std::experimental::is_detected<HasMultTables, C1 >::value) {
@@ -444,8 +449,7 @@ struct FilterCF {
444449 outputCollRefs (collision.globalIndex ());
445450 }
446451 for (const auto & track : tracks) {
447- float maxDCAxy = getMaxDCAxy (track.pt ());
448- if ((std::abs (track.dcaXY ()) > maxDCAxy) || (std::abs (track.dcaZ ()) > dcazmax)) {
452+ if (!isTrackSelected (track)) {
449453 continue ;
450454 }
451455
@@ -487,8 +491,7 @@ struct FilterCF {
487491 if (!track.isGlobalTrack ()) {
488492 continue ; // trackQA for global tracks only
489493 }
490- float maxDCAxy = getMaxDCAxy (track.pt ());
491- if ((std::abs (track.dcaXY ()) > maxDCAxy) || (std::abs (track.dcaZ ()) > dcazmax)) {
494+ if (!isTrackSelected (track)) {
492495 continue ;
493496 }
494497 registrytrackQA.fill (HIST (" eta" ), track.eta ());
@@ -530,6 +533,9 @@ struct FilterCF {
530533 mcParticleLabelsCache.push_back (-1 );
531534 }
532535
536+ std::vector<int64_t > bestRecoCollisionIndices (mcCollisions.size (), -1 );
537+ std::vector<int > bestRecoCollisionNContrib (mcCollisions.size (), -1 );
538+
533539 // PASS 1 on collisions: check which particles are kept
534540 for (const auto & collision : allCollisions) {
535541 auto groupedTracks = tracks.sliceBy (perCollision, collision.globalIndex ());
@@ -541,6 +547,12 @@ struct FilterCF {
541547 continue ;
542548 }
543549
550+ const auto mcCollisionId = collision.mcCollisionId ();
551+ if (mcCollisionId >= 0 && mcCollisionId < static_cast <int64_t >(bestRecoCollisionIndices.size ()) && collision.numContrib () > bestRecoCollisionNContrib[mcCollisionId]) {
552+ bestRecoCollisionNContrib[mcCollisionId] = collision.numContrib ();
553+ bestRecoCollisionIndices[mcCollisionId] = collision.globalIndex ();
554+ }
555+
544556 for (const auto & track : groupedTracks) {
545557 if (track.has_mcParticle ()) {
546558 mcReconstructedCache[track.mcParticleId ()] = true ;
@@ -608,9 +620,12 @@ struct FilterCF {
608620 // NOTE works only when we store all MC collisions (as we do here)
609621 outputCollisions (bc.runNumber (), collision.posZ (), collision.multiplicity (), bc.timestamp ());
610622 if (!cfgEfficiencyMultiplicity.value .empty ()) {
611- outputCollisionsExtra (getCorrectedMultiplicity< false > (collision, groupedTracks, bc.timestamp ()));
623+ outputCollisionsExtra (getCorrectedMultiplicity (collision, groupedTracks, bc.timestamp ()));
612624 }
613- outputMcCollisionLabels (collision.mcCollisionId ());
625+
626+ const auto mcCollisionId = collision.mcCollisionId ();
627+ const bool bestRecoCollision = mcCollisionId >= 0 && mcCollisionId < static_cast <int64_t >(bestRecoCollisionIndices.size ()) && bestRecoCollisionIndices[mcCollisionId] == collision.globalIndex ();
628+ outputMcCollisionLabels (mcCollisionId, bestRecoCollision);
614629
615630 if constexpr (std::experimental::is_detected<HasMultTables, C1 >::value) {
616631 multiplicities.clear ();
@@ -662,7 +677,7 @@ struct FilterCF {
662677 using McCollisionsWithHepMC = soa::Join<aod::McCollisions, aod::HepMCXSections>;
663678 void processMC (McCollisionsWithHepMC const & mcCollisions, aod::McParticles const & allParticles,
664679 soa::Join<aod::McCollisionLabels, aod::Collisions, aod::EvSels, aod::CFMultiplicities> const & allCollisions,
665- soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels, aod::TrackSelection>> const & tracks,
680+ soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod:: McTrackLabels, aod::TrackSelection>> const & tracks,
666681 aod::BCsWithTimestamps const & bcs)
667682 {
668683 processMCT (mcCollisions, allParticles, allCollisions, tracks, bcs);
@@ -681,7 +696,7 @@ struct FilterCF {
681696
682697 void processMCMults (McCollisionsWithHepMC const & mcCollisions, aod::McParticles const & allParticles,
683698 soa::Join<aod::McCollisionLabels, aod::Collisions, aod::EvSels, aod::CFMultiplicities, aod::CentFT0Cs, aod::PVMults, aod::FV0Mults, aod::MultsGlobal> const & allCollisions,
684- soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::McTrackLabels, aod::TrackSelection>> const & tracks,
699+ soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod:: McTrackLabels, aod::TrackSelection>> const & tracks,
685700 aod::BCsWithTimestamps const & bcs)
686701 {
687702 processMCT (mcCollisions, allParticles, allCollisions, tracks, bcs);
@@ -761,69 +776,69 @@ struct MultiplicitySelector {
761776
762777 void processTracks (aod::Collision const &, soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection>> const & tracks)
763778 {
764- output (tracks.size (), aod::cfmultiplicity::Tracks );
779+ output (tracks.size (), true );
765780 }
766781 PROCESS_SWITCH (MultiplicitySelector, processTracks, " Select track count as multiplicity" , false );
767782
768783 void processFT0M (aod::CentFT0Ms const & centralities)
769784 {
770785 for (const auto & c : centralities) {
771- output (c.centFT0M (), aod::cfmultiplicity:: FT0M );
786+ output (c.centFT0M (), false );
772787 }
773788 }
774789 PROCESS_SWITCH (MultiplicitySelector, processFT0M, " Select FT0M centrality as multiplicity" , false );
775790
776791 void processFT0C (aod::CentFT0Cs const & centralities)
777792 {
778793 for (const auto & c : centralities) {
779- output (c.centFT0C (), aod::cfmultiplicity:: FT0C );
794+ output (c.centFT0C (), false );
780795 }
781796 }
782797 PROCESS_SWITCH (MultiplicitySelector, processFT0C, " Select FT0C centrality as multiplicity" , false );
783798
784799 void processFT0CVariant1 (aod::CentFT0CVariant1s const & centralities)
785800 {
786801 for (const auto & c : centralities) {
787- output (c.centFT0CVariant1 (), aod::cfmultiplicity::FT0CVariant1 );
802+ output (c.centFT0CVariant1 (), false );
788803 }
789804 }
790805 PROCESS_SWITCH (MultiplicitySelector, processFT0CVariant1, " Select FT0CVariant1 centrality as multiplicity" , false );
791806
792807 void processFT0CVariant2 (aod::CentFT0CVariant2s const & centralities)
793808 {
794809 for (const auto & c : centralities) {
795- output (c.centFT0CVariant2 (), aod::cfmultiplicity::FT0CVariant2 );
810+ output (c.centFT0CVariant2 (), false );
796811 }
797812 }
798813 PROCESS_SWITCH (MultiplicitySelector, processFT0CVariant2, " Select FT0CVariant2 centrality as multiplicity" , false );
799814
800815 void processFT0A (aod::CentFT0As const & centralities)
801816 {
802817 for (const auto & c : centralities) {
803- output (c.centFT0A (), aod::cfmultiplicity:: FT0A );
818+ output (c.centFT0A (), false );
804819 }
805820 }
806821 PROCESS_SWITCH (MultiplicitySelector, processFT0A, " Select FT0A centrality as multiplicity" , false );
807822
808823 void processCentNGlobal (aod::CentNGlobals const & centralities)
809824 {
810825 for (const auto & c : centralities) {
811- output (c.centNGlobal (), aod::cfmultiplicity::CentNGlobal );
826+ output (c.centNGlobal (), false );
812827 }
813828 }
814829 PROCESS_SWITCH (MultiplicitySelector, processCentNGlobal, " Select CentNGlobal centrality as multiplicity" , false );
815830
816831 void processRun2V0M (aod::CentRun2V0Ms const & centralities)
817832 {
818833 for (const auto & c : centralities) {
819- output (c.centRun2V0M (), aod::cfmultiplicity::Run2V0M );
834+ output (c.centRun2V0M (), false );
820835 }
821836 }
822837 PROCESS_SWITCH (MultiplicitySelector, processRun2V0M, " Select V0M centrality as multiplicity" , true );
823838
824839 void processMCGen (aod::McCollision const &, aod::McParticles const & particles)
825840 {
826- output (particles.size (), aod::cfmultiplicity::MCParticles );
841+ output (particles.size (), false );
827842 }
828843 PROCESS_SWITCH (MultiplicitySelector, processMCGen, " Select MC particle count as multiplicity" , false );
829844};
0 commit comments