diff --git a/PWGCF/Core/AnalysisConfigurableCuts.h b/PWGCF/Core/AnalysisConfigurableCuts.h index 77d1f7abbc8..609bf1b8acc 100644 --- a/PWGCF/Core/AnalysisConfigurableCuts.h +++ b/PWGCF/Core/AnalysisConfigurableCuts.h @@ -92,14 +92,14 @@ class TrackSelectionPIDCfg { public: bool mUseIt = false; - float mMinNSigmasTPC[5] = {-3.0, -3.0, -3.0, -3.0, -3.0}; ///< nsigmas TPC lower limit for e, mu, pi, Ka, and p - float mMaxNSigmasTPC[5] = {3.0, 3.0, 3.0, 3.0, 3.0}; ///< nsigmas TPC upper limit for e, mu, pi, Ka, and p - float mPThreshold = 0.0; ///< momentum threshold for considering TOF information - bool mRequireTOF = true; ///< require or not the presence of TOF when the momentum threshold is passed - float mMinNSigmasTOF[5] = {-3.0, -3.0, -3.0, -3.0, -3.0}; ///< nsigmas TOF lower limit for e, mu, pi, Ka, and p - float mMaxNSigmasTOF[5] = {3.0, 3.0, 3.0, 3.0, 3.0}; ///< nsigmas TOF upper limit for e, mu, pi, Ka, and p - bool m2Dcut = true; ///< use an elliptic cut using TPC and TOF nsigmas - bool mExclude = false; ///< should the identified track be excluded for analysis? + std::vector mMinNSigmasTPC = {-3.0f, -3.0f, -3.0f, -3.0f, -3.0f}; ///< nsigmas TPC lower limit for e, mu, pi, Ka, and p + std::vector mMaxNSigmasTPC = {3.0f, 3.0f, 3.0f, 3.0f, 3.0f}; ///< nsigmas TPC upper limit for e, mu, pi, Ka, and p + float mPThreshold = 0.0; ///< momentum threshold for considering TOF information + bool mRequireTOF = true; ///< require or not the presence of TOF when the momentum threshold is passed + std::vector mMinNSigmasTOF = {-3.0f, -3.0f, -3.0f, -3.0f, -3.0f}; ///< nsigmas TOF lower limit for e, mu, pi, Ka, and p + std::vector mMaxNSigmasTOF = {3.0f, 3.0f, 3.0f, 3.0f, 3.0f}; ///< nsigmas TOF upper limit for e, mu, pi, Ka, and p + bool m2Dcut = true; ///< use an elliptic cut using TPC and TOF nsigmas + bool mExclude = false; ///< should the identified track be excluded for analysis? private: ClassDefNV(TrackSelectionPIDCfg, 1); }; diff --git a/PWGCF/TableProducer/dptdptfilter.cxx b/PWGCF/TableProducer/dptdptfilter.cxx index 2d370e8e4ab..ed3590a29cc 100644 --- a/PWGCF/TableProducer/dptdptfilter.cxx +++ b/PWGCF/TableProducer/dptdptfilter.cxx @@ -17,6 +17,7 @@ #include "Framework/ASoAHelpers.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" +#include "Common/Core/TableHelper.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/PIDResponse.h" @@ -25,6 +26,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" #include #include #include @@ -162,6 +164,7 @@ struct DptDptFilter { Configurable cfgSystem{"syst", "PbPb", "System: pp, PbPb, Pbp, pPb, XeXe, ppRun3, PbPbRun3. Default PbPb"}; Configurable cfgDataType{"datatype", "data", "Data type: data, datanoevsel, MC, FastMC, OnTheFlyMC. Default data"}; Configurable cfgTriggSel{"triggsel", "MB", "Trigger selection: MB, None. Default MB"}; + Configurable cfgCentSpec{"centralities", "00-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", "Centrality/multiplicity ranges in min-max separated by commas"}; Configurable cfgBinning{"binning", {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; @@ -530,181 +533,6 @@ T computeRMS(std::vector& vec) struct DptDptFilterTracks { - struct PIDSpeciesSelection { - static const std::vector pdgcodes; - static const std::vector spnames; - static const std::vector sptitles; - static const std::vector spfnames; - static const char hadname[]; - static const char hadtitle[]; - static const char hadfname[]; - uint getNSpecies() { return config.size(); } - const char* getSpeciesName(uint8_t ix) { return spnames[species[ix]].data(); } - const char* getSpeciesTitle(uint8_t ix) { return sptitles[species[ix]].data(); } - const char* getSpeciesFName(uint8_t ix) { return spfnames[species[ix]].data(); } - static const char* getHadName() { return hadname; } - static const char* getHadTitle() { return hadtitle; } - static const char* getHadFName() { return hadfname; } - void Add(uint8_t sp, const o2::analysis::TrackSelectionPIDCfg* incfg) - { - o2::analysis::TrackSelectionPIDCfg* cfg = new o2::analysis::TrackSelectionPIDCfg(*incfg); - config.push_back(cfg); - species.push_back(sp); - - auto last = config[config.size() - 1]; - uint8_t lastsp = species[config.size() - 1]; - LOGF(info, "Inserted species %d with", lastsp); - LOGF(info, " minTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTPC[0], last->mMinNSigmasTPC[1], last->mMinNSigmasTPC[2], last->mMinNSigmasTPC[3], last->mMinNSigmasTPC[4]); - LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); - LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); - LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); - } - void AddExclude(uint8_t sp, const o2::analysis::TrackSelectionPIDCfg* incfg) - { - o2::analysis::TrackSelectionPIDCfg* cfg = new o2::analysis::TrackSelectionPIDCfg(*incfg); - configexclude.push_back(cfg); - speciesexclude.push_back(sp); - auto last = configexclude[configexclude.size() - 1]; - uint8_t lastsp = speciesexclude[configexclude.size() - 1]; - - LOGF(info, "Inserted species %d for exclusion with", lastsp); - LOGF(info, " minTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTPC[0], last->mMinNSigmasTPC[1], last->mMinNSigmasTPC[2], last->mMinNSigmasTPC[3], last->mMinNSigmasTPC[4]); - LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); - LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); - LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); - } - template - int8_t whichSpecies(TrackObject const& track) - { - std::vector tpcnsigmas = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; - std::vector tofnsigmas = {track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; - - auto closeTo = [](auto& values, auto& mindet, auto& maxdet, uint8_t sp) { - if (mindet[sp] <= values[sp] && values[sp] < maxdet[sp]) { - return true; - } else { - return false; - } - }; - auto awayFrom = [](auto& values, auto& mindet, auto& maxdet, uint8_t sp) { - for (int ix = 0; ix < 5; ix++) { - if (ix != sp) { - if (mindet[ix] <= values[ix] && values[ix] < maxdet[ix]) { - return false; - } - } else { - continue; - } - } - return true; - }; - auto closeToTPC = [&](auto& config, uint8_t sp) { - return closeTo(tpcnsigmas, config->mMinNSigmasTPC, config->mMaxNSigmasTPC, sp); - }; - auto awayFromTPC = [&](auto& config, uint8_t sp) { - return awayFrom(tpcnsigmas, config->mMinNSigmasTPC, config->mMaxNSigmasTPC, sp); - }; - auto closeToTOF = [&](auto& config, uint8_t sp) { - return closeTo(tofnsigmas, config->mMinNSigmasTOF, config->mMaxNSigmasTOF, sp); - }; - auto closeToTPCTOF = [&](auto& config, uint8_t sp) { - if (config->m2Dcut) { - float a = (config->mMaxNSigmasTPC[sp] - config->mMinNSigmasTPC[sp]) / 2.0; - float b = (config->mMaxNSigmasTOF[sp] - config->mMinNSigmasTOF[sp]) / 2.0; - float oa = (config->mMaxNSigmasTPC[sp] + config->mMinNSigmasTPC[sp]) / 2.0; - float ob = (config->mMaxNSigmasTOF[sp] + config->mMinNSigmasTOF[sp]) / 2.0; - float vtpc = tpcnsigmas[sp] - oa; - float vtof = tofnsigmas[sp] - ob; - return ((vtpc * vtpc / a / a + vtof * vtof / b / b) < 1); - } else { - return closeToTPC(config, sp) && closeToTOF(config, sp); - } - }; - auto awayFromTPCTOF = [&](auto& config, uint8_t sp) { - for (uint8_t ix = 0; ix < 5; ++ix) { - if (ix != sp) { - if (closeToTPCTOF(config, ix)) { - return false; - } - } else { - continue; - } - } - return true; - }; - auto aboveThreshold = [&](auto& config) { - return ((config->mPThreshold > 0.0) && (config->mPThreshold < track.p())); - }; - auto isA = [&](auto& config, uint8_t sp) { - if (aboveThreshold(config)) { - if (track.hasTOF()) { - return closeToTPCTOF(config, sp) && awayFromTPCTOF(config, sp); - } else { - if (config->mRequireTOF) { - return false; - } - } - } - /* we are here */ - /* - below the threshold */ - /* - above the threshold without TOF and without requiring it */ - /* so we check only the TPC information */ - return closeToTPC(config, sp) && awayFromTPC(config, sp); - }; - - /* let's first check the exclusion from the analysis */ - for (uint8_t ix = 0; ix < configexclude.size(); ++ix) { - if (isA(configexclude[ix], speciesexclude[ix])) { - return -ix; - } - } - /* we don't exclude it so check which species if any required */ - if (config.size() > 0) { - int8_t id = -127; - for (uint8_t ix = 0; ix < config.size(); ++ix) { - if (isA(config[ix], species[ix])) { - if (id < 0) { - id = ix; - } else { - /* already identified once */ - return -127; - } - } - } - return id; - } else { - /* charged hadron */ - return 0; - } - } - template - int8_t whichTruthSpecies(ParticleObject part) - { - int pdgcode = std::abs(part.pdgCode()); - /* let's first check the exclusion from the analysis */ - for (uint8_t ix = 0; ix < configexclude.size(); ++ix) { - if (pdgcode == pdgcodes[speciesexclude[ix]]) { - return -ix; - } - } - /* we don't exclude it so check which species if any required */ - if (config.size() > 0) { - for (uint8_t ix = 0; ix < config.size(); ++ix) { - if (pdgcode == pdgcodes[species[ix]]) { - return ix; - } - } - return -127; - } else { - return 0; - } - } - std::vector config; ///< the PID selection configuration of the species to include in the analysis - std::vector species; ///< the species index of the species to include in the analysis - std::vector configexclude; ///< the PID selection configuration of the species to exclude from the analysis - std::vector speciesexclude; ///< the species index of teh species to exclude from the analysis - }; - Produces scannedtracks; Produces tracksinfo; Produces scannedgentracks; @@ -712,11 +540,6 @@ struct DptDptFilterTracks { Configurable cfgFullDerivedData{"fullderiveddata", false, "Produce the full derived data for external storage. Default false"}; Configurable cfgTrackType{"trktype", 1, "Type of selected tracks: 0 = no selection, 1 = Run2 global tracks FB96, 3 = Run3 tracks, 5 = Run2 TPC only tracks, 7 = Run 3 TPC only tracks. Default 1"}; - Configurable cfgSystem{"syst", "PbPb", "System: pp, PbPb, Pbp, pPb, XeXe, ppRun3, PbPbRun3. Default PbPb"}; - Configurable cfgDataType{"datatype", "data", "Data type: data, datanoevsel, MC, FastMC, OnTheFlyMC. Default data"}; - Configurable cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, - "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; Configurable cfgTraceDCAOutliers{"trackdcaoutliers", {false, 0.0, 0.0}, "Track the generator level DCAxy outliers: false/true, low dcaxy, up dcaxy. Default {false,0.0,0.0}"}; Configurable cfgTraceOutOfSpeciesParticles{"trackoutparticles", false, "Track the particles which are not e,mu,pi,K,p: false/true. Default false"}; Configurable cfgRecoIdMethod{"recoidmethod", 0, "Method for identifying reconstructed tracks: 0 No PID, 1 PID, 2 mcparticle. Default 0"}; @@ -738,23 +561,24 @@ struct DptDptFilterTracks { PIDSpeciesSelection pidselector; bool checkAmbiguousTracks = false; - void init(InitContext&) + void init(InitContext& initContext) { LOGF(info, "DptDptFilterTracks::init()"); fullDerivedData = cfgFullDerivedData; /* update with the configurable values */ - /* the binning */ - ptbins = cfgBinning->mPTbins; - ptlow = cfgBinning->mPTmin; - ptup = cfgBinning->mPTmax; - etabins = cfgBinning->mEtabins; - etalow = cfgBinning->mEtamin; - etaup = cfgBinning->mEtamax; - zvtxbins = cfgBinning->mZVtxbins; - zvtxlow = cfgBinning->mZVtxmin; - zvtxup = cfgBinning->mZVtxmax; + /* self configure the binning */ + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxbins", zvtxbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmin", zvtxlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmax", zvtxup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTbins", ptbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmin", ptlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmax", ptup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtabins", etabins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamin", etalow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamax", etaup); + /* the track types and combinations */ tracktype = cfgTrackType.value; initializeTrackSelection(); @@ -791,9 +615,13 @@ struct DptDptFilterTracks { useOwnTrackSelection = false; } + /* self configure system type and data type */ /* if the system type is not known at this time, we have to put the initialization somewhere else */ - fSystem = getSystemType(cfgSystem); - fDataType = getDataType(cfgDataType); + std::string tmpstr; + getTaskOptionValue(initContext, "dpt-dpt-filter", "syst", tmpstr); + fSystem = getSystemType(tmpstr); + getTaskOptionValue(initContext, "dpt-dpt-filter", "datatype", tmpstr); + fDataType = getDataType(tmpstr); fPDG = TDatabasePDG::Instance(); /* required ambiguous tracks checks? */ @@ -1204,14 +1032,6 @@ struct DptDptFilterTracks { PROCESS_SWITCH(DptDptFilterTracks, filterGenerated, "Generated particles filtering", true) }; -const std::vector DptDptFilterTracks::PIDSpeciesSelection::pdgcodes = {11, 13, 211, 321, 2212}; -const std::vector DptDptFilterTracks::PIDSpeciesSelection::spnames = {"e", "mu", "pi", "ka", "p"}; -const std::vector DptDptFilterTracks::PIDSpeciesSelection::sptitles = {"e", "#mu", "#pi", "K", "p"}; -const std::vector DptDptFilterTracks::PIDSpeciesSelection::spfnames = {"E", "Mu", "Pi", "Ka", "Pr"}; -const char DptDptFilterTracks::PIDSpeciesSelection::hadname[] = "h"; -const char DptDptFilterTracks::PIDSpeciesSelection::hadtitle[] = "h"; -const char DptDptFilterTracks::PIDSpeciesSelection::hadfname[] = "Ha"; - template int8_t DptDptFilterTracks::trackIdentification(TrackObject const& track) { diff --git a/PWGCF/TableProducer/dptdptfilter.h b/PWGCF/TableProducer/dptdptfilter.h index 2f69f134417..0b5eaa6f315 100644 --- a/PWGCF/TableProducer/dptdptfilter.h +++ b/PWGCF/TableProducer/dptdptfilter.h @@ -732,6 +732,185 @@ inline bool AcceptParticle(ParticleObject& particle, MCCollisionObject const& co return false; } +////////////////////////////////////////////////////////////////////////////////// +/// PID +////////////////////////////////////////////////////////////////////////////////// + +struct PIDSpeciesSelection { + const std::vector pdgcodes = {11, 13, 211, 321, 2212}; + const std::vector spnames = {"e", "mu", "pi", "ka", "p"}; + const std::vector sptitles = {"e", "#mu", "#pi", "K", "p"}; + const std::vector spfnames = {"E", "Mu", "Pi", "Ka", "Pr"}; + const char* hadname = "h"; + const char* hadtitle = "h"; + const char* hadfname = "Ha"; + uint getNSpecies() { return config.size(); } + const char* getSpeciesName(uint8_t ix) { return spnames[species[ix]].data(); } + const char* getSpeciesTitle(uint8_t ix) { return sptitles[species[ix]].data(); } + const char* getSpeciesFName(uint8_t ix) { return spfnames[species[ix]].data(); } + const char* getHadName() { return hadname; } + const char* getHadTitle() { return hadtitle; } + const char* getHadFName() { return hadfname; } + void Add(uint8_t sp, o2::analysis::TrackSelectionPIDCfg* incfg) + { + o2::analysis::TrackSelectionPIDCfg* cfg = new o2::analysis::TrackSelectionPIDCfg(*incfg); + config.push_back(cfg); + species.push_back(sp); + + auto last = config[config.size() - 1]; + uint8_t lastsp = species[config.size() - 1]; + LOGF(info, "Inserted species %d with", lastsp); + LOGF(info, " minTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTPC[0], last->mMinNSigmasTPC[1], last->mMinNSigmasTPC[2], last->mMinNSigmasTPC[3], last->mMinNSigmasTPC[4]); + LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); + LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); + LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); + } + void AddExclude(uint8_t sp, const o2::analysis::TrackSelectionPIDCfg* incfg) + { + o2::analysis::TrackSelectionPIDCfg* cfg = new o2::analysis::TrackSelectionPIDCfg(*incfg); + configexclude.push_back(cfg); + speciesexclude.push_back(sp); + auto last = configexclude[configexclude.size() - 1]; + uint8_t lastsp = speciesexclude[configexclude.size() - 1]; + + LOGF(info, "Inserted species %d for exclusion with", lastsp); + LOGF(info, " minTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTPC[0], last->mMinNSigmasTPC[1], last->mMinNSigmasTPC[2], last->mMinNSigmasTPC[3], last->mMinNSigmasTPC[4]); + LOGF(info, " maxTPC nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTPC[0], last->mMaxNSigmasTPC[1], last->mMaxNSigmasTPC[2], last->mMaxNSigmasTPC[3], last->mMaxNSigmasTPC[4]); + LOGF(info, " minTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMinNSigmasTOF[0], last->mMinNSigmasTOF[1], last->mMinNSigmasTOF[2], last->mMinNSigmasTOF[3], last->mMinNSigmasTOF[4]); + LOGF(info, " maxTOF nsigmas: el: %.2f, mu: %.2f, pi: %.2f, ka: %.2f, pr: %.2f", last->mMaxNSigmasTOF[0], last->mMaxNSigmasTOF[1], last->mMaxNSigmasTOF[2], last->mMaxNSigmasTOF[3], last->mMaxNSigmasTOF[4]); + } + template + int8_t whichSpecies(TrackObject const& track) + { + std::vector tpcnsigmas = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::vector tofnsigmas = {track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + + auto closeTo = [](auto& values, auto& mindet, auto& maxdet, uint8_t sp) { + if (mindet[sp] <= values[sp] && values[sp] < maxdet[sp]) { + return true; + } else { + return false; + } + }; + auto awayFrom = [](auto& values, auto& mindet, auto& maxdet, uint8_t sp) { + for (int ix = 0; ix < 5; ix++) { + if (ix != sp) { + if (mindet[ix] <= values[ix] && values[ix] < maxdet[ix]) { + return false; + } + } else { + continue; + } + } + return true; + }; + auto closeToTPC = [&](auto& config, uint8_t sp) { + return closeTo(tpcnsigmas, config->mMinNSigmasTPC, config->mMaxNSigmasTPC, sp); + }; + auto awayFromTPC = [&](auto& config, uint8_t sp) { + return awayFrom(tpcnsigmas, config->mMinNSigmasTPC, config->mMaxNSigmasTPC, sp); + }; + auto closeToTOF = [&](auto& config, uint8_t sp) { + return closeTo(tofnsigmas, config->mMinNSigmasTOF, config->mMaxNSigmasTOF, sp); + }; + auto closeToTPCTOF = [&](auto& config, uint8_t sp) { + if (config->m2Dcut) { + float a = (config->mMaxNSigmasTPC[sp] - config->mMinNSigmasTPC[sp]) / 2.0; + float b = (config->mMaxNSigmasTOF[sp] - config->mMinNSigmasTOF[sp]) / 2.0; + float oa = (config->mMaxNSigmasTPC[sp] + config->mMinNSigmasTPC[sp]) / 2.0; + float ob = (config->mMaxNSigmasTOF[sp] + config->mMinNSigmasTOF[sp]) / 2.0; + float vtpc = tpcnsigmas[sp] - oa; + float vtof = tofnsigmas[sp] - ob; + return ((vtpc * vtpc / a / a + vtof * vtof / b / b) < 1); + } else { + return closeToTPC(config, sp) && closeToTOF(config, sp); + } + }; + auto awayFromTPCTOF = [&](auto& config, uint8_t sp) { + for (uint8_t ix = 0; ix < 5; ++ix) { + if (ix != sp) { + if (closeToTPCTOF(config, ix)) { + return false; + } + } else { + continue; + } + } + return true; + }; + auto aboveThreshold = [&](auto& config) { + return ((config->mPThreshold > 0.0) && (config->mPThreshold < track.p())); + }; + auto isA = [&](auto& config, uint8_t sp) { + if (aboveThreshold(config)) { + if (track.hasTOF()) { + return closeToTPCTOF(config, sp) && awayFromTPCTOF(config, sp); + } else { + if (config->mRequireTOF) { + return false; + } + } + } + /* we are here */ + /* - below the threshold */ + /* - above the threshold without TOF and without requiring it */ + /* so we check only the TPC information */ + return closeToTPC(config, sp) && awayFromTPC(config, sp); + }; + + /* let's first check the exclusion from the analysis */ + for (uint8_t ix = 0; ix < configexclude.size(); ++ix) { + if (isA(configexclude[ix], speciesexclude[ix])) { + return -ix; + } + } + /* we don't exclude it so check which species if any required */ + if (config.size() > 0) { + int8_t id = -127; + for (uint8_t ix = 0; ix < config.size(); ++ix) { + if (isA(config[ix], species[ix])) { + if (id < 0) { + id = ix; + } else { + /* already identified once */ + return -127; + } + } + } + return id; + } else { + /* charged hadron */ + return 0; + } + } + template + int8_t whichTruthSpecies(ParticleObject part) + { + int pdgcode = std::abs(part.pdgCode()); + /* let's first check the exclusion from the analysis */ + for (uint8_t ix = 0; ix < configexclude.size(); ++ix) { + if (pdgcode == pdgcodes[speciesexclude[ix]]) { + return -ix; + } + } + /* we don't exclude it so check which species if any required */ + if (config.size() > 0) { + for (uint8_t ix = 0; ix < config.size(); ++ix) { + if (pdgcode == pdgcodes[species[ix]]) { + return ix; + } + } + return -127; + } else { + return 0; + } + } + std::vector config; ///< the PID selection configuration of the species to include in the analysis + std::vector species; ///< the species index of the species to include in the analysis + std::vector configexclude; ///< the PID selection configuration of the species to exclude from the analysis + std::vector speciesexclude; ///< the species index of teh species to exclude from the analysis +}; + } // namespace dptdptfilter } // namespace analysis } // namespace o2 diff --git a/PWGCF/Tasks/dptdptcorrelations.cxx b/PWGCF/Tasks/dptdptcorrelations.cxx index 89b2eda3a54..ad9c2766ea7 100644 --- a/PWGCF/Tasks/dptdptcorrelations.cxx +++ b/PWGCF/Tasks/dptdptcorrelations.cxx @@ -25,6 +25,7 @@ #include #include "Common/Core/TrackSelection.h" +#include "Common/Core/TableHelper.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -33,6 +34,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" #include "PWGCF/Core/AnalysisConfigurableCuts.h" #include "PWGCF/Core/PairCuts.h" #include "PWGCF/DataModel/DptDptFiltered.h" @@ -675,15 +677,9 @@ struct DptDptCorrelationsTask { Configurable cfgTwoTrackCut{"twotrackcut", -1, "Two-tracks cut: -1 = off; >0 otherwise distance value (suggested: 0.02"}; Configurable cfgTwoTrackCutMinRadius{"twotrackcutminradius", 0.8f, "Two-tracks cut: radius in m from which two-tracks cut is applied"}; - Configurable cfgSpecies{"species", "Ha", "The species to analyze: Ha, Pi, Ka, Pr, separated by commas. Default: Ha"}; Configurable cfgSmallDCE{"smalldce", true, "Use small data collecting engine for singles processing, true = yes. Default = true"}; Configurable cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable cfgProcessME{"processmixedevents", false, "Process mixed events: false = no, just same event, true = yes, also process mixed events"}; - Configurable cfgCentSpec{"centralities", "00-05,05-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", "Centrality/multiplicity ranges in min-max separated by commas"}; - - Configurable cfgBinning{"binning", - {28, -7.0, 7.0, 18, 0.2, 2.0, 16, -0.8, 0.8, 72, 0.5}, - "triplets - nbins, min, max - for z_vtx, pT, eta and phi, binning plus bin fraction of phi origin shift"}; Configurable cfgPtOrder{"ptorder", false, "enforce pT_1 < pT_2. Defalut: false"}; struct : ConfigurableGroup { Configurable cfgCCDBUrl{"input_ccdburl", "http://ccdb-test.cern.ch:8080", "The CCDB url for the input file"}; @@ -693,25 +689,25 @@ struct DptDptCorrelationsTask { OutputObj fOutput{"DptDptCorrelationsData", OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType::OutputObjSource}; - void init(InitContext const&) + void init(InitContext& initContext) { using namespace correlationstask; using namespace o2::analysis::dptdptfilter; - /* update with the configurable values */ - ptbins = cfgBinning->mPTbins; - ptlow = cfgBinning->mPTmin; - ptup = cfgBinning->mPTmax; - etabins = cfgBinning->mEtabins; - etalow = cfgBinning->mEtamin; - etaup = cfgBinning->mEtamax; - zvtxbins = cfgBinning->mZVtxbins; - zvtxlow = cfgBinning->mZVtxmin; - zvtxup = cfgBinning->mZVtxmax; - phibins = cfgBinning->mPhibins; + /* self configure the binning */ + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxbins", zvtxbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmin", zvtxlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmax", zvtxup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTbins", ptbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmin", ptlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmax", ptup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtabins", etabins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamin", etalow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamax", etaup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPhibins", phibins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPhibinshift", phibinshift); philow = 0.0f; phiup = constants::math::TwoPI; - phibinshift = cfgBinning->mPhibinshift; processpairs = cfgProcessPairs.value; processmixedevents = cfgProcessME.value; ptorder = cfgPtOrder.value; @@ -757,16 +753,41 @@ struct DptDptCorrelationsTask { /* create the data collecting engine instances according to the configured centrality/multiplicity ranges */ { - /* configuring the desired species */ - TObjArray* tokens = TString(cfgSpecies.value.c_str()).Tokenize(","); - int nspecies = tokens->GetEntries(); - for (int isp = 0; isp < nspecies; ++isp) { - poinames.push_back(std::string(tokens->At(isp)->GetName())); - tnames.push_back(std::string(TString::Format("%sP", tokens->At(isp)->GetName()).Data())); - tnames.push_back(std::string(TString::Format("%sM", tokens->At(isp)->GetName()).Data())); - LOGF(info, "Incorporated species name %s to the analysis", poinames[isp].c_str()); + /* self configure the desired species */ + o2::analysis::dptdptfilter::PIDSpeciesSelection pidselector; + std::vector cfgnames = {"pipidsel", "kapidsel", "prpidsel"}; + std::vector spids = {2, 3, 4}; + for (uint i = 0; i < cfgnames.size(); ++i) { + auto includeIt = [&pidselector, &initContext](int spid, auto name) { + bool mUseIt = false; + bool mExcludeIt = false; + if (getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mUseIt", name.c_str()).Data(), mUseIt) && + getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mExclude", name.c_str()).Data(), mExcludeIt)) { + if (mUseIt && !mExcludeIt) { + auto cfg = new o2::analysis::TrackSelectionPIDCfg(); + cfg->mUseIt = true; + cfg->mExclude = false; + pidselector.Add(spid, cfg); + } + } + }; + includeIt(spids[i], cfgnames[i]); + } + uint nspecies = pidselector.getNSpecies(); + if (nspecies == 0) { + /* unidentified analysis */ + poinames.push_back(pidselector.getHadFName()); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getHadFName()).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getHadFName()).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[0].c_str()); + } else { + for (uint8_t ix = 0; ix < nspecies; ++ix) { + poinames.push_back(std::string(pidselector.getSpeciesFName(ix))); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getSpeciesFName(ix)).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getSpeciesFName(ix)).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[ix].c_str()); + } } - delete tokens; uint ntracknames = tnames.size(); for (uint isp = 0; isp < ntracknames; ++isp) { trackPairsNames.push_back(std::vector()); @@ -776,11 +797,30 @@ struct DptDptCorrelationsTask { } } - /* the centrality/multiplicity ranges */ - tokens = TString(cfgCentSpec.value.c_str()).Tokenize(","); - ncmranges = tokens->GetEntries(); - fCentMultMin = new float[ncmranges]; - fCentMultMax = new float[ncmranges]; + /* self configure the centrality/multiplicity ranges */ + std::string centspec; + if (getTaskOptionValue(initContext, "dpt-dpt-filter", "centralities", centspec)) { + LOGF(info, "Got the centralities specification: %s", centspec.c_str()); + auto tokens = TString(centspec.c_str()).Tokenize(","); + ncmranges = tokens->GetEntries(); + fCentMultMin = new float[ncmranges]; + fCentMultMax = new float[ncmranges]; + for (int i = 0; i < ncmranges; ++i) { + float cmmin = 0.0f; + float cmmax = 0.0f; + sscanf(tokens->At(i)->GetName(), "%f-%f", &cmmin, &cmmax); + fCentMultMin[i] = cmmin; + fCentMultMax[i] = cmmax; + } + delete tokens; + } else { + LOGF(info, "No centralities specification. Setting it to: 0-100"); + ncmranges = 1; + fCentMultMin = new float[ncmranges]; + fCentMultMax = new float[ncmranges]; + fCentMultMin[0] = 0.0f; + fCentMultMax[0] = 100.0f; + } dataCE = new DataCollectingEngine*[ncmranges]; if (cfgSmallDCE) { dataCE_small = new DataCollectingEngine*[ncmranges]; @@ -811,28 +851,23 @@ struct DptDptCorrelationsTask { initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg)); return dce; }; - float cmmin = 0.0f; - float cmmax = 0.0f; - sscanf(tokens->At(i)->GetName(), "%f-%f", &cmmin, &cmmax); - fCentMultMin[i] = cmmin; - fCentMultMax[i] = cmmax; + TString range = TString::Format("%d-%d", int(fCentMultMin[i]), int(fCentMultMax[i])); if (cfgSmallDCE.value) { if (processpairs) { LOGF(fatal, "Processing pairs cannot be used with the small DCE, please configure properly!!"); } - dataCE_small[i] = builSmallDCEInstance(tokens->At(i)->GetName()); + dataCE_small[i] = builSmallDCEInstance(range.Data()); } else { - dataCE[i] = buildCEInstance(tokens->At(i)->GetName()); + dataCE[i] = buildCEInstance(range.Data()); } if (processmixedevents) { /* consistency check */ if (cfgSmallDCE.value) { LOGF(fatal, "Mixed events cannot be used with the small DCE, please configure properly!!"); } - dataCEME[i] = buildCEInstance(tokens->At(i)->GetName(), true); + dataCEME[i] = buildCEInstance(range.Data(), true); } } - delete tokens; for (int i = 0; i < ncmranges; ++i) { LOGF(info, " centrality/multipliicty range: %d, low limit: %f, up limit: %f", i, fCentMultMin[i], fCentMultMax[i]); } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index dbdfd2bdd01..e471ed3f07f 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -27,3 +27,8 @@ o2physics_add_dpl_workflow(identifiedbf-filter-qa SOURCES identifiedbfqa.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(twopartcorr-efficiency-qc + SOURCES efficiencyAndQc.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/efficiencyAndQc.cxx b/PWGCF/TwoParticleCorrelations/Tasks/efficiencyAndQc.cxx new file mode 100644 index 00000000000..d4bba53caf2 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/efficiencyAndQc.cxx @@ -0,0 +1,504 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TableHelper.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/Expressions.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Math/MatrixFunctions.h" +#include "Math/SMatrix.h" + +#include "PWGCF/Core/AnalysisConfigurableCuts.h" +#include "PWGCF/DataModel/DptDptFiltered.h" +#include "PWGCF/TableProducer/dptdptfilter.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; + +namespace efficiencyandqatask +{ +// initialized during self configuration +int ptbins = 0; +float ptlow = 0.0f; +float ptup = 0.0f; +int etabins = 0; +float etalow = 0.0f; +float etaup = 0.0f; +int zvtxbins = 0; +float zvtxlow = 0.0f; +float zvtxup = 0.0f; + +/// \enum KindOfProcess +/// \brief The kind of processing for templating the procedures +enum KindOfProcess { + kReco = 0, ///< processing over reconstructed particles/tracks + kGen ///< processing over generated particles +}; + +// initialized during self configuration +std::vector poinames; ///< the species of interest names +std::vector tnames; ///< the track names +} // namespace efficiencyandqatask + +/* the QA data collecting engine */ +struct QADataCollectingEngine { + size_t nch = efficiencyandqatask::tnames.size(); + + //=================================================== + // The QA output objects + //=================================================== + /* efficiency histograms histograms */ + /* when two indexes, first index reco and detector level, second index generator level */ + /* when no indexes, reco and detector level */ + std::vector> fhPtB{2, nullptr}; + std::vector> fhPt_vs_EtaB{2, nullptr}; + std::vector> fhPt_vs_ZvtxB{2, nullptr}; + std::vector>> fhPtA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_ZvtxA{2, {nch, nullptr}}; + std::vector> fhPt_vs_EtaItsA{nch, nullptr}; + std::vector> fhPt_vs_EtaTpcA{nch, nullptr}; + std::vector> fhPt_vs_EtaItsTpcA{nch, nullptr}; + std::vector> fhPt_vs_EtaItsTofA{nch, nullptr}; + std::vector> fhPt_vs_EtaTpcTofA{nch, nullptr}; + std::vector> fhPt_vs_EtaItsTpcTofA{nch, nullptr}; + /* primaries and secondaries */ + /* overall, first index detector level second index generator level */ + /* detailed, first index detector level, second index associated particle */ + std::vector> fhPt_vs_EtaPrimA{nch, nullptr}; + std::vector>> fhPt_vs_EtaPrimItsA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaPrimItsTpcA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaPrimItsTpcTofA{2, {nch, nullptr}}; + std::vector> fhPt_vs_EtaSecA{nch, nullptr}; + std::vector>> fhPt_vs_EtaSecItsA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaSecItsTpcA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaSecItsTpcTofA{2, {nch, nullptr}}; + std::vector> fhPt_vs_EtaMatA{nch, nullptr}; + std::vector>> fhPt_vs_EtaMatItsA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaMatItsTpcA{2, {nch, nullptr}}; + std::vector>> fhPt_vs_EtaMatItsTpcTofA{2, {nch, nullptr}}; + /* QC histograms */ + std::shared_ptr fhITS_NCls_vs_PtB{nullptr}; + std::shared_ptr fhITS_Chi2NCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_FindableNCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_FoundNCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_SharedNCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_FractionSharedCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_CrossedRows_vs_PtB{nullptr}; + std::shared_ptr fhTPC_CrossedRowsOverFindableCls_vs_PtB{nullptr}; + std::shared_ptr fhTPC_Chi2NCls_vs_PtB{nullptr}; + std::vector> fhITS_NCls_vs_PtA{nch, nullptr}; + std::vector> fhITS_Chi2NCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_FindableNCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_FoundNCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_SharedNCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_FractionSharedCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_CrossedRows_vs_PtA{nch, nullptr}; + std::vector> fhTPC_CrossedRowsOverFindableCls_vs_PtA{nch, nullptr}; + std::vector> fhTPC_Chi2NCls_vs_PtA{nch, nullptr}; + + template + void init(HistogramRegistry& registry, const char* dirname) + { + using namespace efficiencyandqatask; + + const AxisSpec ptAxis{ptbins, ptlow, ptup, "#it{p}_{T} (GeV/c)"}; + const AxisSpec etaAxis{etabins, etalow, etaup, "#eta"}; + const AxisSpec phiAxis{360, 0.0f, constants::math::TwoPI, "#varphi"}; + const AxisSpec zvtxAxis{zvtxbins, zvtxlow, zvtxup, "#it{z}_{vtx}"}; + const AxisSpec itsNClsAxis{8, -0.5, 7.5, "ITS n clusters"}; + const AxisSpec itsCh2Axis{100, 0, 40, "#Chi^{2}/Cls ITS"}; + const AxisSpec tpcNClsAxis{165, -0.5, 164.5, "TPC n clusters"}; + const AxisSpec tpcNRowsAxis{165, -0.5, 164.5, "TPC n rows"}; + const AxisSpec tpcFractionAxis{100, 0, 1, "fraction"}; + const AxisSpec tpcXRowsOverFindClsAxis{60, 0.7, 1.3, "fraction"}; + const AxisSpec tpcCh2Axis{100, 0, 10, "#Chi^{2}/Cls TPC"}; + +#define ADDHISTOGRAM(thetype, thedir, therecogen, thewhen, thename, thetitle, thekind, thebinning...) \ + registry.add(TString::Format("%s/%s/%s/%s", thedir, therecogen, thewhen, thename).Data(), thetitle, thekind, thebinning) +#define ADDHISTOGRAMID(thetype, thedir, therecogen, thewhen, thename, thetitle, theid, thekind, thebinning...) \ + registry.add(TString::Format("%s/%s/%s/%s_%s", thedir, therecogen, thewhen, thename, theid.c_str()).Data(), TString::Format("%s %s", thetitle, theid.c_str()).Data(), thekind, {thebinning}) + + /* the reconstructed and generated levels histograms */ + std::string recogen = (kind == kReco) ? "Reco" : "Gen"; + fhPtB[kind] = ADDHISTOGRAM(TH1, dirname, recogen.c_str(), "Before", "Pt", "#it{p}_{T}", kTH1F, {ptAxis}); + fhPt_vs_EtaB[kind] = ADDHISTOGRAM(TH2, dirname, recogen.c_str(), "Before", "PtVsEta", "#it{p}_T vs #eta", kTH2F, {etaAxis, ptAxis}); + fhPt_vs_ZvtxB[kind] = ADDHISTOGRAM(TH2, dirname, recogen.c_str(), "Before", "PtVsZvtx", "#it{p}_T vs #it{z}_{vtx}", kTH2F, {zvtxAxis, ptAxis}); + for (uint isp = 0; isp < nch; ++isp) { + fhPtA[kind][isp] = ADDHISTOGRAMID(TH1, dirname, recogen.c_str(), "After", "Pt", "#it{p}_{T}", tnames[isp], kTH1F, {ptAxis}); + fhPt_vs_EtaA[kind][isp] = ADDHISTOGRAMID(TH2, dirname, recogen.c_str(), "After", "PtVsEta", "#it{p}_{T} vs #eta", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_ZvtxA[kind][isp] = ADDHISTOGRAMID(TH2, dirname, recogen.c_str(), "After", "PtVsZvtx", "#it{p}_{T} vs #it{z}_{zvtx}", tnames[isp], kTH2F, {zvtxAxis, ptAxis}); + } + + if constexpr (kind == kReco) { + /* only the reconstructed level histograms*/ + fhITS_NCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "ITSNCls", "ITS clusters", kTH2F, {ptAxis, itsNClsAxis}); + fhITS_Chi2NCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "ITSChi2NCls", "ITS #Chi^{2}", kTH2F, {ptAxis, itsCh2Axis}); + fhTPC_FindableNCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCFindableNCls", "TPC findable clusters", kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_FoundNCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCFoundNCls", "TPC found clusters", kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_SharedNCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCSharedNCls", "TPC shared clusters", kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_FractionSharedCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCFractionSharedCls", "TPC fraction shared clusters", kTH2F, {ptAxis, tpcFractionAxis}); + fhTPC_CrossedRows_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCXrows", "TPC crossed rows", kTH2F, {ptAxis, tpcNRowsAxis}); + fhTPC_CrossedRowsOverFindableCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "XRowsOverFindableCls", "TPC xrows over findable clusters", kTH2F, {ptAxis, tpcXRowsOverFindClsAxis}); + fhTPC_Chi2NCls_vs_PtB = ADDHISTOGRAM(TH2, dirname, "Reco", "Before", "TPCChi2NCls", "TPC #Chi^{2}", kTH2F, {ptAxis, tpcCh2Axis}); + for (uint isp = 0; isp < nch; ++isp) { + fhITS_NCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "ITSNCls", "ITS clusters", tnames[isp], kTH2F, {ptAxis, itsNClsAxis}); + fhITS_Chi2NCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "ITSChi2NCls", "ITS #Chi^{2}", tnames[isp], kTH2F, {ptAxis, itsCh2Axis}); + fhTPC_FindableNCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCFindableNCls", "TPC findable clusters", tnames[isp], kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_FoundNCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCFoundNCls", "TPC found clusters", tnames[isp], kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_SharedNCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCSharedNCls", "TPC shared clusters", tnames[isp], kTH2F, {ptAxis, tpcNClsAxis}); + fhTPC_FractionSharedCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCFractionSharedCls", "TPC fraction shared clusters", tnames[isp], kTH2F, {ptAxis, tpcFractionAxis}); + fhTPC_CrossedRows_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCXrows", "TPC crossed rows", tnames[isp], kTH2F, {ptAxis, tpcNRowsAxis}); + fhTPC_CrossedRowsOverFindableCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "XRowsOverFindableCls", "TPC xrows over findable clusters", tnames[isp], kTH2F, {ptAxis, tpcXRowsOverFindClsAxis}); + fhTPC_Chi2NCls_vs_PtA[isp] = ADDHISTOGRAMID(TH2, dirname, "Reco", "After", "TPCChi2NCls", "TPC #Chi^{2}", tnames[isp], kTH2F, {ptAxis, tpcCh2Axis}); + /* efficiency histograms */ + fhPt_vs_EtaItsA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptIts", "ITS tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaTpcA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptTpc", "TPC tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaItsTpcA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptItsTpc", "ITS&TPC tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaItsTofA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptItsTof", "ITS&TOF tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaTpcTofA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptTpcTof", "TPC&TOF tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaItsTpcTofA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Reco", "ptItsTpcTof", "ITS&TPC&TOF tracks", tnames[isp], kTH2F, {etaAxis, ptAxis}); + } + } else { + for (uint isp = 0; isp < nch; ++isp) { + /* detector level and generator level histograms */ + fhPt_vs_EtaPrimA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Gen", "ptPrim", "ITS tracks (primaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaSecA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Gen", "ptSec", "ITS tracks (secondaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaMatA[isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", "Gen", "ptMat", "ITS tracks (from material)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + const std::vector detectedorigin = {"DetReco", "DetAssoc"}; + for (uint ix = 0; ix < detectedorigin.size(); ++ix) { + fhPt_vs_EtaPrimItsA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsPrim", "ITS tracks (primaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaPrimItsTpcA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcPrim", "ITS&TPC tracks (primaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaPrimItsTpcTofA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcTofPrim", "ITS&TPC&TOF tracks (primaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaSecItsA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsSec", "ITS tracks (secondaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaSecItsTpcA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcSec", "ITS&TPC tracks (secondaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaSecItsTpcTofA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcTofSec", "ITS&TPC&TOF tracks (secondaries)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaMatItsA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsMat", "ITS tracks (from material)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaMatItsTpcA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcMat", "ITS&TPC tracks (from material)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + fhPt_vs_EtaMatItsTpcTofA[ix][isp] = ADDHISTOGRAMID(TH2, dirname, "Efficiency", detectedorigin[ix].c_str(), "ptItsTpcTofMat", "ITS&TPC&TOF tracks (from material)", tnames[isp], kTH2F, {etaAxis, ptAxis}); + } + } + } + } + + template + void processTracks(float zvtx, TrackListObject const& passedtracks) + { + using namespace efficiencyandqatask; + + for (auto& track : passedtracks) { + fhPtB[kind]->Fill(track.pt()); + fhPt_vs_EtaB[kind]->Fill(track.eta(), track.pt()); + fhPt_vs_ZvtxB[kind]->Fill(zvtx, track.pt()); + if (!(track.trackacceptedid() < 0)) { + fhPtA[kind][track.trackacceptedid()]->Fill(track.pt()); + fhPt_vs_EtaA[kind][track.trackacceptedid()]->Fill(track.eta(), track.pt()); + fhPt_vs_ZvtxA[kind][track.trackacceptedid()]->Fill(zvtx, track.pt()); + } + if constexpr (kind == kReco) { + bool hasits = track.hasITS(); + bool hastpc = track.hasTPC(); + bool hastof = track.hasTOF(); + + fhITS_NCls_vs_PtB->Fill(track.pt(), track.itsNCls()); + fhITS_Chi2NCls_vs_PtB->Fill(track.pt(), track.itsChi2NCl()); + fhTPC_FindableNCls_vs_PtB->Fill(track.pt(), track.tpcNClsFindable()); + fhTPC_FoundNCls_vs_PtB->Fill(track.pt(), track.tpcNClsFound()); + fhTPC_SharedNCls_vs_PtB->Fill(track.pt(), track.tpcNClsShared()); + fhTPC_FractionSharedCls_vs_PtB->Fill(track.pt(), track.tpcFractionSharedCls()); + fhTPC_CrossedRows_vs_PtB->Fill(track.pt(), track.tpcNClsCrossedRows()); + fhTPC_CrossedRowsOverFindableCls_vs_PtB->Fill(track.pt(), track.tpcCrossedRowsOverFindableCls()); + fhTPC_Chi2NCls_vs_PtB->Fill(track.pt(), track.tpcChi2NCl()); + if (!(track.trackacceptedid() < 0)) { + fhITS_NCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.itsNCls()); + fhITS_Chi2NCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.itsChi2NCl()); + fhTPC_FindableNCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcNClsFindable()); + fhTPC_FoundNCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcNClsFound()); + fhTPC_SharedNCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcNClsShared()); + fhTPC_FractionSharedCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcFractionSharedCls()); + fhTPC_CrossedRows_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcNClsCrossedRows()); + fhTPC_CrossedRowsOverFindableCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcCrossedRowsOverFindableCls()); + fhTPC_Chi2NCls_vs_PtA[track.trackacceptedid()]->Fill(track.pt(), track.tpcChi2NCl()); + /* efficiency histograms */ + auto fillhisto = [&track](auto& h, bool cond) { + if (cond) { + h->Fill(track.eta(), track.pt()); + } + }; + fillhisto(fhPt_vs_EtaItsA[track.trackacceptedid()], hasits); + fillhisto(fhPt_vs_EtaTpcA[track.trackacceptedid()], hastpc); + fillhisto(fhPt_vs_EtaItsTpcA[track.trackacceptedid()], hasits && hastpc); + fillhisto(fhPt_vs_EtaItsTofA[track.trackacceptedid()], hasits && hastof); + fillhisto(fhPt_vs_EtaTpcTofA[track.trackacceptedid()], hastpc && hastof); + fillhisto(fhPt_vs_EtaItsTpcTofA[track.trackacceptedid()], hasits && hastpc && hastof); + /* the detector / generator combined level */ + if constexpr (framework::has_type_v) { + /* get the associated MC particle we are sure it does exist because the track was accepted */ + const auto& mcparticle = track.template mcParticle_as>(); + + /* TODO: what if the id of the generated is not the same as the id of the reconstructed */ + bool isprimary = mcparticle.isPhysicalPrimary(); + bool issecdecay = !isprimary && (mcparticle.getProcess() == 4); + bool isfrommaterial = !isprimary && !issecdecay; + auto fillhisto = [](auto& h, float pt, float eta, bool cond1, bool cond2) { + if (cond1 && cond2) { + h->Fill(eta, pt); + } + }; + std::vector t_pt = {track.pt(), mcparticle.pt()}; + std::vector t_eta = {track.eta(), mcparticle.eta()}; + for (uint ix = 0; ix < t_pt.size(); ++ix) { + fillhisto(fhPt_vs_EtaPrimItsA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits, isprimary); + fillhisto(fhPt_vs_EtaPrimItsTpcA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastpc, isprimary); + fillhisto(fhPt_vs_EtaPrimItsTpcTofA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastof, isprimary); + fillhisto(fhPt_vs_EtaSecItsA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits, issecdecay); + fillhisto(fhPt_vs_EtaSecItsTpcA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastpc, issecdecay); + fillhisto(fhPt_vs_EtaSecItsTpcTofA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastof, issecdecay); + fillhisto(fhPt_vs_EtaMatItsA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits, isfrommaterial); + fillhisto(fhPt_vs_EtaMatItsTpcA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastpc, isfrommaterial); + fillhisto(fhPt_vs_EtaMatItsTpcTofA[ix][track.trackacceptedid()], t_pt[ix], t_eta[ix], hasits && hastof, isfrommaterial); + } + } + } + } + if constexpr (kind == kGen) { + if (!(track.trackacceptedid() < 0)) { + /* pure generator level */ + if (track.isPhysicalPrimary()) { + fhPt_vs_EtaPrimA[track.trackacceptedid()]->Fill(track.eta(), track.pt()); + } else if (track.getProcess() == 4) { + fhPt_vs_EtaSecA[track.trackacceptedid()]->Fill(track.eta(), track.pt()); + } else { + fhPt_vs_EtaMatA[track.trackacceptedid()]->Fill(track.eta(), track.pt()); + } + } + } + } + } +}; + +struct EfficiencyCollectingEngine { + size_t nch = efficiencyandqatask::tnames.size(); + + std::vector fhN1_pt{nch, nullptr}; +}; + +struct DptDptEfficiencyAndQc { + /* the data memebers for this task */ + /* the centrality / multiplicity limits for collecting data in this task instance */ + uint ncmranges = 0; + float* fCentMultMin = nullptr; + float* fCentMultMax = nullptr; + + /* the data collecting engine instances */ + QADataCollectingEngine** dataCE; + + /* this is a nightmare but not other way found to overcome the histogram registry limit */ + HistogramRegistry registry_one{"registry_one", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_two{"registry_two", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_three{"registry_three", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_four{"registry_four", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_five{"registry_five", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_six{"registry_six", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_seven{"registry_seven", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_eight{"registry_eight", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_nine{"registry_nine", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registry_ten{"registry_ten", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::vector registrybank{®istry_one, ®istry_two, ®istry_three, ®istry_four, ®istry_five, + ®istry_six, ®istry_seven, ®istry_eight, ®istry_nine, ®istry_ten}; + + void init(o2::framework::InitContext& initContext) + { + using namespace efficiencyandqatask; + /* Self configuration: requires dptdptfilter task in the workflow */ + { + /* the binning */ + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxbins", zvtxbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmin", zvtxlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mZVtxmax", zvtxup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTbins", ptbins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmin", ptlow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mPTmax", ptup); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtabins", etabins); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamin", etalow); + getTaskOptionValue(initContext, "dpt-dpt-filter", "binning.mEtamax", etaup); + + /* configuring the involved species */ + o2::analysis::dptdptfilter::PIDSpeciesSelection pidselector; + std::vector cfgnames = {"pipidsel", "kapidsel", "prpidsel"}; + std::vector spids = {2, 3, 4}; + for (uint i = 0; i < cfgnames.size(); ++i) { + auto includeIt = [&pidselector, &initContext](int spid, auto name) { + bool mUseIt = false; + bool mExcludeIt = false; + if (getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mUseIt", name.c_str()).Data(), mUseIt) && + getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mExclude", name.c_str()).Data(), mExcludeIt)) { + if (mUseIt && !mExcludeIt) { + auto cfg = new o2::analysis::TrackSelectionPIDCfg(); + cfg->mUseIt = true; + cfg->mExclude = false; + pidselector.Add(spid, cfg); + } + } + }; + includeIt(spids[i], cfgnames[i]); + } + uint nspecies = pidselector.getNSpecies(); + if (nspecies == 0) { + /* unidentified analysis */ + poinames.push_back(pidselector.getHadFName()); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getHadFName()).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getHadFName()).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[0].c_str()); + } else { + for (uint8_t ix = 0; ix < nspecies; ++ix) { + poinames.push_back(std::string(pidselector.getSpeciesFName(ix))); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getSpeciesFName(ix)).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getSpeciesFName(ix)).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[ix].c_str()); + } + } + + /* create the data collecting engine instances according to the configured centrality/multiplicity ranges */ + std::string centspec; + if (getTaskOptionValue(initContext, "dpt-dpt-filter", "centralities", centspec)) { + LOGF(info, "Got the centralities specification: %s", centspec.c_str()); + auto tokens = TString(centspec.c_str()).Tokenize(","); + ncmranges = tokens->GetEntries(); + fCentMultMin = new float[ncmranges]; + fCentMultMax = new float[ncmranges]; + for (uint i = 0; i < ncmranges; ++i) { + float cmmin = 0.0f; + float cmmax = 0.0f; + sscanf(tokens->At(i)->GetName(), "%f-%f", &cmmin, &cmmax); + fCentMultMin[i] = cmmin; + fCentMultMax[i] = cmmax; + } + delete tokens; + } else { + LOGF(info, "No centralities specification. Setting it to: 0-100"); + ncmranges = 1; + fCentMultMin = new float[ncmranges]; + fCentMultMax = new float[ncmranges]; + fCentMultMin[0] = 0.0f; + fCentMultMax[0] = 100.0f; + } + dataCE = new QADataCollectingEngine*[ncmranges]; + std::string recogen; + if (!doprocessReconstructedNotStored && !doprocessDetectorLevelNotStored) { + LOGF(fatal, "Neither reco nor detector level not configured. Please, fix it!"); + } + if (ncmranges > registrybank.size()) { + LOGF(fatal, "There are more centrality ranges configured than registries in the bank. Please fix it!"); + } + /* in reverse order for proper order in results file */ + for (uint i = 0; i < ncmranges; ++i) { + auto initializeCEInstance = [&](auto dce, auto name) { + /* crete the output list for the passed centrality/multiplicity range */ + /* init the data collection instance */ + dce->template init(*registrybank[i], name.Data()); + if (doprocessGeneratorLevelNotStored) { + dce->template init(*registrybank[i], name.Data()); + } + }; + auto buildCEInstance = [&initializeCEInstance](float min, float max) { + QADataCollectingEngine* dce = new QADataCollectingEngine(); + initializeCEInstance(dce, TString::Format("EfficiencyAndQaData-%d-%d", int(min), int(max))); + return dce; + }; + /* in reverse order for proper order in results file */ + dataCE[ncmranges - i - 1] = buildCEInstance(fCentMultMin[ncmranges - i - 1], fCentMultMax[ncmranges - i - 1]); + } + for (uint i = 0; i < ncmranges; ++i) { + LOGF(info, " centrality/multipliicty range: %d, low limit: %d, up limit: %d", i, int(fCentMultMin[i]), int(fCentMultMax[i])); + } + } + } + + /// \brief Get the data collecting engine index corresponding to the passed collision + template + int getDCEindex(FilteredCollision collision) + { + int ixDCE = -1; + float cm = collision.centmult(); + for (uint i = 0; i < ncmranges; ++i) { + if (cm < fCentMultMax[i]) { + ixDCE = i; + break; + } + } + if (!(ixDCE < 0)) { + if (cm < fCentMultMin[ixDCE]) { + ixDCE = -1; + } + } + return ixDCE; + } + + template + void processTracks(FilterdCollision const& collision, PassedTracks const& tracks) + { + using namespace efficiencyandqatask; + + int ixDCE = getDCEindex(collision); + if (!(ixDCE < 0)) { + dataCE[ixDCE]->processTracks(collision.posZ(), tracks); + } + } + + Filter onlyacceptedcollisions = (aod::dptdptfilter::collisionaccepted == uint8_t(true)); + + void processReconstructedNotStored(soa::Filtered>::iterator const& collision, soa::Join& tracks) + { + using namespace efficiencyandqatask; + + processTracks(collision, tracks); + } + PROCESS_SWITCH(DptDptEfficiencyAndQc, processReconstructedNotStored, "Process reconstructed efficiency and QA for not stored derived data", false); + + void processDetectorLevelNotStored(soa::Filtered>::iterator const& collision, + soa::Join& tracks, + soa::Join const&) + { + using namespace efficiencyandqatask; + + processTracks(collision, tracks); + } + PROCESS_SWITCH(DptDptEfficiencyAndQc, processDetectorLevelNotStored, "Process MC detector level efficiency and QA for not stored derived data", true); + + void processGeneratorLevelNotStored(soa::Filtered>::iterator const& collision, + soa::Join& particles) + { + using namespace efficiencyandqatask; + + processTracks(collision, particles); + } + PROCESS_SWITCH(DptDptEfficiencyAndQc, processGeneratorLevelNotStored, "Process MC generator level efficiency and QA for not stored derived data", true); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + return workflow; +} \ No newline at end of file