Skip to content

Commit fc7adcd

Browse files
committed
Fix event mixing bug
1 parent def7bbd commit fc7adcd

5 files changed

Lines changed: 268 additions & 78 deletions

File tree

PWGDQ/Core/MixingHandler.cxx

Lines changed: 36 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,40 @@ 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 [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];
196+
}
197+
198+
//_________________________________________________________________________
199+
void MixingHandler::SetCategoryBinCenters(int category, float* values) const
200+
{
201+
//
202+
// set the mixing variables to the bin centers of this category (used for the leftover mixing)
203+
//
204+
for (auto [var, pos] : fVariables) {
205+
int bin = GetBinFromCategory(static_cast<VarManager::Variables>(var), category);
206+
if (bin < 0) {
207+
continue;
208+
}
209+
values[var] = 0.5 * (fVariableLimits[pos][bin] + fVariableLimits[pos][bin + 1]);
210+
}
181211
}

PWGDQ/Core/MixingHandler.h

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <Rtypes.h>
2525

26+
#include <algorithm>
2627
#include <array>
2728
#include <cstdint>
2829
#include <iostream>
@@ -39,11 +40,19 @@ class MixingHandler : public TNamed
3940
float eta;
4041
float phi;
4142
uint32_t filteringFlags;
43+
// globalIndex is unique only within a dataframe, so the dataframe sequence is part of the track identity
44+
uint64_t dataFrameSequence = 0;
45+
uint64_t trackGlobalIndex = 0;
46+
bool IsSamePhysicalTrack(const MixingTrack& other) const
47+
{
48+
return dataFrameSequence == other.dataFrameSequence && trackGlobalIndex == other.trackGlobalIndex;
49+
}
4250
// Clear a bit once the track was used in mixing for that bit for the required pool depth.
4351
void ClearBit(uint32_t mask) { filteringFlags &= ~mask; }
4452
void Print() const
4553
{
46-
std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", filteringFlags: " << filteringFlags << std::endl;
54+
std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", filteringFlags: " << filteringFlags
55+
<< ", dataframe: " << dataFrameSequence << ", track: " << trackGlobalIndex << std::endl;
4756
}
4857
};
4958

@@ -70,6 +79,19 @@ class MixingHandler : public TNamed
7079
}
7180
// Clear bits in the filtering mask.
7281
void ClearFilteringMask(uint32_t mask) { filteringMask &= ~mask; }
82+
// clear the cut bits from all tracks and the filtering mask; remove tracks with no active bits left
83+
void ClearBits(uint32_t mask)
84+
{
85+
for (auto& track : tracks1) {
86+
track.ClearBit(mask);
87+
}
88+
tracks1.erase(std::remove_if(tracks1.begin(), tracks1.end(), [](auto const& track) { return track.filteringFlags == 0; }), tracks1.end());
89+
for (auto& track : tracks2) {
90+
track.ClearBit(mask);
91+
}
92+
tracks2.erase(std::remove_if(tracks2.begin(), tracks2.end(), [](auto const& track) { return track.filteringFlags == 0; }), tracks2.end());
93+
ClearFilteringMask(mask);
94+
}
7395
// 1) increment the counters for a given track cut bit mask and if the counters reached the pool depth,
7496
// 2) clear the corresponding bit in the tracks filtering flags to exclude them from further mixing
7597
// 3) for each track, if there are no more active bits in the filtering mask, then remove the track from the event
@@ -157,6 +179,35 @@ class MixingHandler : public TNamed
157179
CleanPool();
158180
events.push_back(event);
159181
}
182+
// fixed-block mixing: AddEvent() until GetMixingMask() reports full cuts, mix, then ClearBits()
183+
void AddEvent(const MixingEvent& event) { events.push_back(event); }
184+
// bit mask of the cuts for which at least poolDepth events are in the pool
185+
uint32_t GetMixingMask(int16_t poolDepth) const
186+
{
187+
std::array<int16_t, 32> counts = {0};
188+
for (auto const& event : events) {
189+
for (int icut = 0; icut < 32; ++icut) {
190+
if (event.filteringMask & (static_cast<uint32_t>(1) << icut)) {
191+
counts[icut]++;
192+
}
193+
}
194+
}
195+
uint32_t fullMask = 0;
196+
for (int icut = 0; icut < 32; ++icut) {
197+
if (counts[icut] >= poolDepth) {
198+
fullMask |= static_cast<uint32_t>(1) << icut;
199+
}
200+
}
201+
return fullMask;
202+
}
203+
// clear the given cut bits from all events in the pool and remove the events with no tracks left
204+
void ClearBits(uint32_t mask)
205+
{
206+
for (auto& event : events) {
207+
event.ClearBits(mask);
208+
}
209+
CleanPool();
210+
}
160211
// getter for the events in the pool
161212
const std::vector<MixingEvent>& GetEvents() const { return events; }
162213

@@ -176,17 +227,22 @@ class MixingHandler : public TNamed
176227
// setters
177228
void AddMixingVariable(int var, const std::vector<float>& binLims);
178229
void SetPoolDepth(int16_t depth) { fPoolDepth = depth; }
230+
// remove all pools (e.g. at a run change)
231+
void ClearPools() { fPools.clear(); }
179232

180233
// getters
181234
// int GetNMixingVariables() const { return fVariables.size(); }
182235
// int GetMixingVariable(VarManager::Variables var); // returns the position in the internal varible list of the handler. Useful for checks, mostly
183236
// std::vector<float> GetMixingVariableLimits(VarManager::Variables var);
184237
MixingPool& GetPool(int category) { return fPools[category]; }
238+
std::map<int, MixingPool>& GetPools() { return fPools; }
185239
int16_t GetPoolDepth() const { return fPoolDepth; }
186240

187241
void Init();
188242
int FindEventCategory(float* values);
189243
int GetBinFromCategory(VarManager::Variables var, int category) const;
244+
// set the mixing variables to the bin centers of the given category
245+
void SetCategoryBinCenters(int category, float* values) const;
190246

191247
private:
192248
MixingHandler(const MixingHandler& handler);

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
}

0 commit comments

Comments
 (0)