From f80465ddfd1e8e490ce7c19e69dcf48baf8af1ab Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Mon, 1 Jun 2026 09:50:33 +0200 Subject: [PATCH 1/3] Adding functionality for event mixing across multiple TFs --- PWGDQ/Core/MixingHandler.cxx | 90 ++++++++-------- PWGDQ/Core/MixingHandler.h | 142 ++++++++++++++++++++++++-- PWGDQ/Core/MixingLibrary.cxx | 92 ++++++++--------- PWGDQ/Core/VarManager.h | 20 ++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 114 +++++++++++++++++++++ 5 files changed, 354 insertions(+), 104 deletions(-) diff --git a/PWGDQ/Core/MixingHandler.cxx b/PWGDQ/Core/MixingHandler.cxx index 5fd601f67d0..834fa14e91c 100644 --- a/PWGDQ/Core/MixingHandler.cxx +++ b/PWGDQ/Core/MixingHandler.cxx @@ -27,9 +27,11 @@ ClassImp(MixingHandler); //_________________________________________________________________________ MixingHandler::MixingHandler() : TNamed(), - fIsInitialized(kFALSE), + fIsInitialized(false), fVariableLimits(), - fVariables() + fVariables(), + fPoolDepth(0), + fPools() { // // default constructor @@ -38,9 +40,11 @@ MixingHandler::MixingHandler() : TNamed(), //_________________________________________________________________________ MixingHandler::MixingHandler(const char* name, const char* title) : TNamed(name, title), - fIsInitialized(kFALSE), + fIsInitialized(false), fVariableLimits(), - fVariables() + fVariables(), + fPoolDepth(0), + fPools() { // // Named constructor @@ -56,29 +60,13 @@ MixingHandler::~MixingHandler() } //_________________________________________________________________________ -void MixingHandler::AddMixingVariable(int var, int nBins, float* binLims) +void MixingHandler::AddMixingVariable(int var, std::vector binLims) { - // - // add a mixing variable - // - fVariables.push_back(var); - TArrayF varBins; - varBins.Set(nBins, binLims); - fVariableLimits.push_back(varBins); - VarManager::SetUseVariable(var); -} - -//_________________________________________________________________________ -void MixingHandler::AddMixingVariable(int var, int nBins, std::vector binLims) -{ - - float* bins = new float[nBins]; - for (int i = 0; i < nBins; ++i) { - bins[i] = binLims[i]; - } - AddMixingVariable(var, nBins, bins); + fVariables[var] = fVariableLimits.size(); + fVariableLimits.push_back(binLims); } +/* //_________________________________________________________________________ int MixingHandler::GetMixingVariable(VarManager::Variables var) { @@ -90,7 +78,9 @@ int MixingHandler::GetMixingVariable(VarManager::Variables var) } return -1; } +*/ +/* //_________________________________________________________________________ std::vector MixingHandler::GetMixingVariableLimits(VarManager::Variables var) { @@ -105,21 +95,21 @@ std::vector MixingHandler::GetMixingVariableLimits(VarManager::Variables } } return binLimits; -} +}*/ //_________________________________________________________________________ void MixingHandler::Init() { - // - // Initialization of pools - // The correct event category will be retrieved using the function FindEventCategory() - // - int size = 1; - for (auto v : fVariableLimits) { - size *= (v.GetSize() - 1); + // loop over all variables and create a mixing pool for each category defined by the binning of the variables + int nCategories = 1; + for (auto& var : fVariables) { + nCategories *= (fVariableLimits[var.second].size() - 1); } - (void)size; - fIsInitialized = kTRUE; + // add elements in the map for each category (the key is the category and the value is an empty pool) + for (int i = 0; i < nCategories; i++) { + fPools[i] = MixingPool(); + } + fIsInitialized = true; } //_________________________________________________________________________ @@ -135,16 +125,21 @@ int MixingHandler::FindEventCategory(float* values) Init(); } + // loop over the variables and find out in which bin the value of the variable for the event is located std::vector bin; - int iVar = 0; - for (auto v = fVariableLimits.begin(); v != fVariableLimits.end(); v++, iVar++) { - int binValue = TMath::BinarySearch((*v).GetSize(), (*v).GetArray(), values[fVariables[iVar]]); - bin.push_back(binValue); - if (bin[iVar] == -1 || bin[iVar] == (*v).GetSize() - 1) { + for (auto [var, pos] : fVariables) { + // check that the value is within limits, if not return -1 to exclude the event from mixing + size_t binValue = std::distance(fVariableLimits[pos].begin(), std::upper_bound(fVariableLimits[pos].begin(), fVariableLimits[pos].end(), values[var])); + if (binValue == 0 || binValue == fVariableLimits[pos].size()) { return -1; // all variables must be inside limits } - } + bin.push_back(binValue - 1); + } + // Hash the bin values to define a unique category + // The hashing is done such that the original bin values can be retrieved from the category + // For example, for 3 variables with n1, n2, n3 bins respectively, the category for bin values (b1, b2, b3) would be: + // category = b1*(n2*n3) + b2*(n3) + b3 int category = 0; int tempCategory = 1; int iv1 = 0; @@ -156,7 +151,7 @@ int MixingHandler::FindEventCategory(float* values) if (iv2 == iv1) { tempCategory *= bin[iv2]; } else { - tempCategory *= (fVariableLimits[iv2].GetSize() - 1); + tempCategory *= (fVariableLimits[iv2].size() - 1); } } category += tempCategory; @@ -175,19 +170,14 @@ int MixingHandler::GetBinFromCategory(VarManager::Variables var, int category) c } // Search for the position of the variable "var" in the internal variable list of the handler - int tempVar = 0; - for (auto v = fVariables.begin(); v != fVariables.end(); v++, tempVar++) { - if (*v == var) { - break; - } - } + int ivar = fVariables.at(var); // extract the bin position in variable "var" from the category int norm = 1; - for (int i = fVariables.size() - 1; i > tempVar; --i) { - norm *= (fVariableLimits[i].GetSize() - 1); + for (int i = fVariables.size() - 1; i > ivar; --i) { + norm *= (fVariableLimits[i].size() - 1); } int truncatedCategory = category - (category % norm); truncatedCategory /= norm; - return truncatedCategory % (fVariableLimits[tempVar].GetSize() - 1); + return truncatedCategory % (fVariableLimits[ivar].size() - 1); } diff --git a/PWGDQ/Core/MixingHandler.h b/PWGDQ/Core/MixingHandler.h index f73d5632895..6d720c8d578 100644 --- a/PWGDQ/Core/MixingHandler.h +++ b/PWGDQ/Core/MixingHandler.h @@ -25,23 +25,145 @@ #include #include +#include +#include +#include class MixingHandler : public TNamed { public: + + // Struct to define track properties relevant for mixing and few utility functions + struct MixingTrack { + float pt; + float eta; + float phi; + uint32_t filteringFlags; + // flip a bit to zero (needed when a track was already used in mixing for that bit for the required pool depth) + void FlipBit(int64_t mask) { filteringFlags ^= mask;} + void Print() const { + std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", filteringFlags: " << filteringFlags << std::endl; + } + }; + + // Struct to define events used in mixing and few utility functions. + // An event is defined as two vectors of tracks (typically the legs of a two-body + //decay or the two-particles in a correlation analysis) + struct MixingEvent { + std::vector tracks1; + std::vector tracks2; + // bit map for active filtering bits of all the tracks + uint32_t filteringMask = 0; + // counters to keep track of how many times the event was used for mixing (for each track cut separately) + std::array counters = {0}; + // add a track to the event and update the filtering mask accordingly + void AddTrack1(const MixingTrack& track) { + tracks1.push_back(track); + filteringMask |= track.filteringFlags; + } + void AddTrack2(const MixingTrack& track) { + tracks2.push_back(track); + filteringMask |= track.filteringFlags; + } + // flip bits in the filtering mask + void FlipFilteringMask(int64_t mask) { filteringMask ^= mask; } + // 1) increment the counters for a given track cut bit mask and if the counters reached the pool depth, + // 2) flip the corresponding bit in the tracks filtering flags to exclude them from further mixing + // 3) for each track, if there are no more active bits in the filtering mask, then remove the track from the event + void IncrementCounters(uint32_t mask, short poolDepth) { + for (int i = 0; i < 32; i++) { + if (mask & (1ULL << i)) { + counters[i]++; + if (counters[i] >= poolDepth) { + for (auto& track : tracks1) { + track.FlipBit(1ULL << i); + if (track.filteringFlags == 0) { + track = tracks1.back(); + tracks1.pop_back(); + } + } + for (auto& track : tracks2) { + track.FlipBit(1ULL << i); + if (track.filteringFlags == 0) { + track = tracks2.back(); + tracks2.pop_back(); + } + } + FlipFilteringMask(1ULL << i); + } + } + } + } + void Print() const { + std::cout << "Event filtering mask: "; + for (int i = 0; i < 32; i++) { + if (filteringMask & (1ULL << i)) { + std::cout << "1"; + } else { + std::cout << "0"; + } + } + std::cout << std::endl; + for (int i = 0; i < 32; i++) { + if (filteringMask & (1ULL << i)) { + std::cout << "Counter " << i << ": " << counters[i] << std::endl; + } + } + std::cout << "Tracks 1: " << std::endl; + for (const auto& track : tracks1) { + track.Print(); + } + std::cout << "Tracks 2: " << std::endl; + for (const auto& track : tracks2) { + track.Print(); + } + } + }; + + struct MixingPool { + std::vector events; + + // check which events in the pool are empty (i.e. no active tracks for mixing) and remove them from the pool + void CleanPool() { + events.erase(std::remove_if(events.begin(), events.end(), + [](const MixingEvent& event) { return event.tracks1.empty() && event.tracks2.empty(); }), + events.end()); + } + // The function that performs the mixing is called outside this class, but the pool provides the events and tracks to be mixed and takes care of updating the events after mixing + // (e.g. incrementing the counters and removing the tracks that reached the pool depth for a given cut) + void UpdatePool(const MixingEvent& event, short poolDepth) { + for (auto& event : events) { + event.IncrementCounters(event.filteringMask, poolDepth); + } + CleanPool(); + events.push_back(event); + } + // getter for the events in the pool + const std::vector& GetEvents() const { return events; } + + void Print() const { + std::cout << "Mixing pool with " << events.size() << " events:" << std::endl; + for (const auto& event : events) { + event.Print(); + } + } + }; + MixingHandler(); MixingHandler(const char* name, const char* title); virtual ~MixingHandler(); // setters - void AddMixingVariable(int var, int nBins, float* binLims); - void AddMixingVariable(int var, int nBins, std::vector binLims); + void AddMixingVariable(int var, std::vector binLims); + void SetPoolDepth(short depth) { fPoolDepth = depth; } // getters - int GetNMixingVariables() const { return fVariables.size(); } - int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly - std::vector GetMixingVariableLimits(VarManager::Variables var); + //int GetNMixingVariables() const { return fVariables.size(); } + //int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly + //std::vector GetMixingVariableLimits(VarManager::Variables var); + MixingPool& GetPool(int category) { return fPools[category]; } + short GetPoolDepth() const { return fPoolDepth; } void Init(); int FindEventCategory(float* values); @@ -54,10 +176,14 @@ class MixingHandler : public TNamed // User options bool fIsInitialized; // check if the mixing handler is initialized - std::vector fVariableLimits; - std::vector fVariables; + // bin limits for the variables used for mixing, the number of vectors corresponds to the number of variables and the content of each vector corresponds to the bin limits for that variable + std::vector> fVariableLimits; + std::map fVariables; // key: variable, value: position in the internal variable list of the handler (used to map the variables to the values passed to FindEventCategory) + + short fPoolDepth; // number of events to be kept in each pool + std::map fPools; // key: category, value: pool of events corresponding to that category - ClassDef(MixingHandler, 1); + ClassDef(MixingHandler, 2); }; #endif // PWGDQ_CORE_MIXINGHANDLER_H_ diff --git a/PWGDQ/Core/MixingLibrary.cxx b/PWGDQ/Core/MixingLibrary.cxx index 28e453b5479..b152de7d27c 100644 --- a/PWGDQ/Core/MixingLibrary.cxx +++ b/PWGDQ/Core/MixingLibrary.cxx @@ -31,183 +31,183 @@ void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible std::string nameStr = mixingVarible; if (!nameStr.compare("Centrality1")) { std::vector fCentLimsHashing = {0.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality2")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality3")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality4")) { std::vector fCentLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality5")) { std::vector fCentLimsHashing = {0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("Centrality6")) { std::vector fCentLimsHashing = {0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing.size(), fCentLimsHashing); + mh->AddMixingVariable(VarManager::kCentVZERO, fCentLimsHashing); } if (!nameStr.compare("CentralityFT0C1")) { std::vector fCentFT0CLimsHashing = {0.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C2")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C3")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C4")) { std::vector fCentFT0CLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C5")) { std::vector fCentFT0CLimsHashing = {0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("CentralityFT0C6")) { std::vector fCentFT0CLimsHashing = {0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}; - mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing.size(), fCentFT0CLimsHashing); + mh->AddMixingVariable(VarManager::kCentFT0C, fCentFT0CLimsHashing); } if (!nameStr.compare("Mult1")) { std::vector fMultLimsHashing = {0.0f, 10.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 120.0f, 160.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Mult2")) { std::vector fMultLimsHashing = {0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 120.0f, 140.0f, 180.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Mult3")) { std::vector fMultLimsHashing = {0.0f, 5.0f, 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 45.0f, 50.0f, 55.0f, 60.0f, 65.0f, 70.0f, 75.0f, 80.0f, 85.0f, 90.0f, 100.0f, 120.0f, 140.0f, 165.0f, 200.0f, 350.0f}; - mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing.size(), fMultLimsHashing); + mh->AddMixingVariable(VarManager::kVtxNcontrib, fMultLimsHashing); } if (!nameStr.compare("Vtx1")) { std::vector fZLimsHashing = {-10.0f, 0.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx2")) { std::vector fZLimsHashing = {-10.0f, -5.0f, 0.0f, 5.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx3")) { std::vector fZLimsHashing = {-10.0f, -7.5f, -5.0f, -2.5f, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx4")) { std::vector fZLimsHashing = {-10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Vtx5")) { std::vector fZLimsHashing = {-10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}; - mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing.size(), fZLimsHashing); + mh->AddMixingVariable(VarManager::kVtxZ, fZLimsHashing); } if (!nameStr.compare("Occupancy1")) { std::vector fOccLimsHashing = {0.0f, 500.0f, 1000.0f, 2000.0f, 3000.0f, 6000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Occupancy2")) { std::vector fOccLimsHashing = {0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 6000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Occupancy3")) { std::vector fOccLimsHashing = {0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}; - mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing.size(), fOccLimsHashing); + mh->AddMixingVariable(VarManager::kTrackOccupancyInTimeRange, fOccLimsHashing); } if (!nameStr.compare("Psi2A1")) { std::vector fPsi2A = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A2")) { std::vector fPsi2A = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A3")) { std::vector fPsi2A = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A4")) { std::vector fPsi2A = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2A5")) { std::vector fPsi2A = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A.size(), fPsi2A); + mh->AddMixingVariable(VarManager::kPsi2A, fPsi2A); } if (!nameStr.compare("Psi2B1")) { std::vector fPsi2B = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B2")) { std::vector fPsi2B = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B3")) { std::vector fPsi2B = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B4")) { std::vector fPsi2B = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2B5")) { std::vector fPsi2B = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B.size(), fPsi2B); + mh->AddMixingVariable(VarManager::kPsi2B, fPsi2B); } if (!nameStr.compare("Psi2C1")) { std::vector fPsi2C = {-TMath::Pi() / 2., 0.0f, TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C2")) { std::vector fPsi2C = {-TMath::Pi() / 2., -TMath::Pi() / 4., 0.0f, TMath::Pi() / 4., TMath::Pi() / 2.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C3")) { std::vector fPsi2C = {-4 * TMath::Pi() / 8., -3 * TMath::Pi() / 8., -2 * TMath::Pi() / 8., -TMath::Pi() / 8., 0.0f, TMath::Pi() / 8., 2 * TMath::Pi() / 8., 3 * TMath::Pi() / 8., 4 * TMath::Pi() / 8.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C4")) { std::vector fPsi2C = {-8 * TMath::Pi() / 16., -7 * TMath::Pi() / 16., -6 * TMath::Pi() / 16., -5 * TMath::Pi() / 16., -4 * TMath::Pi() / 16., -3 * TMath::Pi() / 16., -2 * TMath::Pi() / 16., -TMath::Pi() / 16., 0.0f, TMath::Pi() / 16., 2 * TMath::Pi() / 16., 3 * TMath::Pi() / 16., 4 * TMath::Pi() / 16., 5 * TMath::Pi() / 16., 6 * TMath::Pi() / 16., 7 * TMath::Pi() / 16., 8 * TMath::Pi() / 16.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("Psi2C5")) { std::vector fPsi2C = {-12 * TMath::Pi() / 24., -11 * TMath::Pi() / 24., -10 * TMath::Pi() / 24., -9 * TMath::Pi() / 24., -8 * TMath::Pi() / 24., -7 * TMath::Pi() / 24., -6 * TMath::Pi() / 24., -5 * TMath::Pi() / 24., -4 * TMath::Pi() / 24., -3 * TMath::Pi() / 24., -2 * TMath::Pi() / 24., -TMath::Pi() / 24., 0.0f, TMath::Pi() / 24., 2 * TMath::Pi() / 24., 3 * TMath::Pi() / 24., 4 * TMath::Pi() / 24., 5 * TMath::Pi() / 24., 6 * TMath::Pi() / 24., 7 * TMath::Pi() / 24., 8 * TMath::Pi() / 24., 9 * TMath::Pi() / 24., 10 * TMath::Pi() / 24., 11 * TMath::Pi() / 24., 12 * TMath::Pi() / 24.}; - mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C.size(), fPsi2C); + mh->AddMixingVariable(VarManager::kPsi2C, fPsi2C); } if (!nameStr.compare("MedianTimeA1")) { std::vector fMTLimsHashing = {-100.0f, -40.0f, -20.0f, 20.0f, 40.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("MedianTimeA2")) { std::vector fMTLimsHashing = {-100.0f, -80.0f, -60.0f, -40.0f, -20.0f, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("MedianTimeA3")) { std::vector fMTLimsHashing = {-100.0f, -80.0f, -60.0f, -40.0f, -30.0f, -20.0f, -10.0f, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 60.0f, 80.0f, 100.0f}; - mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing.size(), fMTLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCmedianTimeLongA, fMTLimsHashing); } if (!nameStr.compare("PileUpA1")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 6000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA2")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 4000.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA3")) { std::vector fPileUpLimsHashing = {0.0f, 1000.0f, 2000.0f, 3000.0f, 4000.0f, 5000.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } if (!nameStr.compare("PileUpA4")) { std::vector fPileUpLimsHashing = {0.0f, 500.0f, 1000.0f, 1500.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 5500.0f, 6000.0f, 8000.0f, 10000.0f, 20000.0f}; - mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); + mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing); } } @@ -250,6 +250,6 @@ void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json) } // set up mixing variable - mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits.size(), limits); + mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits); } } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 7dfb955aaa6..b9549fa63c1 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1396,6 +1396,8 @@ class VarManager : public TObject static void FillTriple(T1 const& t1, T2 const& t2, T3 const& t3, float* values = nullptr, PairCandidateType pairType = kTripleCandidateToEEPhoton); template static void FillPairME(T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillPairMEAcrossTFs(T const& t1, T const& t2, float* values = nullptr); template static void FillPairMC(T1 const& t1, T2 const& t2, float* values = nullptr); template @@ -4214,6 +4216,24 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) } } +template +void VarManager::FillPairMEAcrossTFs(T const& t1, T const& t2, float* values) +{ + if (!values) { + values = fgValues; + } + + float m1 = o2::constants::physics::MassElectron; + ROOT::Math::PtEtaPhiMVector v1(t1.pt, t1.eta, t1.phi, m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt, t2.eta, t2.phi, m1); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + values[kPhi] = v12.Phi() > 0 ? v12.Phi() : v12.Phi() + 2. * M_PI; + values[kRap] = -v12.Rapidity(); +} + template void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values) { diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index ecd68a04327..e67e6bb9cd3 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1306,6 +1306,9 @@ struct AnalysisSameEventPairing { } fConfigCuts; Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; + Configurable fConfigRunMixingAcrossTFs{"cfgRunMixingAcrossTFs", false, "If true, run event mixing using the MixingHandler which accumulates events across multiple TFs"}; // Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; @@ -1353,6 +1356,7 @@ struct AnalysisSameEventPairing { Filter filterEventSelected = aod::dqanalysisflags::isEventSelected > static_cast(0); HistogramManager* fHistMan; + MixingHandler fMixingHandler; o2::analysis::DQMlResponse fDQMlResponse; std::vector fOutputMlPsi2ee = {}; // TODO: check this is needed or not @@ -1390,6 +1394,7 @@ struct AnalysisSameEventPairing { { fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra") || context.mOptions.get("processBarrelOnlyWithQvectorCentrSkimmedNoCov"); fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed") || context.mOptions.get("processMixingBarrelSkimmedFlow") || context.mOptions.get("processMixingBarrelWithQvectorCentrSkimmedNoCov"); + fEnableBarrelMixingHistos |= fConfigRunMixingAcrossTFs; fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMuonOnlySkimmedFlow"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed") || context.mOptions.get("processMixingMuonSkimmedFlow"); fEnableBarrelMuonHistos = context.mOptions.get("processElectronMuonSkimmed"); @@ -1620,6 +1625,26 @@ struct AnalysisSameEventPairing { } } + if (fConfigRunMixingAcrossTFs) { + TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; + std::unique_ptr objArray(mixVarsString.Tokenize(",")); + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { + //fMixingHandler = new MixingHandler("mixingHandler", "mixing handler"); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(&fMixingHandler, objArray->At(iVar)->GetName()); + } + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(&fMixingHandler, mixVarsJsonString.Data()); + } + fMixingHandler.SetPoolDepth(fConfigMixingDepth); + fMixingHandler.Init(); + } + + fCurrentRun = 0; fCCDB->setURL(fConfigCCDB.url.value); @@ -2182,6 +2207,95 @@ struct AnalysisSameEventPairing { if (fEnableBarrelHistos && fConfigQA) { fHistMan->FillHistClass("PairingSEQA", VarManager::fgValues); } + + if (fConfigRunMixingAcrossTFs) { + // run event mixing across TFs + // 1) create a MixingEvent and fill it with the relevant tracks + MixingHandler::MixingEvent mixingEvent; + uint32_t trackFilterForMixing = 0; + for (auto& assoc : groupedAssocs) { + if constexpr (TPairType == VarManager::kDecayToEE) { + trackFilterForMixing = assoc.isBarrelSelected_raw() & assoc.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; + if (!trackFilterForMixing) { + continue; + } + auto t1 = assoc.template reducedtrack_as(); + MixingHandler::MixingTrack mixingTrack(t1.pt(), t1.eta(), t1.phi(), trackFilterForMixing); + if (t1.sign() > 0) { + mixingEvent.AddTrack1(mixingTrack); + } else { + mixingEvent.AddTrack2(mixingTrack); + } + } + } + // 2) run the mixing with the events in the pool corresponding to this event + auto& pool = fMixingHandler.GetPool(fMixingHandler.FindEventCategory(VarManager::fgValues)); + for (auto& poolEvent : pool.GetEvents()) { + for (auto& t1 : mixingEvent.tracks1) { + // run +- pairing + for (auto& t2 : poolEvent.tracks2) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + // run ++ pairing + for (auto& t2 : poolEvent.tracks1) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPP_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + } + for (auto& t1 : mixingEvent.tracks2) { + // run -+ pairing + for (auto& t2 : poolEvent.tracks1) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEPM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + // run -- pairing + for (auto& t2 : poolEvent.tracks2) { + // check the two-track filter for the mixed pair + uint32_t mixedTwoTrackFilter = t1.filteringFlags & t2.filteringFlags; + if (!mixedTwoTrackFilter) { + continue; + } + VarManager::FillPairMEAcrossTFs(t1, t2); + for (int icut = 0; icut < ncuts; icut++) { + if (mixedTwoTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("PairsBarrelMEMM_%s", fTrackCuts[icut].Data()), VarManager::fgValues); + } + } + } + } + } + // 3) add the current event to the pool + pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth()); + pool.Print(); + } } // end loop over events } From 3c09b3f1919d6188bf897a4fbbfac6312b73194e Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Thu, 4 Jun 2026 03:56:22 +0200 Subject: [PATCH 2/3] remove printouts --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index e67e6bb9cd3..c82d8a84663 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -2294,7 +2294,7 @@ struct AnalysisSameEventPairing { } // 3) add the current event to the pool pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth()); - pool.Print(); + //pool.Print(); } } // end loop over events } From 04ea8b7abbf979b2a1f318908f770e6ebd0ba129 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 4 Jun 2026 02:04:59 +0000 Subject: [PATCH 3/3] Please consider the following formatting changes --- PWGDQ/Core/MixingHandler.cxx | 2 +- PWGDQ/Core/MixingHandler.h | 55 +++++++++++++++------------ PWGDQ/Tasks/tableReader_withAssoc.cxx | 5 +-- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/PWGDQ/Core/MixingHandler.cxx b/PWGDQ/Core/MixingHandler.cxx index 834fa14e91c..5b769fed65d 100644 --- a/PWGDQ/Core/MixingHandler.cxx +++ b/PWGDQ/Core/MixingHandler.cxx @@ -134,7 +134,7 @@ int MixingHandler::FindEventCategory(float* values) return -1; // all variables must be inside limits } bin.push_back(binValue - 1); - } + } // Hash the bin values to define a unique category // The hashing is done such that the original bin values can be retrieved from the category diff --git a/PWGDQ/Core/MixingHandler.h b/PWGDQ/Core/MixingHandler.h index 6d720c8d578..2a396ab7d35 100644 --- a/PWGDQ/Core/MixingHandler.h +++ b/PWGDQ/Core/MixingHandler.h @@ -24,16 +24,15 @@ #include -#include -#include #include #include +#include +#include class MixingHandler : public TNamed { public: - // Struct to define track properties relevant for mixing and few utility functions struct MixingTrack { float pt; @@ -41,15 +40,16 @@ class MixingHandler : public TNamed float phi; uint32_t filteringFlags; // flip a bit to zero (needed when a track was already used in mixing for that bit for the required pool depth) - void FlipBit(int64_t mask) { filteringFlags ^= mask;} - void Print() const { + void FlipBit(int64_t mask) { filteringFlags ^= mask; } + void Print() const + { std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", filteringFlags: " << filteringFlags << std::endl; } }; // Struct to define events used in mixing and few utility functions. - // An event is defined as two vectors of tracks (typically the legs of a two-body - //decay or the two-particles in a correlation analysis) + // An event is defined as two vectors of tracks (typically the legs of a two-body + // decay or the two-particles in a correlation analysis) struct MixingEvent { std::vector tracks1; std::vector tracks2; @@ -58,20 +58,23 @@ class MixingHandler : public TNamed // counters to keep track of how many times the event was used for mixing (for each track cut separately) std::array counters = {0}; // add a track to the event and update the filtering mask accordingly - void AddTrack1(const MixingTrack& track) { + void AddTrack1(const MixingTrack& track) + { tracks1.push_back(track); filteringMask |= track.filteringFlags; } - void AddTrack2(const MixingTrack& track) { + void AddTrack2(const MixingTrack& track) + { tracks2.push_back(track); filteringMask |= track.filteringFlags; } // flip bits in the filtering mask void FlipFilteringMask(int64_t mask) { filteringMask ^= mask; } - // 1) increment the counters for a given track cut bit mask and if the counters reached the pool depth, + // 1) increment the counters for a given track cut bit mask and if the counters reached the pool depth, // 2) flip the corresponding bit in the tracks filtering flags to exclude them from further mixing // 3) for each track, if there are no more active bits in the filtering mask, then remove the track from the event - void IncrementCounters(uint32_t mask, short poolDepth) { + void IncrementCounters(uint32_t mask, short poolDepth) + { for (int i = 0; i < 32; i++) { if (mask & (1ULL << i)) { counters[i]++; @@ -95,7 +98,8 @@ class MixingHandler : public TNamed } } } - void Print() const { + void Print() const + { std::cout << "Event filtering mask: "; for (int i = 0; i < 32; i++) { if (filteringMask & (1ULL << i)) { @@ -123,16 +127,18 @@ class MixingHandler : public TNamed struct MixingPool { std::vector events; - + // check which events in the pool are empty (i.e. no active tracks for mixing) and remove them from the pool - void CleanPool() { + void CleanPool() + { events.erase(std::remove_if(events.begin(), events.end(), [](const MixingEvent& event) { return event.tracks1.empty() && event.tracks2.empty(); }), events.end()); } - // The function that performs the mixing is called outside this class, but the pool provides the events and tracks to be mixed and takes care of updating the events after mixing + // The function that performs the mixing is called outside this class, but the pool provides the events and tracks to be mixed and takes care of updating the events after mixing // (e.g. incrementing the counters and removing the tracks that reached the pool depth for a given cut) - void UpdatePool(const MixingEvent& event, short poolDepth) { + void UpdatePool(const MixingEvent& event, short poolDepth) + { for (auto& event : events) { event.IncrementCounters(event.filteringMask, poolDepth); } @@ -142,14 +148,15 @@ class MixingHandler : public TNamed // getter for the events in the pool const std::vector& GetEvents() const { return events; } - void Print() const { + void Print() const + { std::cout << "Mixing pool with " << events.size() << " events:" << std::endl; for (const auto& event : events) { event.Print(); } } }; - + MixingHandler(); MixingHandler(const char* name, const char* title); virtual ~MixingHandler(); @@ -159,9 +166,9 @@ class MixingHandler : public TNamed void SetPoolDepth(short depth) { fPoolDepth = depth; } // getters - //int GetNMixingVariables() const { return fVariables.size(); } - //int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly - //std::vector GetMixingVariableLimits(VarManager::Variables var); + // int GetNMixingVariables() const { return fVariables.size(); } + // int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly + // std::vector GetMixingVariableLimits(VarManager::Variables var); MixingPool& GetPool(int category) { return fPools[category]; } short GetPoolDepth() const { return fPoolDepth; } @@ -178,10 +185,10 @@ class MixingHandler : public TNamed // bin limits for the variables used for mixing, the number of vectors corresponds to the number of variables and the content of each vector corresponds to the bin limits for that variable std::vector> fVariableLimits; - std::map fVariables; // key: variable, value: position in the internal variable list of the handler (used to map the variables to the values passed to FindEventCategory) + std::map fVariables; // key: variable, value: position in the internal variable list of the handler (used to map the variables to the values passed to FindEventCategory) - short fPoolDepth; // number of events to be kept in each pool - std::map fPools; // key: category, value: pool of events corresponding to that category + short fPoolDepth; // number of events to be kept in each pool + std::map fPools; // key: category, value: pool of events corresponding to that category ClassDef(MixingHandler, 2); }; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index c82d8a84663..182d1959ac4 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1630,7 +1630,7 @@ struct AnalysisSameEventPairing { TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { - //fMixingHandler = new MixingHandler("mixingHandler", "mixing handler"); + // fMixingHandler = new MixingHandler("mixingHandler", "mixing handler"); if (objArray->GetEntries() > 0) { for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { dqmixing::SetUpMixing(&fMixingHandler, objArray->At(iVar)->GetName()); @@ -1643,7 +1643,6 @@ struct AnalysisSameEventPairing { fMixingHandler.SetPoolDepth(fConfigMixingDepth); fMixingHandler.Init(); } - fCurrentRun = 0; @@ -2294,7 +2293,7 @@ struct AnalysisSameEventPairing { } // 3) add the current event to the pool pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth()); - //pool.Print(); + // pool.Print(); } } // end loop over events }