Skip to content

Commit 3736e45

Browse files
authored
[PWGDQ] Fix event mixing bug in MixingHandler and tableReader (#17880)
1 parent eb1a220 commit 3736e45

5 files changed

Lines changed: 74 additions & 12 deletions

File tree

PWGDQ/Core/MixingHandler.cxx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ void MixingHandler::AddMixingVariable(int var, const std::vector<float>& binLims
6262
{
6363
fVariables[var] = fVariableLimits.size();
6464
fVariableLimits.push_back(binLims);
65+
// FillEvent() only fills variables marked as used
66+
VarManager::SetUseVariable(var);
6567
}
6668

6769
/*
@@ -125,13 +127,16 @@ int MixingHandler::FindEventCategory(float* values)
125127

126128
// loop over the variables and find out in which bin the value of the variable for the event is located
127129
std::vector<int> bin;
130+
// number of bins per variable in the iteration order of fVariables (fVariableLimits is in insertion order)
131+
std::vector<int> nBins;
128132
for (auto [var, pos] : fVariables) {
129133
// check that the value is within limits, if not return -1 to exclude the event from mixing
130134
size_t binValue = std::distance(fVariableLimits[pos].begin(), std::upper_bound(fVariableLimits[pos].begin(), fVariableLimits[pos].end(), values[var]));
131135
if (binValue == 0 || binValue == fVariableLimits[pos].size()) {
132136
return -1; // all variables must be inside limits
133137
}
134138
bin.push_back(binValue - 1);
139+
nBins.push_back(fVariableLimits[pos].size() - 1);
135140
}
136141

137142
// Hash the bin values to define a unique category
@@ -149,7 +154,7 @@ int MixingHandler::FindEventCategory(float* values)
149154
if (iv2 == iv1) {
150155
tempCategory *= bin[iv2];
151156
} else {
152-
tempCategory *= (fVariableLimits[iv2].size() - 1);
157+
tempCategory *= nBins[iv2];
153158
}
154159
}
155160
category += tempCategory;
@@ -167,15 +172,25 @@ int MixingHandler::GetBinFromCategory(VarManager::Variables var, int category) c
167172
return -1;
168173
}
169174

170-
// Search for the position of the variable "var" in the internal variable list of the handler
171-
int ivar = fVariables.at(var);
175+
// number of bins and position of var in the iteration order of fVariables, as used by FindEventCategory()
176+
std::vector<int> nBins;
177+
int ivar = -1;
178+
for (auto const& [v, pos] : fVariables) {
179+
if (v == var) {
180+
ivar = static_cast<int>(nBins.size());
181+
}
182+
nBins.push_back(fVariableLimits[pos].size() - 1);
183+
}
184+
if (ivar < 0) {
185+
return -1;
186+
}
172187

173188
// extract the bin position in variable "var" from the category
174189
int norm = 1;
175-
for (int i = fVariables.size() - 1; i > ivar; --i) {
176-
norm *= (fVariableLimits[i].size() - 1);
190+
for (size_t i = nBins.size() - 1; i > static_cast<size_t>(ivar); --i) {
191+
norm *= nBins[i];
177192
}
178193
int truncatedCategory = category - (category % norm);
179194
truncatedCategory /= norm;
180-
return truncatedCategory % (fVariableLimits[ivar].size() - 1);
195+
return truncatedCategory % nBins[ivar];
181196
}

PWGDQ/Core/MixingHandler.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class MixingHandler : public TNamed
3333
{
3434

3535
public:
36+
// number of track cuts which fit in the 32-bit filtering masks
37+
static constexpr int NMaxCuts = 32;
38+
3639
// Struct to define track properties relevant for mixing and few utility functions
3740
struct MixingTrack {
3841
float pt;
@@ -157,6 +160,17 @@ class MixingHandler : public TNamed
157160
CleanPool();
158161
events.push_back(event);
159162
}
163+
// Same, but the stored events are aged only for the cuts in agingMask. Passing the filtering mask of the
164+
// incoming event ages an event only for the cuts for which a mixed pair was actually produced, so that the
165+
// pool depth is a number of mixed partners and not a number of arrivals.
166+
void UpdatePool(const MixingEvent& event, int16_t poolDepth, uint32_t agingMask)
167+
{
168+
for (auto& poolEvent : events) {
169+
poolEvent.IncrementCounters(agingMask, poolDepth);
170+
}
171+
CleanPool();
172+
events.push_back(event);
173+
}
160174
// getter for the events in the pool
161175
const std::vector<MixingEvent>& GetEvents() const { return events; }
162176

@@ -176,6 +190,8 @@ class MixingHandler : public TNamed
176190
// setters
177191
void AddMixingVariable(int var, const std::vector<float>& binLims);
178192
void SetPoolDepth(int16_t depth) { fPoolDepth = depth; }
193+
// remove all pools (e.g. at a run change)
194+
void ClearPools() { fPools.clear(); }
179195

180196
// getters
181197
// int GetNMixingVariables() const { return fVariables.size(); }

PWGDQ/Tasks/tableReader.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ struct AnalysisEventSelection {
273273

274274
if (fMixHandler != nullptr) {
275275
int hh = fMixHandler->FindEventCategory(VarManager::fgValues);
276+
// events outside the mixing limits (-1) get a distinct negative hash so that they are not mixed with each other
277+
if (hh < 0) {
278+
hh = -1 - static_cast<int>(event.globalIndex());
279+
}
276280
hash(hh);
277281
}
278282
}

PWGDQ/Tasks/tableReader_withAssoc.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,10 @@ struct AnalysisEventSelection {
494494
// create the mixing hash and publish it into the hash table
495495
if (fMixHandler != nullptr) {
496496
int hh = fMixHandler->FindEventCategory(dqtablereader_helpers::varValues());
497+
// events outside the mixing limits (-1) get a distinct negative hash so that they are not mixed with each other
498+
if (hh < 0) {
499+
hh = -1 - static_cast<int>(event.globalIndex());
500+
}
497501
hash(hh);
498502
}
499503
}
@@ -1714,6 +1718,9 @@ struct AnalysisSameEventPairing {
17141718
}
17151719

17161720
if (fConfigRunMixingAcrossTFs) {
1721+
if (fNCutsBarrel > MixingHandler::NMaxCuts) {
1722+
LOGF(fatal, "Across-TF mixing supports at most %d barrel track-cut bits, got %d", MixingHandler::NMaxCuts, fNCutsBarrel);
1723+
}
17171724
TString mixVarsString = fConfigMixingVariables.value;
17181725
TString mixVarsJsonString = fConfigMixingVariablesJson.value;
17191726
std::unique_ptr<TObjArray> objArray(mixVarsString.Tokenize(","));
@@ -1899,6 +1906,10 @@ struct AnalysisSameEventPairing {
18991906
{
19001907
if (events.size() > 0) { // Additional protection to avoid crashing of events.begin().runNumber()
19011908
if (fCurrentRun != events.begin().runNumber()) {
1909+
if (fConfigRunMixingAcrossTFs) {
1910+
// do not mix events from different runs
1911+
fMixingHandler.ClearPools();
1912+
}
19021913
initParamsFromCCDB(events.begin().timestamp(), events.begin().runNumber(), TTwoProngFitter);
19031914
fCurrentRun = events.begin().runNumber();
19041915
}
@@ -2006,6 +2017,10 @@ struct AnalysisSameEventPairing {
20062017
}
20072018
VarManager::FillEventFlowResoFactor(ResoFlowSP, ResoFlowEP);
20082019
}
2020+
int mixingCategory = -1;
2021+
if (fConfigRunMixingAcrossTFs) {
2022+
mixingCategory = fMixingHandler.FindEventCategory(dqtablereader_helpers::varValues());
2023+
}
20092024

20102025
bool isFirst = true;
20112026
for (auto const& [a1, a2] : o2::soa::combinations(groupedAssocs, groupedAssocs)) {
@@ -2478,6 +2493,9 @@ struct AnalysisSameEventPairing {
24782493

24792494
if (fConfigRunMixingAcrossTFs) {
24802495
// run event mixing across TFs
2496+
if (mixingCategory < 0) {
2497+
continue;
2498+
}
24812499
// 1) create a MixingEvent and fill it with the relevant tracks
24822500
MixingHandler::MixingEvent mixingEvent;
24832501
uint32_t trackFilterForMixing = 0;
@@ -2496,8 +2514,11 @@ struct AnalysisSameEventPairing {
24962514
}
24972515
}
24982516
}
2517+
if (mixingEvent.tracks1.empty() && mixingEvent.tracks2.empty()) {
2518+
continue;
2519+
}
24992520
// 2) run the mixing with the events in the pool corresponding to this event
2500-
auto& pool = fMixingHandler.GetPool(fMixingHandler.FindEventCategory(dqtablereader_helpers::varValues()));
2521+
auto& pool = fMixingHandler.GetPool(mixingCategory);
25012522
for (auto const& poolEvent : pool.GetEvents()) {
25022523
for (auto const& t1 : mixingEvent.tracks1) {
25032524
// run +- pairing
@@ -2561,7 +2582,7 @@ struct AnalysisSameEventPairing {
25612582
}
25622583
}
25632584
// 3) add the current event to the pool
2564-
pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth());
2585+
pool.UpdatePool(mixingEvent, fMixingHandler.GetPoolDepth(), mixingEvent.filteringMask);
25652586
// pool.Print();
25662587
}
25672588
} // end loop over events

PWGDQ/Tasks/tableReader_withAssoc_direct.cxx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,16 @@ struct AnalysisEventSelection {
494494
VarManager::FillBC(bc);
495495
VarManager::FillEvent<TEventFillMap>(event);
496496

497+
// the hash table is joined to the events by row order, so publish one row per event before any event selection
498+
if (fMixHandler != nullptr) {
499+
int hh = fMixHandler->FindEventCategory(VarManager::fgValues);
500+
// events outside the mixing limits (-1) get a distinct negative hash so that they are not mixed with each other
501+
if (hh < 0) {
502+
hh = -1 - static_cast<int>(event.globalIndex());
503+
}
504+
hash(hh);
505+
}
506+
497507
bool decision = false;
498508
if (fConfigQA) {
499509
fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues);
@@ -533,10 +543,6 @@ struct AnalysisEventSelection {
533543
auto& evIndices = fBCCollMap[bc.globalBC()];
534544
evIndices.push_back(event.globalIndex());
535545
}
536-
if (fMixHandler != nullptr) {
537-
int hh = fMixHandler->FindEventCategory(VarManager::fgValues);
538-
hash(hh);
539-
}
540546
}
541547
}
542548

0 commit comments

Comments
 (0)