Skip to content

Commit 990e78f

Browse files
committed
FU: D0 task - histos for prompt fraction; adding process to store only Reco events in MC Truth
1 parent 92ed585 commit 990e78f

2 files changed

Lines changed: 235 additions & 305 deletions

File tree

PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx

Lines changed: 110 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h"
1919
#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h"
2020

21+
#include "Common/CCDB/EventSelectionParams.h"
22+
#include "Common/CCDB/RCTSelectionFlags.h"
2123
#include "Common/CCDB/TriggerAliases.h"
2224
#include "Common/Core/RecoDecay.h"
2325
#include "Common/DataModel/EventSelection.h"
@@ -47,6 +49,7 @@ using namespace o2::analysis::femto_universe;
4749
using namespace o2::framework;
4850
using namespace o2::framework::expressions;
4951
using namespace o2::constants::physics;
52+
using namespace o2::aod::rctsel;
5053

5154
namespace o2::aod
5255
{
@@ -76,22 +79,23 @@ int getRowDaughters(int daughID, T const& vecID)
7679
}
7780

7881
struct FemtoUniverseProducerMCTruthTask {
79-
int mRunNumber;
80-
float mMagField;
81-
Service<o2::ccdb::BasicCCDBManager> ccdb; /// Accessing the CCDB
82+
83+
float mMagField = 0.;
84+
Service<o2::ccdb::BasicCCDBManager> ccdb{}; /// Accessing the CCDB
8285

8386
// Tables being produced
8487
Produces<aod::FdCollisions> outputCollision;
8588
Produces<aod::FDParticles> outputParts;
8689
// Produces<aod::FDMCLabels> outputPartsMCLabels;
8790
// Produces<aod::FdMCParticles> outputPartsMC;
8891

92+
RCTFlagsChecker rctChecker;
93+
8994
// Analysis configs
9095
Configurable<bool> confIsRun3{"confIsRun3", false, "Running on Run3 or pilot"};
91-
Configurable<bool> confIsMC{"confIsMC", false, "Running on MC; implemented only for Run3"};
92-
Configurable<bool> confIsForceGRP{"confIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"};
9396
Configurable<std::vector<int>> confPDGCodes{"confPDGCodes", std::vector<int>{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"};
9497
Configurable<bool> confAnalysisWithPID{"confAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles"};
98+
Configurable<bool> confStoreMotherPDG{"confStoreMotherPDG", false, "Store mother's PDG in tempFitVar."};
9599

96100
/// Event cuts
97101
Configurable<float> confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"};
@@ -101,6 +105,7 @@ struct FemtoUniverseProducerMCTruthTask {
101105
Configurable<float> confCentFT0Min{"confCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"};
102106
Configurable<float> confCentFT0Max{"confCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"};
103107
Configurable<bool> confDoSpher{"confDoSpher", false, "Calculate sphericity. If false sphericity will take value of 2."};
108+
Configurable<bool> confIsCheckRCTFlags{"confIsCheckRCTFlags", true, "Use RCTFlags"};
104109

105110
// Track cuts
106111
struct : o2::framework::ConfigurableGroup {
@@ -113,21 +118,26 @@ struct FemtoUniverseProducerMCTruthTask {
113118
Configurable<float> yD0CandGenMax{"yD0CandGenMax", 0.5, "Rapidity cut for the D0/D0bar mesons"};
114119

115120
FemtoUniverseCollisionSelection colCuts;
121+
FemtoUniverseCollisionSelection recoCollCuts;
116122
FemtoUniverseTrackSelection trackCuts;
117123
HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject};
124+
HistogramRegistry qaRecoRegistry{"QARecoHistos", {}, OutputObjHandlingPolicy::QAObject};
118125

119126
void init(InitContext&)
120127
{
121-
if ((doprocessTrackMC) == false) {
122-
LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one.");
128+
if (!doprocessTrackMC || !doprocessTrackMcOnlyRecoColl) {
129+
LOGF(fatal, "Neither processTrackMC nor processTrackMcOnlyRecoColl enabled. Please choose one.");
123130
}
124-
131+
rctChecker.init("CBT_hadronPID", false, true);
132+
// MC Truth collisions
125133
colCuts.setCuts(confEvtZvtx, confEvtTriggerCheck, confEvtTriggerSel, confEvtOfflineCheck, confIsRun3, confCentFT0Min, confCentFT0Max);
126-
127134
colCuts.init(&qaRegistry);
135+
// MC Reco collisions
136+
recoCollCuts.setCuts(confEvtZvtx, confEvtTriggerCheck, confEvtTriggerSel, confEvtOfflineCheck, confIsRun3, confCentFT0Min, confCentFT0Max);
137+
recoCollCuts.init(&qaRecoRegistry);
138+
128139
trackCuts.init<aod::femtouniverseparticle::ParticleType::kTrack, aod::femtouniverseparticle::TrackType::kNoChild, aod::femtouniverseparticle::CutContainerType>(&qaRegistry);
129140

130-
mRunNumber = 0;
131141
mMagField = 0.0;
132142

133143
/// Initializing CCDB
@@ -159,6 +169,44 @@ struct FemtoUniverseProducerMCTruthTask {
159169
}
160170
}
161171

172+
template <typename CollisionType>
173+
bool checkMcRecoCollisions(CollisionType const& col)
174+
{
175+
if (confIsCheckRCTFlags && !rctChecker(col)) {
176+
return false;
177+
}
178+
179+
// check whether the basic event selection criteria are fulfilled
180+
// if the basic selection is NOT fulfilled MC Truth collision is rejected
181+
if (!recoCollCuts.isSelected(col)) {
182+
return false;
183+
}
184+
// additional checks on the reconstructed collisions
185+
if (col.selection_bit(aod::evsel::kNoSameBunchPileup) && col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && col.selection_bit(aod::evsel::kIsVertexITSTPC)) {
186+
recoCollCuts.fillQA(col);
187+
return true;
188+
} else {
189+
return false;
190+
}
191+
}
192+
193+
template <typename ParticleType>
194+
int getMotherPDG(ParticleType particle)
195+
{
196+
if (particle.isPhysicalPrimary()) {
197+
return 0;
198+
} else if (particle.has_mothers()) {
199+
if (particle.getProcess() == 20 || particle.getProcess() == 23) { // treat particles from hadronic scattering (20, 23) as primary
200+
return 0;
201+
}
202+
auto motherparticlesMC = particle.template mothers_as<aod::McParticles>();
203+
auto motherparticleMC = motherparticlesMC.front();
204+
return motherparticleMC.pdgCode();
205+
} else {
206+
return 999;
207+
}
208+
}
209+
162210
template <typename TrackType>
163211
void fillParticles(TrackType const& tracks)
164212
{
@@ -168,28 +216,27 @@ struct FemtoUniverseProducerMCTruthTask {
168216
/// if the most open selection criteria are not fulfilled there is no
169217
/// point looking further at the track
170218

171-
if (particle.pt() < ConfFilteringTracks.confPtLowFilterCut || particle.pt() > ConfFilteringTracks.confPtHighFilterCut)
219+
if (particle.pt() < ConfFilteringTracks.confPtLowFilterCut || particle.pt() > ConfFilteringTracks.confPtHighFilterCut) {
172220
continue;
221+
}
173222

174223
int pdgCode = particle.pdgCode();
175224

176225
if (confAnalysisWithPID) {
177226
bool pass = false;
178227
std::vector<int> tmpPDGCodes = confPDGCodes; // necessary due to some features of the Configurable
179228
for (auto const& pdg : tmpPDGCodes) {
180-
if (pdgCode == Pdg::kPhi) { // phi meson
229+
if (pdgCode == Pdg::kPhi || // phi meson
230+
std::abs(pdgCode) == Pdg::kD0 || // D0(bar) meson
231+
pdgCode == Pdg::kDPlus || // D+ meson
232+
(pdg == pdgCode && particle.isPhysicalPrimary())) {
181233
pass = true;
182-
} else if (std::abs(pdgCode) == Pdg::kD0) { // D0(bar) meson
183-
pass = true;
184-
} else if (pdgCode == Pdg::kDPlus) { // D+ meson
185-
pass = true;
186-
} else if (static_cast<int>(pdg) == static_cast<int>(pdgCode)) {
187-
if (particle.isPhysicalPrimary())
188-
pass = true;
234+
break; // Exit early once a match is found
189235
}
190236
}
191-
if (!pass)
237+
if (!pass) {
192238
continue;
239+
}
193240
}
194241

195242
// check if D0/D0bar mesons pass the rapidity cut
@@ -199,15 +246,10 @@ struct FemtoUniverseProducerMCTruthTask {
199246
if (std::abs(particle.pdgCode()) == Pdg::kD0) {
200247
if (std::abs(particle.y()) > yD0CandGenMax) {
201248
continue;
202-
} else {
203-
origin = RecoDecay::getCharmHadronOrigin(tracks, particle);
204-
}
205-
} else {
206-
if (std::abs(particle.eta()) > ConfFilteringTracks.confEtaFilterCut) {
207-
continue;
208-
} else {
209-
origin = -99;
210249
}
250+
origin = RecoDecay::getCharmHadronOrigin(tracks, particle);
251+
} else if (std::abs(particle.eta()) > ConfFilteringTracks.confEtaFilterCut) {
252+
continue;
211253
}
212254

213255
/// check if we end-up with the correct final state using MC info
@@ -216,7 +258,8 @@ struct FemtoUniverseProducerMCTruthTask {
216258
/// check if we have D0(bar) → π± K∓
217259
continue;
218260
}
219-
261+
// Getting the PDG code of the mother particle
262+
int motherPDG = confStoreMotherPDG ? getMotherPDG(particle) : particle.pdgCode();
220263
// we cannot use isSelectedMinimal since it takes Ncls
221264
// if (!trackCuts.isSelectedMinimal(track)) {
222265
// continue;
@@ -239,22 +282,54 @@ struct FemtoUniverseProducerMCTruthTask {
239282
pdgCode,
240283
childIDs,
241284
origin,
242-
-999.);
285+
motherPDG);
243286
}
244287
}
245288

246-
void
247-
processTrackMC(aod::McCollision const&,
248-
soa::SmallGroups<soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::McCollisionLabels>> const& collisions,
249-
aod::McParticles const& mcParticles,
250-
aod::BCsWithTimestamps const&)
289+
void processTrackMC(aod::McCollision const&,
290+
soa::SmallGroups<soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::McCollisionLabels>> const& collisions,
291+
aod::McParticles const& mcParticles,
292+
aod::BCsWithTimestamps const&)
251293
{
252294
// magnetic field for run not needed for mc truth
253295
// fill the tables
254296
fillCollisions(collisions, mcParticles);
255297
fillParticles(mcParticles);
256298
}
257299
PROCESS_SWITCH(FemtoUniverseProducerMCTruthTask, processTrackMC, "Provide MC data for track analysis", true);
300+
301+
Preslice<aod::McParticles> perMCCollision = aod::mcparticle::mcCollisionId;
302+
PresliceUnsorted<soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::McCollisionLabels>> recoCollsPerMCColl = aod::mcparticle::mcCollisionId;
303+
304+
void processTrackMcOnlyRecoColl(aod::McCollisions const& mccols,
305+
soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::McCollisionLabels> const& collisions,
306+
aod::McParticles const& mcParticles,
307+
aod::BCsWithTimestamps const&)
308+
{
309+
// check on the reco collisions
310+
static std::set<int> mcColIds;
311+
mcColIds.clear();
312+
313+
for (const auto& col : collisions) {
314+
const auto colcheck = checkMcRecoCollisions(col);
315+
if (colcheck) {
316+
mcColIds.insert(col.mcCollisionId());
317+
}
318+
}
319+
// filling truth collisions and particles
320+
for (const auto& mccol : mccols) {
321+
if (!mcColIds.contains(mccol.globalIndex())) {
322+
continue;
323+
}
324+
auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex());
325+
auto groupedCollisions = collisions.sliceBy(recoCollsPerMCColl, mccol.globalIndex());
326+
// magnetic field for run not needed for mc truth
327+
// fill the tables
328+
fillCollisions(groupedCollisions, groupedMCParticles);
329+
fillParticles(groupedMCParticles);
330+
}
331+
}
332+
PROCESS_SWITCH(FemtoUniverseProducerMCTruthTask, processTrackMcOnlyRecoColl, "Provide MC data for track analysis from truth coll which were recontructed ", false);
258333
};
259334

260335
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)

0 commit comments

Comments
 (0)