Skip to content

Commit ce13609

Browse files
committed
Track multiplicity source and simplify efficiency lookup
1 parent 0d7ee15 commit ce13609

3 files changed

Lines changed: 102 additions & 80 deletions

File tree

‎PWGCF/DataModel/CorrelationsDerived.h‎

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,24 @@ using CFMcParticle = CFMcParticles::iterator;
5858
namespace cfmultiplicity
5959
{
6060
DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float);
61-
DECLARE_SOA_COLUMN(MultiplicityEstimator, multiplicityEstimator, uint8_t); //! Source used for the multiplicity value
62-
enum EstimatorType : uint8_t {
63-
Tracks,
64-
FT0M,
65-
FT0C,
66-
FT0CVariant1,
67-
FT0CVariant2,
68-
FT0A,
69-
CentNGlobal,
70-
Run2V0M,
71-
MCParticles,
72-
};
61+
DECLARE_SOA_COLUMN(IsTrackMultiplicity, isTrackMultiplicity, bool); //! Whether MultiplicitySelector::processTracks produced the multiplicity
7362
} // namespace cfmultiplicity
74-
DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity, cfmultiplicity::MultiplicityEstimator);
63+
DECLARE_SOA_TABLE(CFMultiplicities, "AOD", "CFMULTIPLICITY", cfmultiplicity::Multiplicity, cfmultiplicity::IsTrackMultiplicity);
7564

7665
using CFMultiplicity = CFMultiplicities::iterator;
7766

7867
namespace cfcollision
7968
{
80-
DECLARE_SOA_INDEX_COLUMN(CFMcCollision, cfMcCollision); //! Index to reduced MC collision; o2-linter: disable=name/o2-column (preserve the established derived-table API)
81-
DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Centrality/multiplicity value
69+
DECLARE_SOA_INDEX_COLUMN(CFMcCollision, cfMcCollision); //! Index to reduced MC collision; o2-linter: disable=name/o2-column (preserve the established derived-table API)
70+
DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Centrality/multiplicity value
71+
DECLARE_SOA_COLUMN(BestRecoCollision, bestRecoCollision, bool); //! Whether this is the best reconstructed collision for the associated MC collision (largest number of contributors)
8272
} // namespace cfcollision
8373
DECLARE_SOA_TABLE(CFCollisions, "AOD", "CFCOLLISION", //! Reduced collision table
8474
o2::soa::Index<>,
8575
bc::RunNumber, collision::PosZ,
8676
cfcollision::Multiplicity, timestamp::Timestamp);
8777
DECLARE_SOA_TABLE(CFCollLabels, "AOD", "CFCOLLLABEL", //! Labels for reduced collision table
88-
cfcollision::CFMcCollisionId);
78+
cfcollision::CFMcCollisionId, cfcollision::BestRecoCollision);
8979
using CFCollision = CFCollisions::iterator;
9080
using CFCollLabel = CFCollLabels::iterator;
9181
using CFCollisionsWithLabel = soa::Join<CFCollisions, CFCollLabels>;
@@ -136,7 +126,6 @@ enum MultiplicityEstimators : uint8_t {
136126
MultNTracksGlobal = 0x8,
137127
CentFT0M = 0x10,
138128
};
139-
140129
inline constexpr uint32_t NMultiplicityEstimators = __builtin_ctz(CentFT0M) + 1;
141130

142131
} // namespace cfmultset

‎PWGCF/TableProducer/filterCorrelations.cxx‎

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)