Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PWGDQ] Implement charge checks and improve candidate selection in open charm analyses #9455

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 46 additions & 9 deletions PWGDQ/Tasks/dqEfficiency_withAssoc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no
// Configurable workflow for running several DQ or other PWG analyses

#include <iostream>

Check warning on line 15 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[include-iostream]

Including iostream is discouraged. Use O2 logging instead.
#include <vector>
#include <algorithm>
#include <map>
Expand Down Expand Up @@ -273,7 +273,7 @@
auto ev2 = events.rawIteratorAt(*ev2It);
// compute 2-event quantities and mark the candidate split collisions
VarManager::FillTwoEvents(ev1, ev2);
if (TMath::Abs(VarManager::fgValues[VarManager::kTwoEvDeltaZ]) < fConfigSplitCollisionsDeltaZ) { // this is a possible collision split

Check warning on line 276 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
collisionSplittingMap[*ev1It] = true;
collisionSplittingMap[*ev2It] = true;
}
Expand All @@ -298,7 +298,7 @@
auto ev2 = events.rawIteratorAt(ev2It);
// compute 2-event quantities and mark the candidate split collisions
VarManager::FillTwoEvents(ev1, ev2);
if (TMath::Abs(VarManager::fgValues[VarManager::kTwoEvDeltaZ]) < fConfigSplitCollisionsDeltaZ) { // this is a possible collision split

Check warning on line 301 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
collisionSplittingMap[ev1It] = true;
collisionSplittingMap[ev2It] = true;
}
Expand Down Expand Up @@ -1940,8 +1940,10 @@
uint32_t fLegAFilterMask;
uint32_t fLegBFilterMask;
uint32_t fLegCFilterMask;
// Map tracking which pair of leg cuts the track cuts participate in
std::map<int, uint32_t> fTrackCutFilterMasks;
// Maps tracking which combination of leg cuts the track cuts participate in
std::map<int, uint32_t> fConstructedLegAFilterMasksMap;
std::map<int, uint32_t> fConstructedLegBFilterMasksMap;
std::map<int, uint32_t> fConstructedLegCFilterMasksMap;
// Filter map for common track cuts
uint32_t fCommonTrackCutMask;
// Map tracking which common track cut the track cuts correspond to
Expand Down Expand Up @@ -2013,14 +2015,14 @@
}
}
// Check that the leg cut masks make sense
if (static_cast<int>(std::floor(TMath::Log2(fLegAFilterMask))) + 1 > objArray->GetEntries()) {

Check warning on line 2018 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
LOGF(fatal, "fConfigLegAFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast<int>(std::floor(TMath::Log2(fLegAFilterMask))) + 1, objArray->GetEntries());

Check warning on line 2019 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
}
if (static_cast<int>(std::floor(TMath::Log2(fLegBFilterMask))) + 1 > objArray->GetEntries()) {

Check warning on line 2021 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
LOGF(fatal, "fConfigLegBFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast<int>(std::floor(TMath::Log2(fLegBFilterMask))) + 1, objArray->GetEntries());

Check warning on line 2022 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
}
if (static_cast<int>(std::floor(TMath::Log2(fLegCFilterMask))) + 1 > objArray->GetEntries()) {

Check warning on line 2024 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
LOGF(fatal, "fConfigLegCFilterMask has highest bit at position %d, but track-selection only has %d cuts!", static_cast<int>(std::floor(TMath::Log2(fLegCFilterMask))) + 1, objArray->GetEntries());

Check warning on line 2025 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
}

// Get the cuts defining the legs
Expand Down Expand Up @@ -2053,15 +2055,15 @@
legAIdx = objArray->IndexOf(legs->At(0));
if (legAIdx >= 0) {
fConstructedLegAFilterMask |= static_cast<uint32_t>(1) << legAIdx;
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legAIdx;
fConstructedLegAFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legAIdx;
} else {
LOGF(fatal, "Leg A cut %s was not calculated upstream. Check the config!", legs->At(0)->GetName());
continue;
}
legBIdx = objArray->IndexOf(legs->At(1));
if (legBIdx >= 0) {
fConstructedLegBFilterMask |= static_cast<uint32_t>(1) << legBIdx;
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legBIdx;
fConstructedLegBFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legBIdx;
} else {
LOGF(fatal, "Leg B cut %s was not calculated upstream. Check the config!", legs->At(1)->GetName());
continue;
Expand All @@ -2070,7 +2072,7 @@
legCIdx = objArray->IndexOf(legs->At(2));
if (legCIdx >= 0) {
fConstructedLegCFilterMask |= static_cast<uint32_t>(1) << legCIdx;
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legCIdx;
fConstructedLegCFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legCIdx;
} else {
LOGF(fatal, "Leg C cut %s was not calculated upstream. Check the config!", legs->At(2)->GetName());
continue;
Expand Down Expand Up @@ -2379,7 +2381,7 @@
bool isPairIdWrong = false;
for (int icut = 0; icut < fNLegCuts; ++icut) {
// Find leg pair definitions both candidates participate in
if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) {
if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut])) {
twoTrackFilter |= static_cast<uint32_t>(1) << icut;
// If the supposed pion passes a kaon cut, this is a K+K-. Skip it.
if (TPairType == VarManager::kDecayToKPi && fConfigSkipAmbiguousIdCombinations.value) {
Expand Down Expand Up @@ -2626,8 +2628,8 @@
uint32_t threeTrackFilter = 0;
uint32_t threeTrackCommonFilter = 0;
for (int icut = 0; icut < fNLegCuts; ++icut) {
// Find out which leg cut combination the triplet passes
if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask) | (a3.isBarrelSelected_raw() & fLegCFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) {
// Find out which leg cut combinations the triplet passes
if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut]) && (a3.isBarrelSelected_raw() & fConstructedLegCFilterMasksMap[icut])) {
threeTrackFilter |= (static_cast<uint32_t>(1) << icut);
if (tripletType == VarManager::kTripleCandidateToPKPi && fConfigSkipAmbiguousIdCombinations.value) {
// Check if the supposed pion passes as a proton or kaon, if so, skip this triplet. It is pKp or pKK.
Expand Down Expand Up @@ -2662,6 +2664,17 @@
if (t1 == t2 || t1 == t3 || t2 == t3) {
return;
}
// Check charge
if (tripletType == VarManager::kTripleCandidateToKPiPi) {
if (!((t1.sign() == -1 && t2.sign() == 1 && t3.sign() == 1) || (t1.sign() == 1 && t2.sign() == -1 && t3.sign() == -1))) {
return;
}
}
if (tripletType == VarManager::kTripleCandidateToPKPi) {
if (!((t1.sign() == 1 && t2.sign() == -1 && t3.sign() == 1) || (t1.sign() == -1 && t2.sign() == 1 && t3.sign() == -1))) {
return;
}
}

// store the ambiguity of the three legs in the last 3 digits of the two-track filter
if (t1.barrelAmbiguityInBunch() > 1 || t1.barrelAmbiguityOutOfBunch() > 1) {
Expand Down Expand Up @@ -3118,7 +3131,7 @@

// loop over hadrons
for (auto& assoc : assocs) {
if constexpr (TCandidateType == VarManager::kBtoJpsiEEK || TCandidateType == VarManager::kDstarToD0KPiPi) {
if constexpr (TCandidateType == VarManager::kBtoJpsiEEK) {
if (!assoc.isBarrelSelected_bit(fTrackCutBit)) {
continue;
}
Expand All @@ -3138,6 +3151,30 @@
}
}
}
if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) {
if (!assoc.isBarrelSelected_bit(fTrackCutBit)) {
continue;
}
auto track = assoc.template reducedtrack_as<TTracks>();
if (track.globalIndex() == dilepton.index0Id() || track.globalIndex() == dilepton.index1Id()) {
continue;
}
// Check that the charge combination makes sense for D*+ -> D0 pi+ or D*- -> D0bar pi-
if (!((track.sign() == 1 && lepton1.sign() == -1 && lepton2.sign() == 1) || (track.sign() == -1 && lepton1.sign() == 1 && lepton2.sign() == -1))) {
continue;
}
VarManager::FillDileptonHadron(dilepton, track, fValuesHadron);
VarManager::FillDileptonTrackVertexing<TCandidateType, TEventFillMap, TTrackFillMap>(event, lepton1, lepton2, track, fValuesHadron);

auto trackMC = track.reducedMCTrack();
mcDecision = 0;
isig = 0;
for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) {
if ((*sig).CheckSignal(true, lepton1MC, lepton2MC, trackMC)) {
mcDecision |= (static_cast<uint32_t>(1) << isig);
}
}
}
if constexpr (TCandidateType == VarManager::kBcToThreeMuons) {
if (!assoc.isMuonSelected_bit(fTrackCutBit)) {
continue;
Expand Down Expand Up @@ -3334,7 +3371,7 @@
// The histogram classes and their components histograms are defined below depending on the name of the histogram class
//
std::unique_ptr<TObjArray> objArray(histClasses.Tokenize(";"));
for (Int_t iclass = 0; iclass < objArray->GetEntries(); ++iclass) {

Check warning on line 3374 in PWGDQ/Tasks/dqEfficiency_withAssoc.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[root-entity]

Consider replacing ROOT entities with equivalents from standard C++ or from O2.
TString classStr = objArray->At(iclass)->GetName();
histMan->AddHistClass(classStr.Data());

Expand Down
46 changes: 37 additions & 9 deletions PWGDQ/Tasks/tableReader_withAssoc.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1926,8 +1926,10 @@ struct AnalysisAsymmetricPairing {
uint32_t fLegAFilterMask;
uint32_t fLegBFilterMask;
uint32_t fLegCFilterMask;
// Map tracking which pair of leg cuts the track cuts participate in
std::map<int, uint32_t> fTrackCutFilterMasks;
// Maps tracking which combination of leg cuts the track cuts participate in
std::map<int, uint32_t> fConstructedLegAFilterMasksMap;
std::map<int, uint32_t> fConstructedLegBFilterMasksMap;
std::map<int, uint32_t> fConstructedLegCFilterMasksMap;
// Filter map for common track cuts
uint32_t fCommonTrackCutMask;
// Map tracking which common track cut the track cuts correspond to
Expand Down Expand Up @@ -2027,15 +2029,15 @@ struct AnalysisAsymmetricPairing {
legAIdx = objArray->IndexOf(legs->At(0));
if (legAIdx >= 0) {
fConstructedLegAFilterMask |= (static_cast<uint32_t>(1) << legAIdx);
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legAIdx;
fConstructedLegAFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legAIdx;
} else {
LOGF(fatal, "Leg A cut %s was not calculated upstream. Check the config!", legs->At(0)->GetName());
continue;
}
legBIdx = objArray->IndexOf(legs->At(1));
if (legBIdx >= 0) {
fConstructedLegBFilterMask |= (static_cast<uint32_t>(1) << legBIdx);
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legBIdx;
fConstructedLegBFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legBIdx;
} else {
LOGF(fatal, "Leg B cut %s was not calculated upstream. Check the config!", legs->At(1)->GetName());
continue;
Expand All @@ -2044,7 +2046,7 @@ struct AnalysisAsymmetricPairing {
legCIdx = objArray->IndexOf(legs->At(2));
if (legCIdx >= 0) {
fConstructedLegCFilterMask |= (static_cast<uint32_t>(1) << legCIdx);
fTrackCutFilterMasks[icut] |= static_cast<uint32_t>(1) << legCIdx;
fConstructedLegCFilterMasksMap[icut] |= static_cast<uint32_t>(1) << legCIdx;
} else {
LOGF(fatal, "Leg C cut %s was not calculated upstream. Check the config!", legs->At(2)->GetName());
continue;
Expand Down Expand Up @@ -2258,7 +2260,7 @@ struct AnalysisAsymmetricPairing {
bool isPairIdWrong = false;
for (int icut = 0; icut < fNLegCuts; ++icut) {
// Find leg pair definitions both candidates participate in
if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) {
if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut])) {
twoTrackFilter |= (static_cast<uint32_t>(1) << icut);
// If the supposed pion passes a kaon cut, this is a K+K-. Skip it.
if (TPairType == VarManager::kDecayToKPi && fConfigSkipAmbiguousIdCombinations.value) {
Expand Down Expand Up @@ -2435,8 +2437,8 @@ struct AnalysisAsymmetricPairing {
uint32_t threeTrackFilter = static_cast<uint32_t>(0);
uint32_t threeTrackCommonFilter = static_cast<uint32_t>(0);
for (int icut = 0; icut < fNLegCuts; ++icut) {
// Find out which leg cut combination the triplet passes
if ((((a1.isBarrelSelected_raw() & fLegAFilterMask) | (a2.isBarrelSelected_raw() & fLegBFilterMask) | (a3.isBarrelSelected_raw() & fLegCFilterMask)) & fTrackCutFilterMasks[icut]) == fTrackCutFilterMasks[icut]) {
// Find out which leg cut combinations the triplet passes
if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut]) && (a3.isBarrelSelected_raw() & fConstructedLegCFilterMasksMap[icut])) {
threeTrackFilter |= (static_cast<uint32_t>(1) << icut);
if (tripletType == VarManager::kTripleCandidateToPKPi && fConfigSkipAmbiguousIdCombinations.value) {
// Check if the supposed pion passes as a proton or kaon, if so, skip this triplet. It is pKp or pKK.
Expand Down Expand Up @@ -2471,6 +2473,17 @@ struct AnalysisAsymmetricPairing {
if (t1 == t2 || t1 == t3 || t2 == t3) {
return;
}
// Check charge
if (tripletType == VarManager::kTripleCandidateToKPiPi) {
if (!((t1.sign() == -1 && t2.sign() == 1 && t3.sign() == 1) || (t1.sign() == 1 && t2.sign() == -1 && t3.sign() == -1))) {
return;
}
}
if (tripletType == VarManager::kTripleCandidateToPKPi) {
if (!((t1.sign() == 1 && t2.sign() == -1 && t3.sign() == 1) || (t1.sign() == -1 && t2.sign() == 1 && t3.sign() == -1))) {
return;
}
}

// store the ambiguity of the three legs in the last 3 digits of the two-track filter
if (t1.barrelAmbiguityInBunch() > 1 || t1.barrelAmbiguityOutOfBunch() > 1) {
Expand Down Expand Up @@ -2823,14 +2836,29 @@ struct AnalysisDileptonTrack {

// loop over hadrons
for (auto& assoc : assocs) {
if constexpr (TCandidateType == VarManager::kBtoJpsiEEK || TCandidateType == VarManager::kDstarToD0KPiPi) {
if constexpr (TCandidateType == VarManager::kBtoJpsiEEK) {
if (!assoc.isBarrelSelected_bit(fTrackCutBit)) {
continue;
}
auto track = assoc.template reducedtrack_as<TTracks>();
if (track.globalIndex() == dilepton.index0Id() || track.globalIndex() == dilepton.index1Id()) {
continue;
}
VarManager::FillDileptonHadron(dilepton, track, fValuesHadron);
VarManager::FillDileptonTrackVertexing<TCandidateType, TEventFillMap, TTrackFillMap>(event, lepton1, lepton2, track, fValuesHadron);
}
if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) {
if (!assoc.isBarrelSelected_bit(fTrackCutBit)) {
continue;
}
auto track = assoc.template reducedtrack_as<TTracks>();
if (track.globalIndex() == dilepton.index0Id() || track.globalIndex() == dilepton.index1Id()) {
continue;
}
// Check that the charge combination makes sense for D*+ -> D0 pi+ or D*- -> D0bar pi-
if (!((track.sign() == 1 && lepton1.sign() == -1 && lepton2.sign() == 1) || (track.sign() == -1 && lepton1.sign() == 1 && lepton2.sign() == -1))) {
continue;
}
VarManager::FillDileptonHadron(dilepton, track, fValuesHadron);
VarManager::FillDileptonTrackVertexing<TCandidateType, TEventFillMap, TTrackFillMap>(event, lepton1, lepton2, track, fValuesHadron);
}
Expand Down
Loading