diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index b6fc8b9eaa5..8c283cecc40 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -45,7 +45,7 @@ o2physics_add_dpl_workflow(dpt-dpt-per-run-extra-qc o2physics_add_dpl_workflow(corr-reso SOURCES corrReso.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::TwoPartCorrCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(neutron-proton-corr-zdc @@ -60,7 +60,7 @@ o2physics_add_dpl_workflow(di-hadron-cor o2physics_add_dpl_workflow(pid-di-hadron SOURCES pidDiHadron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::TwoPartCorrCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(longrange-correlation diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrReso.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrReso.cxx index 1f75e51f647..f3185668771 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrReso.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrReso.cxx @@ -13,7 +13,7 @@ /// \brief Ultra long range correlation using forward FIT detectors and TPC, with focus on resonances /// \author Thor Jensen (thor.kjaersgaard.jensen@cern.ch) -#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/TwoParticleCorrelations/Core/DihadronContainer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -87,121 +88,131 @@ struct CorrReso { o2::aod::ITSResponse itsResponse; Service ccdb{}; - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, true, "Use additional event cut on mult correlations") - O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgQaCheck, bool, true, "Enable QA histograms for event selection") - O2_DEFINE_CONFIGURABLE(cfgStrictTrackCounter, bool, false, "Strict track counter for multiplicity correlation cut, counts only tracks that pass all cuts and are used in the correlation") - O2_DEFINE_CONFIGURABLE(cfgMinMultForCorrelations, int, 0, "minimum multiplicity for correlations") - O2_DEFINE_CONFIGURABLE(cfgMaxMultForCorrelations, int, 20, "maximum multiplicity for correlations") - Configurable> cfgRunRemoveList{"cfgRunRemoveList", std::vector{-1}, "excluded run numbers"}; - O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking (CBT)', 'CBT_hadronPID' ") - - struct : ConfigurableGroup{ - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") - O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") - O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z")} cfgTrackCuts; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgQABasic, bool, true, "Enable QA histograms for event and track selection") + O2_DEFINE_CONFIGURABLE(cfgStrictTrackCounter, bool, false, "Strict track counter for multiplicity correlation cut, counts only tracks that pass all cuts and are used in the correlation") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, int, 10, "Sample size for mixed event") + O2_DEFINE_CONFIGURABLE(cfgAnalyzeTPCFT0A, bool, true, "Switch for doing TPC-FT0A correlations") + O2_DEFINE_CONFIGURABLE(cfgAnalyzeTPCFT0C, bool, true, "Switch for doing TPC-FT0C correlations") + O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") + Configurable> cfgRunRemoveList{"cfgRunRemoveList", std::vector{-1}, "excluded run numbers"}; + Configurable cfgGainEqPath{"cfgGainEqPath", "Analysis/EventPlane/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgCorrLevel{"cfgCorrLevel", 0, "calibration step: 0 = no corr, 1 = gain corr"}; + } cfgGeneral; struct : ConfigurableGroup{ - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy")} cfgEventSelection; + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyNch, std::string, "", "CCDB path to multiplicity dependent efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiencyNch, bool, false, "Use local multiplicity dependent efficiency object")} cfgEffWeights; - Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt.front().data(), 14, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kIsGoodITSLayer0123", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgGlobalPtMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgGlobalPtMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgGlobalEta, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgGlobalChi2prTPCcls, float, 2.5f, "Maximum chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgGlobalDCAz, float, 2.0f, "Maximum DCA to vertex z") + Configurable> cfgTrackCutsDCAxy{"cfgTrackCutsDCAxy", std::vector{"[0]*(0.0026+0.005/(x^1.01))", "[0]*(0.0026+0.005/(x^1.01))"}, "Functional form of pt-dependent DCAxy cut"}; + Configurable> cfgTrackCutsDCAz{"cfgTrackCutsDCAz", std::vector{"", ""}, "Functional form of pt-dependent DCAz cut"}; + Configurable> cfgTrackCuts{"cfgTrackCuts", {LongArrayFloat.front().data(), 10, 2, {"PtMin", "PtMax", "EtaCut", "Chi2PrTpcCls", "TpcCluster", "TpcCrossedRows", "ItsCluster", "DCAz", "DCAzNsigma", "DCAxyNsigma"}, {"General", "SelNch"}}, "Labeled array for track selections"}; + } cfgTrkSel; - O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") - O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") - O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgEfficiencyNch, std::string, "", "CCDB path to multiplicity dependent efficiency object") - O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") - O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") - O2_DEFINE_CONFIGURABLE(cfgLocalEfficiencyNch, bool, false, "Use local multiplicity dependent efficiency object"); - O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgGlobalCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, true, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgMinMultForCorrelations, int, 0, "minimum multiplicity for correlations") + O2_DEFINE_CONFIGURABLE(cfgMaxMultForCorrelations, int, 20, "maximum multiplicity for correlations") + O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FV0A") + O2_DEFINE_CONFIGURABLE(cfgMinCentForCorrelations, int, 0, "minimum centrality for correlations") + O2_DEFINE_CONFIGURABLE(cfgMaxCentForCorrelations, int, 20, "maximum centrality for correlations") + O2_DEFINE_CONFIGURABLE(cfgUseCol2ForMixedEvSel, bool, true, "Use Mult/Cent cut on collision 2 during mixed event") + O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking (CBT)', 'CBT_hadronPID' ") + Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt.front().data(), 14, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kIsGoodITSLayer0123", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; + } cfgEvSel; struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); - O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgMultT0CCutEnabled, bool, false, "Enable Global multiplicity vs T0C centrality cut") Configurable> cfgMultT0CCutPars{"cfgMultT0CCutPars", std::vector{143.04, -4.58368, 0.0766055, -0.000727796, 2.86153e-06, 23.3108, -0.36304, 0.00437706, -4.717e-05, 1.98332e-07}, "Global multiplicity vs T0C centrality cut parameter values"}; O2_DEFINE_CONFIGURABLE(cfgMultPVT0CCutEnabled, bool, false, "Enable PV multiplicity vs T0C centrality cut") Configurable> cfgMultPVT0CCutPars{"cfgMultPVT0CCutPars", std::vector{195.357, -6.15194, 0.101313, -0.000955828, 3.74793e-06, 30.0326, -0.43322, 0.00476265, -5.11206e-05, 2.13613e-07}, "PV multiplicity vs T0C centrality cut parameter values"}; - O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); - O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCutEnabled, bool, false, "Enable global multiplicity vs PV multiplicity cut") Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.140809, 0.734344, 2.77495, 0.0165935}, "PV multiplicity vs T0C centrality cut parameter values"}; - O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); - O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; std::vector multT0CCutPars; std::vector multPVT0CCutPars; std::vector multGlobalPVCutPars; std::vector multMultV0ACutPars; - TF1* fMultPVT0CCutLow = nullptr; - TF1* fMultPVT0CCutHigh = nullptr; - TF1* fMultT0CCutLow = nullptr; - TF1* fMultT0CCutHigh = nullptr; - TF1* fMultGlobalPVCutLow = nullptr; - TF1* fMultGlobalPVCutHigh = nullptr; - TF1* fMultMultV0ACutLow = nullptr; - TF1* fMultMultV0ACutHigh = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; + std::unique_ptr fMultPVT0CCutLow = nullptr; + std::unique_ptr fMultPVT0CCutHigh = nullptr; + std::unique_ptr fMultT0CCutLow = nullptr; + std::unique_ptr fMultT0CCutHigh = nullptr; + std::unique_ptr fMultGlobalPVCutLow = nullptr; + std::unique_ptr fMultGlobalPVCutHigh = nullptr; + std::unique_ptr fMultMultV0ACutLow = nullptr; + std::unique_ptr fMultMultV0ACutHigh = nullptr; + std::unique_ptr fT0AV0AMean = nullptr; + std::unique_ptr fT0AV0ASigma = nullptr; + std::unique_ptr fPtDepDCAxy = nullptr; + std::unique_ptr fPtDepDCAxyForNch = nullptr; + std::unique_ptr fPtDepDCAz = nullptr; + std::unique_ptr fPtDepDCAzForNch = nullptr; O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") } cfgFuncParas; struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") - O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") - O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") - O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") - O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.4f, "Minimum pt to use TOF N-sigma") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, false, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") Configurable> nSigmas{"nSigmas", {LongArrayFloat.front().data(), 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; - Configurable> cfgResoCuts{"cfgResoCuts", {LongArrayFloat.front().data(), 13, 3, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "Rapidity", "ArmPodMinVal", "DCABetDaug"}, {"K0", "Lambda", "Phi"}}, "Labeled array (float) for various cuts on resonances"}; - Configurable> cfgResoSwitches{"cfgResoSwitches", {LongArrayInt.front().data(), 6, 3, {"UseCosPA", "NMassBins", "UseDCABetDaug", "UseProperLifetime", "UseV0Radius", "UseArmPodCut"}, {"K0", "Lambda", "Phi"}}, "Labeled array (int) for various cuts on resonances"}; + O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") + O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "4 = kshort, 5 = lambda, 0 for no PID") + Configurable> cfgResoCuts{"cfgResoCuts", {LongArrayFloat.front().data(), 15, 2, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "RapidityMin", "RapidityMax", "ArmPodMinVal", "DCABetDaug", "CompMassRej"}, {"K0", "Lambda"}}, "Labeled array (float) for various cuts on resonances"}; + Configurable> cfgResoSwitches{"cfgResoSwitches", {LongArrayInt.front().data(), 7, 2, {"UseCosPA", "NMassBins", "UseDCABetDaug", "UseProperLifetime", "UseV0Radius", "UseArmPodCut", "UseCompMassRej"}, {"K0", "Lambda"}}, "Labeled array (int) for various cuts on resonances"}; } cfgPIDConfigs; - Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; - Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; - Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; - Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; - SliceCache cache; + // Axes for general QA ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; - ConfigurableAxis axisMult{"axisMult", {10, 0, 100}, "multiplicity axis for histograms"}; + ConfigurableAxis axisMult{"axisMult", {10, 0, 100}, "multiplicity axis for QA histograms"}; + ConfigurableAxis axisCent{"axisCent", {100, 0, 100}, "centrality axis for QA histograms"}; ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {72, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis axisPtFiner{"axisPtFiner", {98, 0.2, 10.0}, "pt axis for histograms"}; + + // Axes for Correlations + ConfigurableAxis axisMultForCorr{"axisMultForCorr", {VARIABLE_WIDTH, 0, 5, 10, 20, 50, 100, 150, 200, 300, 500}, "multiplicity axis for correlation histograms"}; + ConfigurableAxis axisCentForCorr{"axisCentForCorr", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "centrality axis for correlation histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; - ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity / centrality axis for mixed event histograms"}; - ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; - - ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; - ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; - ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; - ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; - ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt axis for efficiency histograms"}; - ConfigurableAxis axisAmplitudeFt0a{"axisAmplitudeFt0a", {5000, 0, 1000}, "FT0A amplitude"}; + // Axes for long-range correlations QA + ConfigurableAxis axisAmplitudeFt0{"axisAmplitudeFt0", {5000, 0, 1000}, "FT0A amplitude"}; ConfigurableAxis axisChannelFt0aAxis{"axisChannelFt0aAxis", {96, 0.0, 96.0}, "FT0A channel"}; + ConfigurableAxis axisChannelFt0cAxis{"axisChannelFt0cAxis", {96, 0.0, 96.0}, "FT0C channel"}; - Configurable cfgGainEqPath{"cfgGainEqPath", "Analysis/EventPlane/GainEq", "CCDB path for gain equalization constants"}; - Configurable cfgCorrLevel{"cfgCorrLevel", 0, "calibration step: 0 = no corr, 1 = gain corr"}; - ConfigurableAxis cfgaxisFITamp{"cfgaxisFITamp", {1000, 0, 5000}, ""}; - AxisSpec axisFit{cfgaxisFITamp, "fit amplitude"}; - AxisSpec axisChID = {220, 0, 220}; - - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut); - Filter trackFilter = (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaCut) && (cfgTrackCuts.cfgPtCutMin < aod::track::pt) && (cfgTrackCuts.cfgPtCutMax > aod::track::pt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)); + // Axes for PID QA + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgEvSel.cfgGlobalCutVertex); + Filter trackFilter = (nabs(aod::track::eta) < cfgTrkSel.cfgGlobalEta) && (aod::track::pt > cfgTrkSel.cfgGlobalPtMin) && (aod::track::pt < cfgTrkSel.cfgGlobalPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (nabs(aod::track::dcaZ) < cfgTrkSel.cfgGlobalDCAz) && (aod::track::tpcChi2NCl < cfgTrkSel.cfgGlobalChi2prTPCcls); using FilteredCollisions = soa::Filtered>; using FilteredTracks = soa::Filtered>; @@ -220,21 +231,22 @@ struct CorrReso { bool correctionsLoaded = false; // Define the outputs - OutputObj sameTpcFt0a{"sameEvent_TPC_FT0A"}; - OutputObj mixedTpcFt0a{"mixedEvent_TPC_FT0A"}; - OutputObj sameTpcFt0c{"sameEvent_TPC_FT0C"}; - OutputObj mixedTpcFt0c{"mixedEvent_TPC_FT0C"}; + OutputObj sameTpcFt0a{"sameEvent_TPC_FT0A"}; + OutputObj mixedTpcFt0a{"mixedEvent_TPC_FT0A"}; + OutputObj sameTpcFt0c{"sameEvent_TPC_FT0C"}; + OutputObj mixedTpcFt0c{"mixedEvent_TPC_FT0C"}; - HistogramRegistry registry{"registry"}; + HistogramRegistry histos{"histos"}; // For Labelled array value containers - std::array, 13> resoCutVals{}; - std::array, 6> resoSwitchVals{}; + std::array, 10> trackCuts{}; std::array, 14> eventCuts{}; std::array, 6> nSigmaVals{}; + std::array, 15> resoCutVals{}; + std::array, 7> resoSwitchVals{}; // define global variables - TRandom3* gRandom = new TRandom3(); + TRandom3 fRandom{0}; enum EventType { SameEvent = 1, @@ -242,101 +254,142 @@ struct CorrReso { }; enum FITIndex { - kFT0A = 0, - kFT0C = 1 + IndexFT0A = 0, + IndexFT0C = 1 }; enum PIDIndex { - kCharged = 0, - kPions, - kKaons, - kProtons, - kK0, - kLambda, - kPhi + UseCharged = 0, + UsePions, + UseKaons, + UseProtons, + UseK0, + UseLambda, }; enum PiKpArrayIndex { - iPionUp = 0, - iKaonUp, - iProtonUp, - iPionLow, - iKaonLow, - iProtonLow - }; - enum ResoArrayIndex { - iK0 = 0, - iLambda = 1, - iPhi = 2, - NResoParticles = 3 - }; - enum ResoParticleCuts { - kCosPA = 0, - kMassMin, - kMassMax, - kPosTrackPt, - kNegTrackPt, - kDCAPosToPVMin, - kDCANegToPVMin, - kLifeTime, - kRadiusMin, - kRadiusMax, - kRapidity, - kArmPodMinVal, - kDCABetDaug, - kNParticleCuts - }; - enum ResoParticleSwitches { - kUseCosPA = 0, - kMassBins, - kUseDCABetDaug, - kUseProperLifetime, - kUseV0Radius, - kUseArmPodCut, - kNParticleSwitches + IndexPionUp = 0, + IndexKaonUp, + IndexProtonUp, + IndexPionLow, + IndexKaonLow, + IndexProtonLow }; enum DetectorType { - kTPC = 0, - kTOF, - kITS + UseTPC = 0, + UseTOF, + UseITS }; enum EventCutTypes { - kFilteredEvents = 0, - kAfterSel8, - kUseNoTimeFrameBorder, - kUseNoITSROFrameBorder, - kUseNoSameBunchPileup, - kUseGoodZvtxFT0vsPV, - kUseNoCollInTimeRangeStandard, - kUseGoodITSLayersAll, - kUseGoodITSLayer0123, - kUseNoCollInRofStandard, - kUseNoHighMultCollInPrevRof, - kUseOccupancy, - kUseMultCorrCut, - kUseT0AV0ACut, - kNEventCuts + FilteredEvents = 0, + AfterSel8, + UseNoTimeFrameBorder, + UseNoITSROFrameBorder, + UseNoSameBunchPileup, + UseGoodZvtxFT0vsPV, + UseNoCollInTimeRangeStandard, + UseGoodITSLayersAll, + UseGoodITSLayer0123, + UseNoCollInRofStandard, + UseNoHighMultCollInPrevRof, + UseOccupancy, + UseMultCorrCut, + UseT0AV0ACut, + HaveFT0Cut, + NumEventCuts }; enum EventCutType { - kEvCut1 = 0, - kNEvCutTypes = 1 + EvCut1 = 0, + NumEvCutTypes = 1 + }; + + enum TrackCuts { + TrkCutPtMin = 0, + TrkCutPtMax, + TrkCutEtaCut, + TrkCutChi2PrTpcCls, + TrkCutTpcCluster, + TrkCutTpcCrossedRows, + TrkCutItsCluster, + TrkCutDCAz, + TrkCutDCAzNsigma, + TrkCutDCAxyNsigma + }; + + enum TrackCutGroup { + UseGenTrkCuts = 0, + UseNchSelCuts, + NumTrackCutTypes + }; + enum ResoArrayIndex { + IndexK0 = 0, + IndexLambda = 1, + IndexPhi = 2, + NumResoParticles = 3 + }; + enum ResoParticleCuts { + CutCosPA = 0, + CutMassMin, + CutMassMax, + CutPosTrackPt, + CutNegTrackPt, + CutDCAPosToPVMin, + CutDCANegToPVMin, + CutLifeTime, + CutRadiusMin, + CutRadiusMax, + CutRapidityMin, + CutRapidityMax, + CutArmPodMinVal, + CutDCABetDaug, + CutCompMassRej, + NumParticleCuts + }; + enum ResoParticleSwitches { + UseCosPA = 0, + UseMassBins, + UseDCABetDaug, + UseProperLifetime, + UseV0Radius, + UseArmPodCut, + UseCompMassRej, + NumParticleSwitches + }; + + enum ResoSelectionFlags { + FillCandidate = 0, + FillDaughterPt, + FillMassCut, + FillRapidityCut, + FillDCAtoPV, + FillDCAxDaughters, + FillV0Radius, + FillCosPA, + FillProperLifetime, + FillArmPodCut, + FillCompetingMass, + FillDaughterTrackSelected, }; enum CentEstimators { - kCentFT0C = 0, - kCentFT0CVariant1, - kCentFT0M, - kCentFV0A, + UseCentFT0C = 0, + UseCentFT0CVariant1, + UseCentFT0M, + UseCentFV0A, // Count the total number of enum - kCount_CentEstimators + NumCentEstimators }; RCTFlagsChecker rctChecker{"CBT"}; void init(InitContext&) { + // ---------------------------------------------------------------------------------------------------------------------- + // The way the code is initialized, TPC-FT0 correlations are done together + // ---------------------------------------------------------------------------------------------------------------------- + ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); @@ -344,249 +397,286 @@ struct CorrReso { LOGF(info, "Starting init"); - if (cfgPIDConfigs.cfgPIDParticle < kK0) { + readMatrix(cfgTrkSel.cfgTrackCuts->getData(), trackCuts); + readMatrix(cfgEvSel.cfgUseEventCuts->getData(), eventCuts); + readMatrix(cfgPIDConfigs.nSigmas->getData(), nSigmaVals); + readMatrix(cfgPIDConfigs.cfgResoCuts->getData(), resoCutVals); + readMatrix(cfgPIDConfigs.cfgResoSwitches->getData(), resoSwitchVals); + + if (cfgPIDConfigs.cfgPIDParticle < UseK0) { LOGF(fatal, "The input number does not correspond to any particle"); return; } - readMatrix(cfgPIDConfigs.cfgResoCuts->getData(), resoCutVals); - readMatrix(cfgPIDConfigs.cfgResoSwitches->getData(), resoSwitchVals); - readMatrix(cfgUseEventCuts->getData(), eventCuts); - readMatrix(cfgPIDConfigs.nSigmas->getData(), nSigmaVals); - // Creating mass axis depending on particle - 4 = kshort, 5 = lambda, 6 = phi AxisSpec axisInvMass = {10, 0, 1, "mass"}; - if (cfgPIDConfigs.cfgPIDParticle == kK0) { - const auto bins = resoSwitchVals[kMassBins][iK0]; - const auto min = resoCutVals[kMassMin][iK0]; - const auto max = resoCutVals[kMassMax][iK0]; + if (cfgPIDConfigs.cfgPIDParticle == UseK0) { + const auto bins = resoSwitchVals[UseMassBins][IndexK0]; + const auto min = resoCutVals[CutMassMin][IndexK0]; + const auto max = resoCutVals[CutMassMax][IndexK0]; axisInvMass = {bins, min, max, "M_{#pi^{+}#pi^{-}} (GeV/c^{2})"}; } - if (cfgPIDConfigs.cfgPIDParticle == kLambda) { - const auto bins = resoSwitchVals[kMassBins][iLambda]; - const auto min = resoCutVals[kMassMin][iLambda]; - const auto max = resoCutVals[kMassMax][iLambda]; + if (cfgPIDConfigs.cfgPIDParticle == UseLambda) { + const auto bins = resoSwitchVals[UseMassBins][IndexLambda]; + const auto min = resoCutVals[CutMassMin][IndexLambda]; + const auto max = resoCutVals[CutMassMax][IndexLambda]; axisInvMass = {bins, min, max, "M_{p#pi} (GeV/c^{2})"}; } - if (cfgPIDConfigs.cfgPIDParticle == kPhi) { - const auto bins = resoSwitchVals[kMassBins][iPhi]; - const auto min = resoCutVals[kMassMin][iPhi]; - const auto max = resoCutVals[kMassMax][iPhi]; - - axisInvMass = {bins, min, max, "M_{K^{+}K^{-}} (GeV/c^{2})"}; - } - - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c) { - if (cfgPIDConfigs.cfgPIDParticle == kK0) { // For K0 - registry.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - registry.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - registry.add("hK0Phi", "", {HistType::kTH1D, {axisPhi}}); - registry.add("hK0Eta", "", {HistType::kTH1D, {axisEta}}); - - registry.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{11, 0, 11}}}); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(1, "K0 candidates"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(3, "Mass cut"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(4, "Rapidity cut"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(5, "DCA to PV"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(6, "DCA between daughters"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(7, "V0radius"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(8, "CosPA"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(10, "ArmenterosPod"); - registry.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(11, "Daughter track selection"); - } - if (cfgPIDConfigs.cfgPIDParticle == kLambda) { // For Lambda - registry.add("PrPlusTPC_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PiMinusTPC_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PrPlusTOF_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - registry.add("PiMinusTOF_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - - registry.add("PrMinusTPC_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PiPlusTPC_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); - registry.add("PrMinusTOF_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - registry.add("PiPlusTOF_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); - - registry.add("hLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); - registry.add("hLambdaEta", "", {HistType::kTH1D, {axisEta}}); - - registry.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(1, "Lambda candidates"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(3, "Mass cut"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(4, "Rapidity cut"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(5, "DCA to PV"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(6, "DCA between daughters"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(7, "V0radius"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(8, "CosPA"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); - registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); - } - } - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c) { - registry.add("hEventCountRct", "Number of Event;; Count", {HistType::kTH1D, {{2, 0, 2}}}); - registry.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(1, "rct fail"); - registry.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(2, "rct pass"); - registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{14, -0.5, 13.5}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered events"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayer0123 + 1, "kIsGoodITSLayer0123"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "MultCorrelation Cut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); - } - - if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c) && cfgQaCheck) { - registry.add("hPassedEventSelection", "Number of Event;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered events"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseGoodITSLayer0123 + 1, "kIsGoodITSLayer0123"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); + + // Set the sample axis + auto maxSample = static_cast(cfgGeneral.cfgSampleSize); + AxisSpec axisSample{cfgGeneral.cfgSampleSize, 0, maxSample, "Sample"}; + + // Choose if it is Nch selection or Centrality selection + AxisSpec axisEventClass = {axisMultForCorr, "N_{ch}"}; + + if (!cfgEvSel.cfgSelCollByNch) { + axisEventClass = {axisCentForCorr, "Centrality"}; + } + + if (cfgPIDConfigs.cfgPIDParticle == UseK0) { // For K0 + histos.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + histos.add("hK0Phi", "", {HistType::kTH1D, {axisPhi}}); + histos.add("hK0Rap", "", {HistType::kTH1D, {axisEta}}); + histos.add("hK0Eta", "", {HistType::kTH1D, {axisEta}}); + + histos.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate + 1, "K0 candidates"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt + 1, "Daughter pt"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillMassCut + 1, "Mass cut"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillRapidityCut + 1, "Rapidity cut"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDCAtoPV + 1, "DCA to PV"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDCAxDaughters + 1, "DCA between daughters"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillV0Radius + 1, "V0radius"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCosPA + 1, "CosPA"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillProperLifetime + 1, "Proper lifetime"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillArmPodCut + 1, "ArmenterosPod"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCompetingMass + 1, "CompetingMassRejection"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected + 1, "Daughter track selection"); + } + + if (cfgPIDConfigs.cfgPIDParticle == UseLambda) { // For Lambda + histos.add("PrPlusTPC_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PrPlusTOF_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_La", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + + histos.add("PrMinusTPC_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PiPlusTPC_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTPC}}}); + histos.add("PrMinusTOF_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + histos.add("PiPlusTOF_Al", "", {HistType::kTH2D, {{axisPtFiner, axisNsigmaTOF}}}); + + histos.add("hLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); + histos.add("hLambdaRap", "", {HistType::kTH1D, {axisEta}}); + histos.add("hLambdaEta", "", {HistType::kTH1D, {axisEta}}); + + histos.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate + 1, "Lambda candidates"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt + 1, "Daughter pt"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillMassCut + 1, "Mass cut"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillRapidityCut + 1, "Rapidity cut"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAtoPV + 1, "DCA to PV"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAxDaughters + 1, "DCA between daughters"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillV0Radius + 1, "V0radius"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCosPA + 1, "CosPA"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillProperLifetime + 1, "Proper lifetime"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillArmPodCut + 1, "ArmenterosPod"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCompetingMass + 1, "CompetingMassRejection"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected + 1, "Daughter track selection"); + } + + histos.add("hEventCountRct", "Number of Event;; Count", {HistType::kTH1D, {{2, 0, 2}}}); + histos.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(1, "rct fail"); + histos.get(HIST("hEventCountRct"))->GetXaxis()->SetBinLabel(2, "rct pass"); + histos.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(FilteredEvents + 1, "Filtered events"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(AfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodITSLayer0123 + 1, "kIsGoodITSLayer0123"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseMultCorrCut + 1, "MultCorrelation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseT0AV0ACut + 1, "T0AV0A cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(HaveFT0Cut + 1, "Event has FT0 cut"); + + if (cfgGeneral.cfgQABasic) { + histos.add("hPassedEventSelection", "Number of Event;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(FilteredEvents + 1, "Filtered events"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(AfterSel8 + 1, "After sel8"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseGoodITSLayer0123 + 1, "kIsGoodITSLayer0123"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hPassedEventSelection"))->GetXaxis()->SetBinLabel(UseOccupancy + 1, "Occupancy Cut"); } // Multiplicity correlation cuts - if (eventCuts[kUseMultCorrCut][kEvCut1] != 0) { + if (eventCuts[UseMultCorrCut][EvCut1] != 0) { cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; cfgFuncParas.multMultV0ACutPars = cfgFuncParas.cfgMultMultV0ACutPars; - cfgFuncParas.fMultPVT0CCutLow = new TF1("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + + cfgFuncParas.fMultPVT0CCutLow = std::make_unique("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); cfgFuncParas.fMultPVT0CCutLow->SetParameters(cfgFuncParas.multPVT0CCutPars.data()); - cfgFuncParas.fMultPVT0CCutHigh = new TF1("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutHigh = std::make_unique("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); cfgFuncParas.fMultPVT0CCutHigh->SetParameters(cfgFuncParas.multPVT0CCutPars.data()); - cfgFuncParas.fMultT0CCutLow = new TF1("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutLow = std::make_unique("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); cfgFuncParas.fMultT0CCutLow->SetParameters(cfgFuncParas.multT0CCutPars.data()); - cfgFuncParas.fMultT0CCutHigh = new TF1("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutHigh = std::make_unique("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); cfgFuncParas.fMultT0CCutHigh->SetParameters(cfgFuncParas.multT0CCutPars.data()); - cfgFuncParas.fMultGlobalPVCutLow = new TF1("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutLow = std::make_unique("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); cfgFuncParas.fMultGlobalPVCutLow->SetParameters(cfgFuncParas.multGlobalPVCutPars.data()); - cfgFuncParas.fMultGlobalPVCutHigh = new TF1("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutHigh = std::make_unique("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(cfgFuncParas.multGlobalPVCutPars.data()); - cfgFuncParas.fMultMultV0ACutLow = new TF1("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutLow = std::make_unique("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); cfgFuncParas.fMultMultV0ACutLow->SetParameters(cfgFuncParas.multMultV0ACutPars.data()); - cfgFuncParas.fMultMultV0ACutHigh = new TF1("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutHigh = std::make_unique("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); cfgFuncParas.fMultMultV0ACutHigh->SetParameters(cfgFuncParas.multMultV0ACutPars.data()); } - if (eventCuts[kUseT0AV0ACut][kEvCut1] != 0) { - cfgFuncParas.fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + if (eventCuts[UseT0AV0ACut][EvCut1] != 0) { + cfgFuncParas.fT0AV0AMean = std::make_unique("fT0AV0AMean", "[0]+[1]*x", 0, 200000); cfgFuncParas.fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); - cfgFuncParas.fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + cfgFuncParas.fT0AV0ASigma = std::make_unique("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c) { - registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); - registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); - registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); - registry.add("pTFiner", "pTFiner", {HistType::kTH1D, {axisPtFiner}}); - registry.add("pTFinerCorrected", "pTFinerCorrected", {HistType::kTH1D, {axisPtFiner}}); - registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMult}}); - registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); - - registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); - registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); - } // end of single particle distribution histograms + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].empty()) { + cfgFuncParas.fPtDepDCAxy = std::make_unique("ptDepDCAxy", cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAxy->SetParameter(0, trackCuts[TrkCutDCAxyNsigma][UseGenTrkCuts]); + LOGF(info, "DCAxy pt-dependence function: %0.1f * %s", trackCuts[TrkCutDCAxyNsigma][UseGenTrkCuts], cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].c_str()); + } + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].empty()) { + cfgFuncParas.fPtDepDCAxyForNch = std::make_unique("ptDepDCAxyForNch", cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAxyForNch->SetParameter(0, trackCuts[TrkCutDCAxyNsigma][UseNchSelCuts]); + LOGF(info, "DCAxy pt-dependence function for Nch: %0.1f * %s", trackCuts[TrkCutDCAxyNsigma][UseNchSelCuts], cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].c_str()); + } - if (cfgQaCheck) { - registry.add("Nch_corrected", "N_{ch} corrected", {HistType::kTH1D, {axisMult}}); + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].empty()) { + cfgFuncParas.fPtDepDCAz = std::make_unique("ptDepDCAz", cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAz->SetParameter(0, trackCuts[TrkCutDCAzNsigma][UseGenTrkCuts]); + LOGF(info, "DCAz pt-dependence function: %0.1f * %s", trackCuts[TrkCutDCAzNsigma][UseGenTrkCuts], cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].c_str()); } + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].empty()) { + cfgFuncParas.fPtDepDCAzForNch = std::make_unique("ptDepDCAzForNch", cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAzForNch->SetParameter(0, trackCuts[TrkCutDCAzNsigma][UseNchSelCuts]); + LOGF(info, "DCAz pt-dependence function for Nch: %0.1f * %s", trackCuts[TrkCutDCAzNsigma][UseNchSelCuts], cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].c_str()); + } + + if (doprocessSameTpcFt0) { + histos.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + histos.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMult}}); + histos.add("Centrality", "Centrality", {HistType::kTH1D, {axisCent}}); - if (doprocessSameTpcFt0a) { - registry.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution - registry.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); - registry.add("Assoc_amp_same_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Assoc_amp_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger, axisInvMass}}}); + if (cfgGeneral.cfgStrictTrackCounter) { + histos.add("Nch_corrected", "N_{ch} corrected", {HistType::kTH1D, {axisMult}}); + } + if (!cfgEvSel.cfgSelCollByNch) { + histos.add("CentralityWeighted", "Centrality (weighted)", {HistType::kTH1D, {axisCent}}); + } + + if (cfgGeneral.cfgQABasic) { + histos.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); + histos.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + histos.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); + histos.add("pTFiner", "pTFiner", {HistType::kTH1D, {axisPtFiner}}); + histos.add("pTFinerCorrected", "pTFinerCorrected", {HistType::kTH1D, {axisPtFiner}}); + } + + if (cfgGeneral.cfgAnalyzeTPCFT0A) { + histos.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution + histos.add("Assoc_amp_same_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0}}); + histos.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEventClass, axisPtTrigger, axisInvMass}}}); + } + if (cfgGeneral.cfgAnalyzeTPCFT0C) { + histos.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution + histos.add("Assoc_amp_same_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0cAxis, axisAmplitudeFt0}}); + histos.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEventClass, axisPtTrigger, axisInvMass}}}); + } } - if (doprocessSameTpcFt0c) { - registry.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution - registry.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); - registry.add("Assoc_amp_same_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Assoc_amp_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger, axisInvMass}}}); + + if (doprocessMixedTpcFt0) { + if (cfgGeneral.cfgAnalyzeTPCFT0A) { + histos.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); + histos.add("Assoc_amp_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0}}); + } + if (cfgGeneral.cfgAnalyzeTPCFT0C) { + histos.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); + histos.add("Assoc_amp_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0cAxis, axisAmplitudeFt0}}); + } } - registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event LOGF(info, "Initializing correlation container"); - // Initialize Nch-related histograms and containers - - std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, + // Initialize containers + std::vector corrAxisTpcFt0a = {{axisSample}, {axisVertex, "z-vtx (cm)"}, + {axisEventClass}, {axisPtTrigger, "p_{T} (GeV/c)"}, {axisInvMass}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; - std::vector corrAxisTpcFt0c = {{axisSample, "Sample"}, + std::vector corrAxisTpcFt0c = {{axisSample}, {axisVertex, "z-vtx (cm)"}, + {axisEventClass}, {axisPtTrigger, "p_{T} (GeV/c)"}, {axisInvMass}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; - std::vector effAxis = { - {axisEtaEfficiency, "#eta"}, - {axisPtEfficiency, "p_{T} (GeV/c)"}, - {axisVertexEfficiency, "z-vtx (cm)"}, - }; - std::vector userAxis; - - if (doprocessSameTpcFt0a) { - sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); - mixedTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + if (cfgGeneral.cfgAnalyzeTPCFT0A) { + sameTpcFt0a.setObject(new DihadronContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a)); + mixedTpcFt0a.setObject(new DihadronContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a)); } - if (doprocessSameTpcFt0c) { - sameTpcFt0c.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); - mixedTpcFt0c.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + if (cfgGeneral.cfgAnalyzeTPCFT0C) { + sameTpcFt0c.setObject(new DihadronContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c)); + mixedTpcFt0c.setObject(new DihadronContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c)); } - if (!cfgEvSelRCTflags.value.empty()) { - rctChecker.init(cfgEvSelRCTflags.value); // override initialzation + if (!cfgEvSel.cfgEvSelRCTflags.value.empty()) { + rctChecker.init(cfgEvSel.cfgEvSelRCTflags.value); // override initialzation } LOGF(info, "End of init"); } template - float getCentrality(TCollision const& collision) + double getCentrality(TCollision const& collision) { - float cent = 0.0; - switch (cfgCentEstimator) { - case kCentFT0C: + double cent = 0.0; + switch (cfgEvSel.cfgCentEstimator) { + case UseCentFT0C: cent = collision.centFT0C(); break; - case kCentFT0CVariant1: + case UseCentFT0CVariant1: cent = collision.centFT0CVariant1(); break; - case kCentFT0M: + case UseCentFT0M: cent = collision.centFT0M(); break; - case kCentFV0A: + case UseCentFV0A: cent = collision.centFV0A(); break; default: @@ -598,195 +688,217 @@ struct CorrReso { template bool eventRct(TCollision const& collision, const bool fillCounter) { + if (cfgEvSel.cfgEvSelRCTflags.value.empty()) { + return true; + } if (!rctChecker(collision)) { if (fillCounter) { - registry.fill(HIST("hEventCountRct"), 0.5); + histos.fill(HIST("hEventCountRct"), 0.5); } - return 0; + return false; } if (fillCounter) { - registry.fill(HIST("hEventCountRct"), 1.5); + histos.fill(HIST("hEventCountRct"), 1.5); } - return 1; + return true; } template - bool eventSelected(TCollision const& collision, const int mult, const bool fillCounter) + bool eventSelected(TCollision const& collision, const int mult, const double cent, const bool fillCounter) { - if (eventCuts[kUseNoTimeFrameBorder][kEvCut1] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return 0; + if (fillCounter) { + histos.fill(HIST("hEventCount"), FilteredEvents); } - if (fillCounter && eventCuts[kUseNoTimeFrameBorder][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); + if (!collision.sel8()) { + return false; } - if (eventCuts[kUseNoITSROFrameBorder][kEvCut1] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return 0; + if (fillCounter) { + histos.fill(HIST("hEventCount"), AfterSel8); + } + + if (eventCuts[UseNoTimeFrameBorder][EvCut1] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (fillCounter && eventCuts[UseNoTimeFrameBorder][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoTimeFrameBorder); } - if (fillCounter && eventCuts[kUseNoITSROFrameBorder][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); + + if (eventCuts[UseNoITSROFrameBorder][EvCut1] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (fillCounter && eventCuts[UseNoITSROFrameBorder][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoITSROFrameBorder); } - if (eventCuts[kUseNoSameBunchPileup][kEvCut1] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + + if (eventCuts[UseNoSameBunchPileup][EvCut1] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoSameBunchPileup][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoSameBunchPileup); + if (fillCounter && eventCuts[UseNoSameBunchPileup][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoSameBunchPileup); } - if (eventCuts[kUseGoodZvtxFT0vsPV][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + + if (eventCuts[UseGoodZvtxFT0vsPV][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference // use this cut at low multiplicities with caution - return 0; + return false; } - if (fillCounter && eventCuts[kUseGoodZvtxFT0vsPV][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); + if (fillCounter && eventCuts[UseGoodZvtxFT0vsPV][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodZvtxFT0vsPV); } - if (eventCuts[kUseNoCollInTimeRangeStandard][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + + if (eventCuts[UseNoCollInTimeRangeStandard][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // no collisions in specified time range - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoCollInTimeRangeStandard][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); + if (fillCounter && eventCuts[UseNoCollInTimeRangeStandard][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoCollInTimeRangeStandard); } - if (eventCuts[kUseGoodITSLayersAll][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + + if (eventCuts[UseGoodITSLayersAll][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { // from Jan 9 2025 AOT meeting // cut time intervals with dead ITS staves - return 0; + return false; } - if (fillCounter && eventCuts[kUseGoodITSLayersAll][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseGoodITSLayersAll); + if (fillCounter && eventCuts[UseGoodITSLayersAll][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodITSLayersAll); } - if (eventCuts[kUseGoodITSLayer0123][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { - return 0; + + if (eventCuts[UseGoodITSLayer0123][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + return false; } - if (fillCounter && eventCuts[kUseGoodITSLayer0123][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseGoodITSLayer0123); + if (fillCounter && eventCuts[UseGoodITSLayer0123][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodITSLayer0123); } - if (eventCuts[kUseNoCollInRofStandard][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + + if (eventCuts[UseNoCollInRofStandard][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoCollInRofStandard][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoCollInRofStandard); + if (fillCounter && eventCuts[UseNoCollInRofStandard][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoCollInRofStandard); } - if (eventCuts[kUseNoHighMultCollInPrevRof][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + + if (eventCuts[UseNoHighMultCollInPrevRof][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoHighMultCollInPrevRof][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); + if (fillCounter && eventCuts[UseNoHighMultCollInPrevRof][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoHighMultCollInPrevRof); } + auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[kUseOccupancy][kEvCut1] && (occupancy < cfgEventSelection.cfgCutOccupancyLow || occupancy > cfgEventSelection.cfgCutOccupancyHigh)) { - return 0; + if (eventCuts[UseOccupancy][EvCut1] && (occupancy < cfgEvSel.cfgCutOccupancyLow || occupancy > cfgEvSel.cfgCutOccupancyHigh)) { + return false; } - if (fillCounter && eventCuts[kUseOccupancy][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseOccupancy); + if (fillCounter && eventCuts[UseOccupancy][EvCut1]) { + histos.fill(HIST("hEventCount"), UseOccupancy); } - if (eventCuts[kUseMultCorrCut][kEvCut1]) { - float cent = getCentrality(collision); + + if (eventCuts[UseMultCorrCut][EvCut1]) { if (cfgFuncParas.cfgMultPVT0CCutEnabled) { if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(cent)) { - return 0; + return false; } if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(cent)) { - return 0; + return false; } } if (cfgFuncParas.cfgMultT0CCutEnabled) { if (mult < cfgFuncParas.fMultT0CCutLow->Eval(cent)) { - return 0; + return false; } if (mult > cfgFuncParas.fMultT0CCutHigh->Eval(cent)) { - return 0; + return false; } } if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { if (mult < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) { - return 0; + return false; } if (mult > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) { - return 0; + return false; } } if (cfgFuncParas.cfgMultMultV0ACutEnabled) { if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(mult)) { - return 0; + return false; } if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(mult)) { - return 0; + return false; } } } - if (fillCounter && eventCuts[kUseMultCorrCut][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseMultCorrCut); + if (fillCounter && eventCuts[UseMultCorrCut][EvCut1]) { + histos.fill(HIST("hEventCount"), UseMultCorrCut); } // V0A T0A 5 sigma cut - if (eventCuts[kUseT0AV0ACut][kEvCut1] && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > cfgFuncParas.cfgV0AT0Acut * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) { - return 0; + if (eventCuts[UseT0AV0ACut][EvCut1] && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > cfgFuncParas.cfgV0AT0Acut * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) { + return false; } - if (fillCounter && eventCuts[kUseT0AV0ACut][kEvCut1]) { - registry.fill(HIST("hEventCount"), kUseT0AV0ACut); + if (fillCounter && eventCuts[UseT0AV0ACut][EvCut1]) { + histos.fill(HIST("hEventCount"), UseT0AV0ACut); } - return 1; + return true; } template void eventSelectedIndividually(TCollision const& collision) { - registry.fill(HIST("hPassedEventSelection"), kFilteredEvents); + histos.fill(HIST("hPassedEventSelection"), FilteredEvents); if (collision.sel8()) { - registry.fill(HIST("hPassedEventSelection"), kAfterSel8); + histos.fill(HIST("hPassedEventSelection"), AfterSel8); } if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoTimeFrameBorder); + histos.fill(HIST("hPassedEventSelection"), UseNoTimeFrameBorder); } if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoITSROFrameBorder); + histos.fill(HIST("hPassedEventSelection"), UseNoITSROFrameBorder); } if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoSameBunchPileup); + histos.fill(HIST("hPassedEventSelection"), UseNoSameBunchPileup); } if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - registry.fill(HIST("hPassedEventSelection"), kUseGoodZvtxFT0vsPV); + histos.fill(HIST("hPassedEventSelection"), UseGoodZvtxFT0vsPV); } if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoCollInTimeRangeStandard); + histos.fill(HIST("hPassedEventSelection"), UseNoCollInTimeRangeStandard); } if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { - registry.fill(HIST("hPassedEventSelection"), kUseGoodITSLayersAll); + histos.fill(HIST("hPassedEventSelection"), UseGoodITSLayersAll); } if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { - registry.fill(HIST("hPassedEventSelection"), kUseGoodITSLayer0123); + histos.fill(HIST("hPassedEventSelection"), UseGoodITSLayer0123); } if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoCollInRofStandard); + histos.fill(HIST("hPassedEventSelection"), UseNoCollInRofStandard); } if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { - registry.fill(HIST("hPassedEventSelection"), kUseNoHighMultCollInPrevRof); + histos.fill(HIST("hPassedEventSelection"), UseNoHighMultCollInPrevRof); } auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[kUseOccupancy][kEvCut1] && (occupancy > cfgEventSelection.cfgCutOccupancyLow && occupancy < cfgEventSelection.cfgCutOccupancyHigh)) { - registry.fill(HIST("hPassedEventSelection"), kUseOccupancy); + if (eventCuts[UseOccupancy][EvCut1] && (occupancy > cfgEvSel.cfgCutOccupancyLow && occupancy < cfgEvSel.cfgCutOccupancyHigh)) { + histos.fill(HIST("hPassedEventSelection"), UseOccupancy); } } @@ -832,7 +944,39 @@ struct CorrReso { template bool trackSelected(TTrack const& track) { - return ((track.tpcNClsFound() >= cfgTrackCuts.cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgTrackCuts.cfgCutITSclu) && (track.tpcChi2NCl() < cfgTrackCuts.cfgCutChi2prTPCcls) && (std::abs(track.dcaZ()) < cfgTrackCuts.cfgCutDCAz)); + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].empty() && std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt())) { + return false; + } + + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].empty()) { + if (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAz->Eval(track.pt())) { + return false; + } + } else { + if (std::fabs(track.dcaZ()) > trackCuts[TrkCutDCAz][UseGenTrkCuts]) { + return false; + } + } + + return ((track.pt() > trackCuts[TrkCutPtMin][UseGenTrkCuts]) && (track.pt() < trackCuts[TrkCutPtMax][UseGenTrkCuts]) && (std::abs(track.eta()) < trackCuts[TrkCutEtaCut][UseGenTrkCuts]) && (track.tpcChi2NCl() < trackCuts[TrkCutChi2PrTpcCls][UseGenTrkCuts]) && (track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseGenTrkCuts]) && (track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseGenTrkCuts]) && (track.itsNCls() >= trackCuts[TrkCutItsCluster][UseGenTrkCuts])); + } + + template + bool trackSelectedForNch(TTrack const& track) + { + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].empty() && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxyForNch->Eval(track.pt()))) { + return false; + } + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].empty()) { + if (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAzForNch->Eval(track.pt())) { + return false; + } + } else { + if (std::fabs(track.dcaZ()) > trackCuts[TrkCutDCAz][UseNchSelCuts]) { + return false; + } + } + return ((track.pt() > trackCuts[TrkCutPtMin][UseNchSelCuts]) && (track.pt() < trackCuts[TrkCutPtMax][UseNchSelCuts]) && (std::abs(track.eta()) < trackCuts[TrkCutEtaCut][UseNchSelCuts]) && (track.tpcChi2NCl() < trackCuts[TrkCutChi2PrTpcCls][UseNchSelCuts]) && (track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseNchSelCuts]) && (track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseNchSelCuts]) && (track.itsNCls() >= trackCuts[TrkCutItsCluster][UseNchSelCuts])); } void loadGain(aod::BCsWithTimestamps::iterator const& bc) @@ -842,12 +986,12 @@ struct CorrReso { auto timestamp = bc.timestamp(); constexpr int ChannelsFT0 = 208; - if (cfgCorrLevel == 0) { + if (cfgGeneral.cfgCorrLevel == 0) { for (auto i{0u}; i < ChannelsFT0; i++) { cstFT0RelGain.push_back(1.); } } else { - fullPath = cfgGainEqPath; + fullPath = cfgGeneral.cfgGainEqPath; fullPath += "/FT0"; const auto objft0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); if (!objft0Gain) { @@ -861,29 +1005,17 @@ struct CorrReso { } template - void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType, int system) + void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType) { - if (fitType == kFT0C) { + if (fitType == IndexFT0C) { id = ft0.channelC()[iCh]; id = id + Ft0IndexA; ampl = ft0.amplitudeC()[iCh]; - if (system == SameEvent) { - registry.fill(HIST("FT0Amp"), id, ampl); - } ampl = ampl / cstFT0RelGain[id]; - if (system == SameEvent) { - registry.fill(HIST("FT0AmpCorrect"), id, ampl); - } - } else if (fitType == kFT0A) { + } else if (fitType == IndexFT0A) { id = ft0.channelA()[iCh]; ampl = ft0.amplitudeA()[iCh]; - if (system == SameEvent) { - registry.fill(HIST("FT0Amp"), id, ampl); - } ampl = ampl / cstFT0RelGain[id]; - if (system == SameEvent) { - registry.fill(HIST("FT0AmpCorrect"), id, ampl); - } } else { LOGF(fatal, "Cor Index %d out of range", fitType); } @@ -899,18 +1031,26 @@ struct CorrReso { int pid = -1; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton std::array nSigmaToUse = cfgPIDConfigs.cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS - int kIndexDetector = cfgPIDConfigs.cfgUseItsPID ? kITS : kTPC; // Choose which nSigma to use: TPC or ITS + int useIndexDetector = UseTPC; + useIndexDetector = cfgPIDConfigs.cfgUseItsPID ? UseITS : UseTPC; // Choose which nSigma to use: TPC or ITS bool isPion = false; bool isKaon = false; bool isProton = false; - bool isDetectedPion = nSigmaToUse[iPionUp] < nSigmaVals[iPionUp][kIndexDetector] && nSigmaToUse[iPionUp] > nSigmaVals[iPionLow][kIndexDetector]; - bool isDetectedKaon = nSigmaToUse[iKaonUp] < nSigmaVals[iKaonUp][kIndexDetector] && nSigmaToUse[iKaonUp] > nSigmaVals[iKaonLow][kIndexDetector]; - bool isDetectedProton = nSigmaToUse[iProtonUp] < nSigmaVals[iProtonUp][kIndexDetector] && nSigmaToUse[iProtonUp] > nSigmaVals[iProtonLow][kIndexDetector]; + bool isDetectedPion = false; + bool isDetectedKaon = false; + bool isDetectedProton = false; + bool isTofPion = false; + bool isTofKaon = false; + bool isTofProton = false; - bool isTofPion = nSigmaTOF[iPionUp] < nSigmaVals[iPionUp][kTOF] && nSigmaTOF[iPionUp] > nSigmaVals[iPionLow][kTOF]; - bool isTofKaon = nSigmaTOF[iKaonUp] < nSigmaVals[iKaonUp][kTOF] && nSigmaTOF[iKaonUp] > nSigmaVals[iKaonLow][kTOF]; - bool isTofProton = nSigmaTOF[iProtonUp] < nSigmaVals[iProtonUp][kTOF] && nSigmaTOF[iProtonUp] > nSigmaVals[iProtonLow][kTOF]; + isDetectedPion = nSigmaToUse[IndexPionUp] < nSigmaVals[IndexPionUp][useIndexDetector] && nSigmaToUse[IndexPionUp] > nSigmaVals[IndexPionLow][useIndexDetector]; + isDetectedKaon = nSigmaToUse[IndexKaonUp] < nSigmaVals[IndexKaonUp][useIndexDetector] && nSigmaToUse[IndexKaonUp] > nSigmaVals[IndexKaonLow][useIndexDetector]; + isDetectedProton = nSigmaToUse[IndexProtonUp] < nSigmaVals[IndexProtonUp][useIndexDetector] && nSigmaToUse[IndexProtonUp] > nSigmaVals[IndexProtonLow][useIndexDetector]; + + isTofPion = nSigmaTOF[IndexPionUp] < nSigmaVals[IndexPionUp][UseTOF] && nSigmaTOF[IndexPionUp] > nSigmaVals[IndexPionLow][UseTOF]; + isTofKaon = nSigmaTOF[IndexKaonUp] < nSigmaVals[IndexKaonUp][UseTOF] && nSigmaTOF[IndexKaonUp] > nSigmaVals[IndexKaonLow][UseTOF]; + isTofProton = nSigmaTOF[IndexProtonUp] < nSigmaVals[IndexProtonUp][UseTOF] && nSigmaTOF[IndexProtonUp] > nSigmaVals[IndexProtonLow][UseTOF]; if (track.pt() > cfgPIDConfigs.cfgTofPtCut && !track.hasTOF()) { return -1; @@ -930,11 +1070,11 @@ struct CorrReso { } if (isPion) { - pid = kPions; + pid = UsePions; } else if (isKaon) { - pid = kKaons; + pid = UseKaons; } else if (isProton) { - pid = kProtons; + pid = UseProtons; } else { return -1; // no particle satisfies the criteria } @@ -945,30 +1085,27 @@ struct CorrReso { template bool selectionV0Daughter(TTrack const& track, int pid) { - if (!(track.itsNCls() >= cfgTrackCuts.cfgCutITSclu)) { + if (!(track.itsNCls() >= trackCuts[TrkCutItsCluster][UseGenTrkCuts])) { return false; } if (!track.hasTPC()) { return false; } - if (!(track.tpcNClsFound() >= cfgTrackCuts.cfgCutTPCclu)) { - return false; - } - if (!(track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgCutTPCCrossedRows)) { + if (!(track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseGenTrkCuts])) { return false; } - if (!(std::abs(track.dcaZ()) < cfgTrackCuts.cfgCutDCAz)) { + if (!(track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseGenTrkCuts])) { return false; } if (cfgPIDConfigs.cfgUseOnlyTPC) { - if (pid == kPions && std::abs(track.tpcNSigmaPi()) > cfgPIDConfigs.cfgTpcCut) { + if (pid == UsePions && std::abs(track.tpcNSigmaPi()) > cfgPIDConfigs.cfgTpcCut) { return false; } - if (pid == kKaons && std::abs(track.tpcNSigmaKa()) > cfgPIDConfigs.cfgTpcCut) { + if (pid == UseKaons && std::abs(track.tpcNSigmaKa()) > cfgPIDConfigs.cfgTpcCut) { return false; } - if (pid == kProtons && std::abs(track.tpcNSigmaPr()) > cfgPIDConfigs.cfgTpcCut) { + if (pid == UseProtons && std::abs(track.tpcNSigmaPr()) > cfgPIDConfigs.cfgTpcCut) { return false; } } else { @@ -987,38 +1124,40 @@ struct CorrReso { if (correctionsLoaded) { return; } - if (!cfgEfficiency.value.empty()) { - if (cfgLocalEfficiency) { - TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); + if (!cfgEffWeights.cfgEfficiency.value.empty()) { + if (cfgEffWeights.cfgLocalEfficiency) { + TFile* fEfficiencyTrigger = nullptr; + fEfficiencyTrigger = TFile::Open(cfgEffWeights.cfgEfficiency.value.c_str(), "READ"); mEfficiency = dynamic_cast(fEfficiencyTrigger->Get("ccdb_object")); } else { - mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + mEfficiency = ccdb->getForTimeStamp(cfgEffWeights.cfgEfficiency, timestamp); } if (mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgEfficiency.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), static_cast(mEfficiency)); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgEfficiency.value.c_str(), static_cast(mEfficiency)); } - if (!cfgEfficiencyNch.value.empty()) { - if (cfgLocalEfficiencyNch) { - TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiencyNch.value.c_str(), "READ"); + if (!cfgEffWeights.cfgEfficiencyNch.value.empty()) { + if (cfgEffWeights.cfgLocalEfficiencyNch) { + TFile* fEfficiencyTrigger = nullptr; + fEfficiencyTrigger = TFile::Open(cfgEffWeights.cfgEfficiencyNch.value.c_str(), "READ"); mEfficiencyNch = dynamic_cast(fEfficiencyTrigger->Get("ccdb_object")); } else { - mEfficiencyNch = ccdb->getForTimeStamp(cfgEfficiencyNch, timestamp); + mEfficiencyNch = ccdb->getForTimeStamp(cfgEffWeights.cfgEfficiencyNch, timestamp); } if (!mEfficiencyNch) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiencyNch.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgEfficiencyNch.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiencyNch.value.c_str(), static_cast(mEfficiencyNch)); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgEfficiencyNch.value.c_str(), static_cast(mEfficiencyNch)); } - if (!cfgCentralityWeight.value.empty()) { - mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); + if (!cfgEffWeights.cfgCentralityWeight.value.empty()) { + mCentralityWeight = ccdb->getForTimeStamp(cfgEffWeights.cfgCentralityWeight, timestamp); if (mCentralityWeight == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCentralityWeight.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgCentralityWeight.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), static_cast(mCentralityWeight)); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgCentralityWeight.value.c_str(), static_cast(mCentralityWeight)); } correctionsLoaded = true; } @@ -1027,10 +1166,8 @@ struct CorrReso { { float effNch = 1.; if (mEfficiencyNch) { - int ptBin = mEfficiencyNch->FindBin(pt); effNch = mEfficiencyNch->GetBinContent(ptBin); - } else { effNch = 1.0; } @@ -1045,12 +1182,10 @@ struct CorrReso { { float eff = 1.; if (mEfficiency) { - int etaBin = mEfficiency->GetXaxis()->FindBin(eta); // use the eta bin corresponding to eta=0 for the trigger particle efficiency int ptBin = mEfficiency->GetYaxis()->FindBin(pt); int vertexBin = mEfficiency->GetZaxis()->FindBin(vertex); // use the vertex bin corresponding to z=0 for the trigger particle efficiency eff = mEfficiency->GetBinContent(etaBin, ptBin, vertexBin); - } else { eff = 1.0; } @@ -1061,17 +1196,34 @@ struct CorrReso { return true; } + bool getCentralityWeight(float& weightCent, const double centrality) + { + float weight = 1.; + if (mCentralityWeight) { + weight = mCentralityWeight->GetBinContent(mCentralityWeight->FindBin(centrality)); + } else { + weight = 1.0; + } + if (weight == 0) { + return false; + } + weightCent = weight; + return true; + } + template - void trackCounter(const TTracks& tracks, double& multiplicity) // function to count the number of tracks in the event and fill the histogram + void nchCounter(const TTracks& tracks, double& multiplicity) // function to count the number of tracks in the event and fill the histogram { double nTracksCorrected = 0; float weightNch = 1.0f; for (auto const& track : tracks) { + if (!trackSelectedForNch(track)) { + continue; + } if (!getEfficiencyCorrectionNch(weightNch, track.pt())) { continue; } - nTracksCorrected += weightNch; } multiplicity = nTracksCorrected; @@ -1094,16 +1246,16 @@ struct CorrReso { continue; } - registry.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); - registry.fill(HIST("Eta"), track1.eta()); - registry.fill(HIST("EtaCorrected"), track1.eta(), weff1); - registry.fill(HIST("pTFiner"), track1.pt()); - registry.fill(HIST("pTFinerCorrected"), track1.pt(), weff1); + histos.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); + histos.fill(HIST("Eta"), track1.eta()); + histos.fill(HIST("EtaCorrected"), track1.eta(), weff1); + histos.fill(HIST("pTFiner"), track1.pt()); + histos.fill(HIST("pTFinerCorrected"), track1.pt(), weff1); } } template - bool isSelectedK0(V0 const& candidate, float posZ, float posY, float posX) + bool isSelectedK0(V0 const& candidate, float posZ, float posY, float posX, int system, int corType) { double mk0 = candidate.mK0Short(); @@ -1111,68 +1263,103 @@ struct CorrReso { auto postrack = candidate.template posTrack_as(); auto negtrack = candidate.template negTrack_as(); - registry.fill(HIST("hK0Count"), 0.5); - if (postrack.pt() < resoCutVals[kPosTrackPt][iK0] || negtrack.pt() < resoCutVals[kNegTrackPt][iK0]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillCandidate); + } + if (postrack.pt() < resoCutVals[CutPosTrackPt][IndexK0] || negtrack.pt() < resoCutVals[CutNegTrackPt][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 1.5); - if (mk0 < resoCutVals[kMassMin][iK0] || mk0 > resoCutVals[kMassMax][iK0]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillDaughterPt); + } + if (mk0 < resoCutVals[CutMassMin][IndexK0] || mk0 > resoCutVals[CutMassMax][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 2.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillMassCut); + } // Rapidity correction - if (std::abs(candidate.yK0Short()) > resoCutVals[kRapidity][iK0]) { + if (candidate.yK0Short() > resoCutVals[CutRapidityMax][IndexK0] || candidate.yK0Short() < resoCutVals[CutRapidityMin][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 3.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillRapidityCut); + } // DCA cuts for K0short - if (std::abs(candidate.dcapostopv()) < resoCutVals[kDCAPosToPVMin][iK0] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCANegToPVMin][iK0]) { + if (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCAPosToPVMin][IndexK0] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCANegToPVMin][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 4.5); - if (resoSwitchVals[kUseDCABetDaug][iK0] && std::abs(candidate.dcaV0daughters()) > resoCutVals[kDCABetDaug][iK0]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillDCAtoPV); + } + if (resoSwitchVals[UseDCABetDaug][IndexK0] && std::abs(candidate.dcaV0daughters()) > resoCutVals[CutDCABetDaug][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 5.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillDCAxDaughters); + } // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][iK0] && (candidate.v0radius() < resoCutVals[kRadiusMin][iK0] || candidate.v0radius() > resoCutVals[kRadiusMax][iK0])) { + if (resoSwitchVals[UseV0Radius][IndexK0] && (candidate.v0radius() < resoCutVals[CutRadiusMin][IndexK0] || candidate.v0radius() > resoCutVals[CutRadiusMax][IndexK0])) { return false; } - registry.fill(HIST("hK0Count"), 6.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillV0Radius); + } // cosine pointing angle cuts - if (resoSwitchVals[kUseCosPA][iK0] && candidate.v0cosPA() < resoCutVals[kCosPA][iK0]) { + if (resoSwitchVals[UseCosPA][IndexK0] && candidate.v0cosPA() < resoCutVals[CutCosPA][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 7.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillCosPA); + } // Proper lifetime float cTauK0 = candidate.distovertotmom(posX, posY, posZ) * massK0Short; - if (resoSwitchVals[kUseProperLifetime][iK0] && cTauK0 > resoCutVals[kLifeTime][iK0]) { + if (resoSwitchVals[UseProperLifetime][IndexK0] && cTauK0 > resoCutVals[CutLifeTime][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 8.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillProperLifetime); + } // ArmenterosPodolanskiCut - if (resoSwitchVals[kUseArmPodCut][iK0] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[kArmPodMinVal][iK0]) { + if (resoSwitchVals[UseArmPodCut][IndexK0] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[CutArmPodMinVal][IndexK0]) { return false; } - registry.fill(HIST("hK0Count"), 9.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillArmPodCut); + } + + if (resoSwitchVals[UseCompMassRej][IndexK0]) { + if (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda) < resoCutVals[CutCompMassRej][IndexK0]) { + return false; + } + if (std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda) < resoCutVals[CutCompMassRej][IndexK0]) { + return false; + } + } + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillCompetingMass); + } + // Selection on V0 daughters - if (!selectionV0Daughter(postrack, kPions) || !selectionV0Daughter(negtrack, kPions)) { + if (!selectionV0Daughter(postrack, UsePions) || !selectionV0Daughter(negtrack, UsePions)) { return false; } - registry.fill(HIST("hK0Count"), 10.5); - - registry.fill(HIST("hK0Phi"), candidate.phi()); - registry.fill(HIST("hK0Eta"), candidate.eta()); - registry.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaPi()); - registry.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaPi()); - registry.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaPi()); - registry.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaPi()); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hK0Count"), FillDaughterTrackSelected); + histos.fill(HIST("hK0Phi"), candidate.phi()); + histos.fill(HIST("hK0Rap"), candidate.yK0Short()); + histos.fill(HIST("hK0Eta"), candidate.eta()); + histos.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaPi()); + histos.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaPi()); + histos.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaPi()); + histos.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaPi()); + } return true; } template - bool isSelectedLambda(V0 const& candidate, float posZ, float posY, float posX) + bool isSelectedLambda(V0 const& candidate, float posZ, float posY, float posX, int system, int corType) { bool isL = false; // Is lambda candidate bool isAL = false; // Is anti-lambda candidate @@ -1184,98 +1371,135 @@ struct CorrReso { auto postrack = candidate.template posTrack_as(); auto negtrack = candidate.template negTrack_as(); - registry.fill(HIST("hLambdaCount"), 0.5); - if (postrack.pt() < resoCutVals[kPosTrackPt][iLambda] || negtrack.pt() < resoCutVals[kNegTrackPt][iLambda]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillCandidate); + } + if (postrack.pt() < resoCutVals[CutPosTrackPt][IndexLambda] || negtrack.pt() < resoCutVals[CutNegTrackPt][IndexLambda]) { return false; } - registry.fill(HIST("hLambdaCount"), 1.5); - if (mlambda > resoCutVals[kMassMin][iLambda] && mlambda < resoCutVals[kMassMax][iLambda]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillDaughterPt); + } + if (mlambda > resoCutVals[CutMassMin][IndexLambda] && mlambda < resoCutVals[CutMassMax][IndexLambda]) { isL = true; } - if (mantilambda > resoCutVals[kMassMin][iLambda] && mantilambda < resoCutVals[kMassMax][iLambda]) { + if (mantilambda > resoCutVals[CutMassMin][IndexLambda] && mantilambda < resoCutVals[CutMassMax][IndexLambda]) { isAL = true; } if (!isL && !isAL) { return false; } - registry.fill(HIST("hLambdaCount"), 2.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillMassCut); + } // Rapidity correction - if (std::abs(candidate.yLambda()) > resoCutVals[kRapidity][iLambda]) { + if (candidate.yLambda() > resoCutVals[CutRapidityMax][IndexLambda] || candidate.yLambda() < resoCutVals[CutRapidityMin][IndexLambda]) { return false; } - registry.fill(HIST("hLambdaCount"), 3.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillRapidityCut); + } // DCA cuts for lambda and antilambda - if (isL && (std::abs(candidate.dcapostopv()) < resoCutVals[kDCAPosToPVMin][iLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCANegToPVMin][iLambda])) { + if (isL && (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCAPosToPVMin][IndexLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCANegToPVMin][IndexLambda])) { isL = false; } - if (isAL && (std::abs(candidate.dcapostopv()) < resoCutVals[kDCANegToPVMin][iLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCAPosToPVMin][iLambda])) { + if (isAL && (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCANegToPVMin][IndexLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCAPosToPVMin][IndexLambda])) { isAL = false; } if (!isL && !isAL) { return false; } - registry.fill(HIST("hLambdaCount"), 4.5); - if (resoSwitchVals[kUseDCABetDaug][iLambda] && std::abs(candidate.dcaV0daughters()) > resoCutVals[kDCABetDaug][iLambda]) { + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillDCAtoPV); + } + if (resoSwitchVals[UseDCABetDaug][IndexLambda] && std::abs(candidate.dcaV0daughters()) > resoCutVals[CutDCABetDaug][IndexLambda]) { return false; } - registry.fill(HIST("hLambdaCount"), 5.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillDCAxDaughters); + } // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][iLambda] && (candidate.v0radius() < resoCutVals[kRadiusMin][iLambda] || candidate.v0radius() > resoCutVals[kRadiusMax][iLambda])) { + if (resoSwitchVals[UseV0Radius][IndexLambda] && (candidate.v0radius() < resoCutVals[CutRadiusMin][IndexLambda] || candidate.v0radius() > resoCutVals[CutRadiusMax][IndexLambda])) { return false; } - registry.fill(HIST("hLambdaCount"), 6.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillV0Radius); + } // cosine pointing angle cuts - if (resoSwitchVals[kUseCosPA][iLambda] && candidate.v0cosPA() < resoCutVals[kCosPA][iLambda]) { + if (resoSwitchVals[UseCosPA][IndexLambda] && candidate.v0cosPA() < resoCutVals[CutCosPA][IndexLambda]) { return false; } - registry.fill(HIST("hLambdaCount"), 7.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillCosPA); + } // Proper lifetime float cTauLambda = candidate.distovertotmom(posX, posY, posZ) * massLambda; - if (resoSwitchVals[kUseProperLifetime][iLambda] && cTauLambda > resoCutVals[kLifeTime][iLambda]) { + if (resoSwitchVals[UseProperLifetime][IndexLambda] && cTauLambda > resoCutVals[CutLifeTime][IndexLambda]) { return false; } - registry.fill(HIST("hLambdaCount"), 8.5); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillProperLifetime); + } + + // ArmenterosPodolanskiCut + if (resoSwitchVals[UseArmPodCut][IndexLambda] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[CutArmPodMinVal][IndexLambda]) { + return false; + } + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillArmPodCut); + } + + if (resoSwitchVals[UseCompMassRej][IndexLambda]) { + if (std::abs(candidate.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[CutCompMassRej][IndexLambda]) { + return false; + } + } + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillCompetingMass); + } if (isL) { - if (!selectionV0Daughter(postrack, kProtons) || !selectionV0Daughter(negtrack, kPions)) { + if (!selectionV0Daughter(postrack, UseProtons) || !selectionV0Daughter(negtrack, UsePions)) { isL = false; } } if (isAL) { - if (!selectionV0Daughter(postrack, kPions) || !selectionV0Daughter(negtrack, kProtons)) { + if (!selectionV0Daughter(postrack, UsePions) || !selectionV0Daughter(negtrack, UseProtons)) { isAL = false; } } if (!isL && !isAL) { return false; } - registry.fill(HIST("hLambdaCount"), 9.5); - - registry.fill(HIST("hLambdaPhi"), candidate.phi()); - registry.fill(HIST("hLambdaEta"), candidate.eta()); - if (isL) { - registry.fill(HIST("PrPlusTPC_La"), postrack.pt(), postrack.tpcNSigmaPr()); - registry.fill(HIST("PrPlusTOF_La"), postrack.pt(), postrack.tofNSigmaPr()); - registry.fill(HIST("PiMinusTPC_La"), negtrack.pt(), negtrack.tpcNSigmaPi()); - registry.fill(HIST("PiMinusTOF_La"), negtrack.pt(), negtrack.tofNSigmaPi()); + if (system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("hLambdaCount"), FillDaughterTrackSelected); + histos.fill(HIST("hLambdaPhi"), candidate.phi()); + histos.fill(HIST("hLambdaEta"), candidate.eta()); + histos.fill(HIST("hLambdaRap"), candidate.yLambda()); } - if (isAL) { - registry.fill(HIST("PrMinusTPC_Al"), negtrack.pt(), negtrack.tpcNSigmaPr()); - registry.fill(HIST("PrMinusTOF_Al"), negtrack.pt(), negtrack.tofNSigmaPr()); - registry.fill(HIST("PiPlusTPC_Al"), postrack.pt(), postrack.tpcNSigmaPi()); - registry.fill(HIST("PiPlusTOF_Al"), postrack.pt(), postrack.tofNSigmaPi()); + if (isL && system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("PrPlusTPC_La"), postrack.pt(), postrack.tpcNSigmaPr()); + histos.fill(HIST("PrPlusTOF_La"), postrack.pt(), postrack.tofNSigmaPr()); + histos.fill(HIST("PiMinusTPC_La"), negtrack.pt(), negtrack.tpcNSigmaPi()); + histos.fill(HIST("PiMinusTOF_La"), negtrack.pt(), negtrack.tofNSigmaPi()); + } + if (isAL && system == SameEvent && corType == IndexFT0A) { + histos.fill(HIST("PrMinusTPC_Al"), negtrack.pt(), negtrack.tpcNSigmaPr()); + histos.fill(HIST("PrMinusTOF_Al"), negtrack.pt(), negtrack.tofNSigmaPr()); + histos.fill(HIST("PiPlusTPC_Al"), postrack.pt(), postrack.tpcNSigmaPi()); + histos.fill(HIST("PiPlusTOF_Al"), postrack.pt(), postrack.tofNSigmaPi()); } return true; } - template - void fillCorrelationsTPCFT0(const TV0Tracks& tracks1, TFT0s const& ft0, float posZ, float posY, float posX, int system, int corType, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + template + void fillCorrelationsTPCFT0(const TV0Tracks& tracks1, TFT0s const& ft0, float posZ, float posY, float posX, int system, double eventClass, int corType, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { - int fSampleIndex = static_cast(gRandom->Uniform(0.0, cfgSampleSize)); + int fSampleIndex = static_cast(fRandom.Uniform(0.0, cfgGeneral.cfgSampleSize)); float triggerWeight = 1.0f; // loop over all tracks @@ -1283,16 +1507,16 @@ struct CorrReso { double resoMass = -1; // 4 = kshort, 5 = lambda, 6 = phi - if (cfgPIDConfigs.cfgPIDParticle == kK0) { - if (!isSelectedK0(track1, posZ, posY, posX)) { + if (cfgPIDConfigs.cfgPIDParticle == UseK0) { + if (!isSelectedK0(track1, posZ, posY, posX, system, corType)) { continue; // Reject if called for K0 but V0 is not K0 } resoMass = track1.mK0Short(); } - if (cfgPIDConfigs.cfgPIDParticle == kLambda) { - if (!isSelectedLambda(track1, posZ, posY, posX)) { + if (cfgPIDConfigs.cfgPIDParticle == UseLambda) { + if (!isSelectedLambda(track1, posZ, posY, posX, system, corType)) { continue; // Reject if called for Lambda but V0 is not lambda } @@ -1300,17 +1524,17 @@ struct CorrReso { } if (system == SameEvent) { - if (corType == kFT0C) { - registry.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, track1.pt(), resoMass, eventWeight * triggerWeight); - } else if (corType == kFT0A) { - registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, track1.pt(), resoMass, eventWeight * triggerWeight); + if (corType == IndexFT0C) { + histos.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, eventClass, track1.pt(), resoMass, eventWeight * triggerWeight); + } else if (corType == IndexFT0A) { + histos.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, eventClass, track1.pt(), resoMass, eventWeight * triggerWeight); } } std::size_t channelSize = 0; - if (corType == kFT0C) { + if (corType == IndexFT0C) { channelSize = ft0.channelC().size(); - } else if (corType == kFT0A) { + } else if (corType == IndexFT0A) { channelSize = ft0.channelA().size(); } else { LOGF(fatal, "Cor Index %d out of range", corType); @@ -1318,7 +1542,7 @@ struct CorrReso { for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int chanelid = 0; float ampl = 0.; - getChannel(ft0, iCh, chanelid, ampl, corType, system); + getChannel(ft0, iCh, chanelid, ampl, corType); auto phi = getPhiFT0(chanelid, corType); auto eta = getEtaFT0(chanelid, corType); @@ -1327,32 +1551,24 @@ struct CorrReso { float deltaEta = track1.eta() - eta; // fill the right sparse and histograms if (system == SameEvent) { - if (corType == kFT0A) { - if (cfgQaCheck) { - registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); - registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } - sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } else if (corType == kFT0C) { - if (cfgQaCheck) { - registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); - registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } - sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (corType == IndexFT0A) { + histos.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); + histos.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + } else if (corType == IndexFT0C) { + histos.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); + histos.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } else if (system == MixedEvent) { - if (corType == kFT0A) { - if (cfgQaCheck) { - registry.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); - registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } - mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } else if (corType == kFT0C) { - if (cfgQaCheck) { - registry.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); - registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); - } - mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (corType == IndexFT0A) { + histos.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); + histos.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + } else if (corType == IndexFT0C) { + histos.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); + histos.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), resoMass, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } } @@ -1361,8 +1577,8 @@ struct CorrReso { bool isGoodRun(int runNumber) { - for (const auto& ExcludedRun : cfgRunRemoveList.value) { - if (runNumber == ExcludedRun) { + for (const auto& excludedRun : cfgGeneral.cfgRunRemoveList.value) { + if (runNumber == excludedRun) { return false; } } @@ -1370,24 +1586,15 @@ struct CorrReso { return true; } - double massKaPlus = o2::constants::physics::MassKPlus; // same as MassKMinus double massLambda = o2::constants::physics::MassLambda; // same as MassLambda0 and MassLambda0Bar double massK0Short = o2::constants::physics::MassK0Short; // same as o2::constants::physics::MassK0 and o2::constants::physics::MassK0Bar - void processSameTpcFt0a(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, aod::V0Datas const& V0s) + void processSameTpcFt0(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, V0TrackCandidate const& V0s) { - registry.fill(HIST("hEventCount"), kFilteredEvents); - - if (cfgQaCheck) { + if (cfgGeneral.cfgQABasic) { eventSelectedIndividually(collision); } - if (!collision.sel8()) { - return; - } - - registry.fill(HIST("hEventCount"), kAfterSel8); - if (!eventRct(collision, true)) { return; } @@ -1395,12 +1602,14 @@ struct CorrReso { auto bc = collision.bc_as(); int currentRunNumber = bc.runNumber(); - if (!cfgRunRemoveList.value.empty()) { - if (!isGoodRun(currentRunNumber)) // Rejects runs if bad run number + if (!cfgGeneral.cfgRunRemoveList.value.empty()) { + if (!isGoodRun(currentRunNumber)) { // Rejects runs if bad run number return; + } } - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) { + auto cent = getCentrality(collision); + if (cfgEvSel.cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) { return; } @@ -1408,41 +1617,56 @@ struct CorrReso { return; } + histos.fill(HIST("hEventCount"), HaveFT0Cut); + loadAlignParam(bc.timestamp()); loadGain(bc); loadCorrection(bc.timestamp()); - float eventWeight = 1.0f; - - registry.fill(HIST("zVtx"), collision.posZ()); + float weightCent = 1.0f; - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - - fillYield(collision, tracks); + histos.fill(HIST("Centrality"), cent); + if (!cfgEvSel.cfgSelCollByNch) { + if (!getCentralityWeight(weightCent, cent)) { + return; // or continue in a loop + } + histos.fill(HIST("CentralityWeighted"), cent, weightCent); + } - double multiplicity = static_cast(tracks.size()); + histos.fill(HIST("zVtx"), collision.posZ()); - if (cfgQaCheck) { - registry.fill(HIST("Nch"), multiplicity); + if (cfgGeneral.cfgQABasic) { + fillYield(collision, tracks); } - if (cfgStrictTrackCounter) { - trackCounter(tracks, multiplicity); - } + auto multiplicity = static_cast(tracks.size()); + histos.fill(HIST("Nch"), multiplicity); - if (cfgQaCheck) { - registry.fill(HIST("Nch_corrected"), multiplicity); + if (cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks, multiplicity); + histos.fill(HIST("Nch_corrected"), multiplicity); } - if (multiplicity > cfgMaxMultForCorrelations || multiplicity < cfgMinMultForCorrelations) { + if (cfgEvSel.cfgSelCollByNch && (multiplicity > cfgEvSel.cfgMaxMultForCorrelations || multiplicity < cfgEvSel.cfgMinMultForCorrelations)) { + return; + } + if (!cfgEvSel.cfgSelCollByNch && (cent > cfgEvSel.cfgMaxCentForCorrelations || cent < cfgEvSel.cfgMinCentForCorrelations)) { return; } + histos.fill(HIST("eventcount"), SameEvent); + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent; + const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(V0s, ft0, collision.posZ(), collision.posY(), collision.posX(), SameEvent, kFT0A, eventWeight); + if (cfgGeneral.cfgAnalyzeTPCFT0A) { + fillCorrelationsTPCFT0(V0s, ft0, collision.posZ(), collision.posY(), collision.posX(), SameEvent, eventClass, IndexFT0A, weightCent); + } + if (cfgGeneral.cfgAnalyzeTPCFT0C) { + fillCorrelationsTPCFT0(V0s, ft0, collision.posZ(), collision.posY(), collision.posX(), SameEvent, eventClass, IndexFT0C, weightCent); + } } - PROCESS_SWITCH(CorrReso, processSameTpcFt0a, "Process same event for TPC-FT0 correlation", false); + PROCESS_SWITCH(CorrReso, processSameTpcFt0, "Process same event for TPC-FT0 correlation", false); - void processMixedTpcFt0a(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, aod::V0Datas const& V0s) + void processMixedTpcFt0(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, V0TrackCandidate const& V0s) { auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); @@ -1452,14 +1676,14 @@ struct CorrReso { using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; - MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}}; + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(V0s, tracks); - Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, v0s1, collision2, tracks2] = *it; - if (!collision1.sel8() || !collision2.sel8()) { + if (!collision1.sel8() || !collision2.sel8()) { // Doing this at the top of mixed events loop to reduce computation (This cut is also there inside eventSelected) continue; } @@ -1469,10 +1693,13 @@ struct CorrReso { auto tracks1 = tracks.sliceByCached(o2::aod::track::collisionId, collision1.globalIndex(), this->cache); - if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) { + auto cent1 = getCentrality(collision1); + auto cent2 = getCentrality(collision2); + + if (cfgEvSel.cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) { continue; } - if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) { + if (cfgEvSel.cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) { continue; } @@ -1480,11 +1707,9 @@ struct CorrReso { continue; } - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); int currentRunNumber = bc.runNumber(); - if (!cfgRunRemoveList.value.empty()) { + if (!cfgGeneral.cfgRunRemoveList.value.empty()) { if (!isGoodRun(currentRunNumber)) { // Rejects runs if bad run number continue; } @@ -1492,154 +1717,55 @@ struct CorrReso { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); - float eventWeight = 1.0f; - double multiplicity = static_cast(tracks1.size()); + auto multiplicity1 = static_cast(tracks1.size()); + auto multiplicity2 = static_cast(tracks2.size()); - if (cfgStrictTrackCounter) { - trackCounter(tracks1, multiplicity); + if (cfgEvSel.cfgSelCollByNch && cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks1, multiplicity1); + if (cfgEvSel.cfgUseCol2ForMixedEvSel) { + nchCounter(tracks2, multiplicity2); + } } - if (multiplicity > cfgMaxMultForCorrelations || multiplicity < cfgMinMultForCorrelations) { + if (cfgEvSel.cfgSelCollByNch && (multiplicity1 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity1 < cfgEvSel.cfgMinMultForCorrelations)) { continue; } - - const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(v0s1, ft0, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, kFT0A, eventWeight); - } - } - PROCESS_SWITCH(CorrReso, processMixedTpcFt0a, "Process mixed events for TPC-FT0A correlation", false); - - void processSameTpcFt0c(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, aod::V0Datas const& V0s) - { - registry.fill(HIST("hEventCount"), kFilteredEvents); - - if (cfgQaCheck) { - eventSelectedIndividually(collision); - } - - if (!collision.sel8()) { - return; - } - - registry.fill(HIST("hEventCount"), kAfterSel8); - - if (!eventRct(collision, true)) { - return; - } - - auto bc = collision.bc_as(); - int currentRunNumber = bc.runNumber(); - if (!cfgRunRemoveList.value.empty()) { - if (!isGoodRun(currentRunNumber)) { // Rejects runs if bad run number - return; - } - } - - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) { - return; - } - if (!collision.has_foundFT0()) { - return; - } - loadAlignParam(bc.timestamp()); - loadGain(bc); - loadCorrection(bc.timestamp()); - - registry.fill(HIST("zVtx"), collision.posZ()); - - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - - const auto& ft0 = collision.foundFT0(); - - double multiplicity = static_cast(tracks.size()); - - if (cfgQaCheck) { - registry.fill(HIST("Nch"), multiplicity); - } - - if (cfgStrictTrackCounter) { - trackCounter(tracks, multiplicity); - } - - if (cfgQaCheck) { - registry.fill(HIST("Nch_corrected"), multiplicity); - } - - if (multiplicity > cfgMaxMultForCorrelations || multiplicity < cfgMinMultForCorrelations) { - return; - } - - fillCorrelationsTPCFT0(V0s, ft0, collision.posZ(), collision.posY(), collision.posX(), SameEvent, kFT0C, 1.0f); - } - PROCESS_SWITCH(CorrReso, processSameTpcFt0c, "Process same event for TPC-FT0C correlation", false); - - void processMixedTpcFt0c(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&, aod::V0Datas const& V0s) - { - - auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { - auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); - auto mult = associatedTracks.size(); - return mult; - }; - - using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; - - MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}}; - - auto tracksTuple = std::make_tuple(V0s, tracks); - Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto it = pairs.begin(); it != pairs.end(); it++) { - auto& [collision1, v0s1, collision2, tracks2] = *it; - if (!collision1.sel8() || !collision2.sel8()) { + if (cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (multiplicity2 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity2 < cfgEvSel.cfgMinMultForCorrelations)) { continue; } - - if (!eventRct(collision1, false) || !eventRct(collision2, false)) { + if (!cfgEvSel.cfgSelCollByNch && (cent1 > cfgEvSel.cfgMaxCentForCorrelations || cent1 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - - auto tracks1 = tracks.sliceByCached(o2::aod::track::collisionId, collision1.globalIndex(), this->cache); - - if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) { + if (!cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (cent2 > cfgEvSel.cfgMaxCentForCorrelations || cent2 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) { - continue; - } + histos.fill(HIST("eventcount"), MixedEvent); + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity1 : cent1; - if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) { - continue; - } + float eventWeight = 1.0f; - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); - int currentRunNumber = bc.runNumber(); - if (!cfgRunRemoveList.value.empty()) { - if (!isGoodRun(currentRunNumber)) { // Rejects runs if bad run number - continue; + if (cfgEffWeights.cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + float weightCent = 1.0f; + if (!cfgEvSel.cfgSelCollByNch) { + if (!getCentralityWeight(weightCent, cent1)) { + continue; // or continue in a loop } } - loadAlignParam(bc.timestamp()); - loadCorrection(bc.timestamp()); - float eventWeight = 1.0f; const auto& ft0 = collision2.foundFT0(); - double multiplicity = static_cast(tracks1.size()); - - if (cfgStrictTrackCounter) { - trackCounter(tracks1, multiplicity); + if (cfgGeneral.cfgAnalyzeTPCFT0A) { + fillCorrelationsTPCFT0(v0s1, ft0, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, eventClass, IndexFT0A, eventWeight * weightCent); } - - if (multiplicity > cfgMaxMultForCorrelations || multiplicity < cfgMinMultForCorrelations) { - continue; + if (cfgGeneral.cfgAnalyzeTPCFT0C) { + fillCorrelationsTPCFT0(v0s1, ft0, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, eventClass, IndexFT0C, eventWeight * weightCent); } - - fillCorrelationsTPCFT0(v0s1, ft0, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, kFT0C, eventWeight); } } - PROCESS_SWITCH(CorrReso, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); + PROCESS_SWITCH(CorrReso, processMixedTpcFt0, "Process mixed events for TPC-FT0 correlations", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx index af48e2069a7..9d206b44ad1 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx @@ -14,7 +14,7 @@ /// \author Preet Bhanjan Pati (preet.bhanjan.pati@cern.ch), Zhiyong Lu (zhiyong.lu@cern.ch) /// \since July/29/2025 -#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/TwoParticleCorrelations/Core/DihadronContainer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -71,10 +72,10 @@ using namespace constants::math; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; template -auto readMatrix(Array2D const& mat, P& array, int rowStart, int rowEnd, int colStart, int colEnd) +auto readMatrix(Array2D const& mat, P& array) { - for (auto i = rowStart; i < rowEnd; ++i) { - for (auto j = colStart; j < colEnd; ++j) { + for (auto i = 0; i < static_cast(mat.rows); ++i) { + for (auto j = 0; j < static_cast(mat.cols); ++j) { array[i][j] = mat(i, j); } } @@ -82,57 +83,79 @@ auto readMatrix(Array2D const& mat, P& array, int rowStart, int rowEnd, int c return; } -static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; -static constexpr int LongArrayInt[3][20] = {{1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}, {2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}, {3, 3, 3, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}}; +static constexpr std::array, 20> LongArrayFloat = {{{{1.1, 2.1, 3.1}}, {{1.2, 2.2, 3.2}}, {{1.3, 2.3, 3.3}}, {{-1.1, -2.1, -3.1}}, {{-1.2, -2.2, -3.2}}, {{-1.3, -2.3, -3.3}}, {{1.1, 1.1, 1.1}}, {{1.2, 1.2, 1.2}}, {{1.3, 1.3, 1.3}}, {{-1.1, -1.1, -1.1}}, {{-1.2, -1.2, -1.2}}, {{-1.3, -1.3, -1.3}}, {{1.1, 1.1, 1.1}}, {{1.2, 1.2, 1.2}}, {{1.3, 1.3, 1.3}}, {{-1.1, -1.1, -1.1}}, {{-1.2, -1.2, -1.2}}, {{-1.3, -1.3, -1.3}}, {{1.1, 1.1, 1.1}}, {{1.2, 1.2, 1.2}}}}; +static constexpr std::array, 20> LongArrayInt = {{{{1, 2, 3}}, {{1, 2, 3}}, {{1, 2, 3}}, {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}}, {{1, 1, 1}}, {{1, 1, 1}}, {{1, 1, 1}}, {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}}, {{1, 1, 1}}, {{1, 1, 1}}, {{1, 1, 1}}, {{0, 0, 0}}, {{0, 0, 0}}, {{0, 0, 0}}, {{1, 1, 1}}, {{1, 1, 1}}}}; struct PidDiHadron { o2::aod::ITSResponse itsResponse; Service ccdb; - O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta cut") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgTpcCluster, float, 50.0f, "minimum TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgTpcCrossRows, float, 70.0f, "minimum TPC crossed rows") - O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") - O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") - O2_DEFINE_CONFIGURABLE(cfgITScluster, float, 5.0f, "minimum ITS clusters") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Minimum occupancy cut") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMin, int, 0, "Maximum occupancy cut") - O2_DEFINE_CONFIGURABLE(cfgFakeKaonCut, float, 0.1f, "Maximum difference in measured momentum and TPC inner ring momentum of particle") - O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") - O2_DEFINE_CONFIGURABLE(cfgCutMerging, float, 0.0, "Merging cut on track merge") - O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") - O2_DEFINE_CONFIGURABLE(cfgCutMultMin, int, 0, "Minimum multiplicity for collision") - O2_DEFINE_CONFIGURABLE(cfgCutMultMax, int, 10, "Maximum multiplicity for collision") - O2_DEFINE_CONFIGURABLE(cfgCutCentMin, float, 60.0f, "Minimum centrality for collision") - O2_DEFINE_CONFIGURABLE(cfgCutCentMax, float, 80.0f, "Maximum centrality for collision") - O2_DEFINE_CONFIGURABLE(cfgMixEventNumMin, int, 5, "Minimum number of events to mix") - O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") - O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") - O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") - O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") - O2_DEFINE_CONFIGURABLE(cfgCentTableUnavailable, bool, false, "if a dataset does not provide centrality information") - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") - O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") - O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") - O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") - O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") - O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") - O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") - O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, false, "enable trigger pT < associated pT cut") - O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, false, "enable trigger pT < associated pT cut in mixed event") - O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") - O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") - O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") - O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") - O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get dEdx histograms for pions, kaons, and protons") - O2_DEFINE_CONFIGURABLE(cfgUseAntiLambda, bool, true, "Use AntiLambda candidates for analysis") - O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgQABasic, bool, true, "Enable QA histograms for event and track selection") + O2_DEFINE_CONFIGURABLE(cfgStrictTrackCounter, bool, false, "Strict track counter for multiplicity correlation cut, counts only tracks that pass all cuts and are used in the correlation") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, int, 10, "Sample size for mixed event") + O2_DEFINE_CONFIGURABLE(cfgAsscPtMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgAsscPtMax, float, 3.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutMerging, float, 0.0, "Merging cut on track merge") + O2_DEFINE_CONFIGURABLE(cfgUseCutMerging, bool, false, "use two track cut"); + O2_DEFINE_CONFIGURABLE(cfgMixEventNumMin, int, 5, "Minimum number of events to mix") + O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, false, "enable trigger pT < associated pT cut") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, false, "enable trigger pT < associated pT cut in mixed event") + } cfgGeneral; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyNch, std::string, "", "CCDB path to multiplicity dependent efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiencyNch, bool, false, "Use local multiplicity dependent efficiency object"); + O2_DEFINE_CONFIGURABLE(cfgUseTrigWeight, bool, false, "enable trigger efficiency correction") + } cfgEffWeights; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgGlobalCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Maximum occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMin, int, 0, "Minimum occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, true, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgCutMultMin, int, 0, "Minimum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgCutMultMax, int, 10, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgCentTableUnavailable, bool, false, "if a dataset does not provide centrality information") + O2_DEFINE_CONFIGURABLE(cfgCutCentMin, float, 60.0f, "Minimum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgCutCentMax, float, 80.0f, "Maximum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgUseCol2ForMixedEvSel, bool, true, "Use Mult/Cent cut on collision 2 during mixed event"); + Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt.front().data(), 14, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kIsGoodITSLayer0123", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; + } cfgEvSel; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgGlobalPtMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgGlobalPtMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgGlobalEta, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgGlobalChi2prTPCcls, float, 2.5f, "Maximum chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgGlobalDCAz, float, 2.0f, "Maximum DCA to vertex z") + Configurable> cfgTrackCutsDCAxy{"cfgTrackCutsDCAxy", std::vector{"[0]*(0.0026+0.005/(x^1.01))", "[0]*(0.0026+0.005/(x^1.01))"}, "Functional form of pt-dependent DCAxy cut"}; + Configurable> cfgTrackCutsDCAz{"cfgTrackCutsDCAz", std::vector{"", ""}, "Functional form of pt-dependent DCAz cut"}; + Configurable> cfgTrackCuts{"cfgTrackCuts", {LongArrayFloat.front().data(), 10, 2, {"PtMin", "PtMax", "EtaCut", "Chi2PrTpcCls", "TpcCluster", "TpcCrossedRows", "ItsCluster", "DCAz", "DCAzNsigma", "DCAxyNsigma"}, {"General", "SelNch"}}, "Labeled array for track selections"}; + } cfgTrkSel; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgQAdEdx, bool, false, "Get dEdx histograms for pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgQANsigma, bool, false, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgPIDTofPtCut, float, 0.4f, "Minimum pt to use TOF N-sigma") + O2_DEFINE_CONFIGURABLE(cfgPIDUseIts, bool, false, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") + O2_DEFINE_CONFIGURABLE(cfgPIDOnlyTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgPIDUseOnlyTpc, bool, true, "Use only TPC PID for daughter selection") + O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 0 for no PID") + O2_DEFINE_CONFIGURABLE(cfgPIDUseReso, bool, false, "Switch to turn on resonance analysis") + Configurable> cfgPIDnSigmas{"cfgPIDnSigmas", {LongArrayFloat.front().data(), 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + Configurable> cfgPIDResoCuts{"cfgPIDResoCuts", {LongArrayFloat.front().data(), 15, 2, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "RapidityMin", "RapidityMax", "ArmPodMinVal", "DCABetDaug", "CompMassRej"}, {"K0", "Lambda"}}, "Labeled array (float) for various cuts on resonances"}; + Configurable> cfgPIDResoSwitches{"cfgPIDResoSwitches", {LongArrayInt.front().data(), 7, 2, {"UseCosPA", "NMassBins", "UseDCABetDaug", "UseProperLifetime", "UseV0Radius", "UseArmPodCut", "UseCompMassRej"}, {"K0", "Lambda"}}, "Labeled array (int) for various cuts on resonances"}; + } cfgPIDConfigs; struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -149,208 +172,224 @@ struct PidDiHadron { O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; - O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); - O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); std::vector multT0CCutPars; std::vector multPVT0CCutPars; std::vector multGlobalPVCutPars; std::vector multMultV0ACutPars; - TF1* fMultPVT0CCutLow = nullptr; - TF1* fMultPVT0CCutHigh = nullptr; - TF1* fMultT0CCutLow = nullptr; - TF1* fMultT0CCutHigh = nullptr; - TF1* fMultGlobalPVCutLow = nullptr; - TF1* fMultGlobalPVCutHigh = nullptr; - TF1* fMultMultV0ACutLow = nullptr; - TF1* fMultMultV0ACutHigh = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; - TF1* fPtDepDCAxy = nullptr; + std::unique_ptr fMultPVT0CCutLow = nullptr; + std::unique_ptr fMultPVT0CCutHigh = nullptr; + std::unique_ptr fMultT0CCutLow = nullptr; + std::unique_ptr fMultT0CCutHigh = nullptr; + std::unique_ptr fMultGlobalPVCutLow = nullptr; + std::unique_ptr fMultGlobalPVCutHigh = nullptr; + std::unique_ptr fMultMultV0ACutLow = nullptr; + std::unique_ptr fMultMultV0ACutHigh = nullptr; + std::unique_ptr fT0AV0AMean = nullptr; + std::unique_ptr fT0AV0ASigma = nullptr; + std::unique_ptr fPtDepDCAxy = nullptr; + std::unique_ptr fPtDepDCAxyForNch = nullptr; + std::unique_ptr fPtDepDCAz = nullptr; + std::unique_ptr fPtDepDCAzForNch = nullptr; + O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") } cfgFuncParas; SliceCache cache; + // Axes for general QA ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity axis for histograms"}; - ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "centrality axis for histograms"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {100, 0, 1000}, "multiplicity axis for histograms"}; + ConfigurableAxis axisCentrality{"axisCentrality", {100, 0, 100}, "centrality axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {98, 0.2, 10.0}, "pt axis for histograms"}; + + // Axes for Correlations + ConfigurableAxis axisMultForCorr{"axisMultForCorr", {VARIABLE_WIDTH, 0, 5, 10, 20, 50, 100, 150, 200, 300, 500}, "multiplicity axis for correlation histograms"}; + ConfigurableAxis axisCentForCorr{"axisCentForCorr", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "centrality axis for correlation histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {48, -2.4, 2.4}, "delta eta axis for histograms"}; ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; - ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt associated axis for histograms"}; + ConfigurableAxis axisParticle{"axisParticle", {4, 0, 4}, "particle axis for correlation container"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity / centrality axis for mixed event histograms"}; - ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; + + // Axes for PID QA ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; ConfigurableAxis axisTpcSignal{"axisTpcSignal", {250, 0, 250}, "dEdx axis for TPC"}; ConfigurableAxis axisSigma{"axisSigma", {200, 0, 20}, "sigma axis for TPC"}; - Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt[0], 15, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut", "kIsVertexITSTPC", "kTVXinTRD"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; - Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; - Configurable> resonanceCuts{"resonanceCuts", {LongArrayFloat[0], 12, 3, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "Rapidity", "ArmPodMinVal"}, {"K0", "Lambda", "Phi"}}, "Labeled array (float) for various cuts on resonances"}; - Configurable> resonanceSwitches{"resonanceSwitches", {LongArrayInt[0], 6, 3, {"UseCosPA", "NMassBins", "DCABetDaug", "UseProperLifetime", "UseV0Radius", "UseArmPodCut"}, {"K0", "Lambda", "Phi"}}, "Labeled array (int) for various cuts on resonances"}; - - ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {1, 0, 1}, "vertex axis for efficiency histograms"}; - ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {1, 0, 1}, "eta axis for efficiency histograms"}; - ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {1, 0, 1}, "pt axis for efficiency histograms"}; - // make the filters and cuts. - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVertex); - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgEvSel.cfgGlobalCutVertex); + Filter trackFilter = (nabs(aod::track::eta) < cfgTrkSel.cfgGlobalEta) && (aod::track::pt > cfgTrkSel.cfgGlobalPtMin) && (aod::track::pt < cfgTrkSel.cfgGlobalPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgTrkSel.cfgGlobalChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgTrkSel.cfgGlobalDCAz); using FilteredCollisions = soa::Filtered>; using FilteredTracks = soa::Filtered>; using FilteredMcTracks = soa::Filtered>; using V0TrackCandidate = aod::V0Datas; + Partition asscTracks = (aod::track::pt > cfgGeneral.cfgAsscPtMin) && (aod::track::pt < cfgGeneral.cfgAsscPtMax); + Preslice perCollision = aod::track::collisionId; Preslice perCollisionV0 = aod::v0::collisionId; // Corrections TH3D* mEfficiency = nullptr; + TH1D* mEfficiencyNch = nullptr; TH1D* mCentralityWeight = nullptr; bool correctionsLoaded = false; // Define the outputs - OutputObj same{"sameEvent"}; - OutputObj mixed{"mixedEvent"}; - OutputObj sameReso{"sameEventReso"}; - OutputObj mixedReso{"mixedEventReso"}; + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + OutputObj sameReso{"sameEventReso"}; + OutputObj mixedReso{"mixedEventReso"}; HistogramRegistry histos{"histos"}; // define global variables - TRandom3* gRandom = new TRandom3(); + TRandom3 fRandom{0}; enum PIDIndex { - kCharged = 0, - kPions, - kKaons, - kProtons, - kK0, - kLambda, - kPhi + UseCharged = 0, + UsePions, + UseKaons, + UseProtons, + UseK0, + UseLambda }; enum PiKpArrayIndex { - iPionUp = 0, - iKaonUp, - iProtonUp, - iPionLow, - iKaonLow, - iProtonLow + IndexPionUp = 0, + IndexKaonUp, + IndexProtonUp, + IndexPionLow, + IndexKaonLow, + IndexProtonLow }; enum ResoArrayIndex { - iK0 = 0, - iLambda = 1, - iPhi = 2, - NResoParticles = 3 + IndexK0 = 0, + IndexLambda, + NumResoParticles }; enum ResoParticleCuts { - kCosPA = 0, - kMassMin, - kMassMax, - kPosTrackPt, - kNegTrackPt, - kDCAPosToPVMin, - kDCANegToPVMin, - kLifeTime, - kRadiusMin, - kRadiusMax, - kRapidity, - kArmPodMinVal, - kNParticleCuts + CutCosPA = 0, + CutMassMin, + CutMassMax, + CutPosTrackPt, + CutNegTrackPt, + CutDCAPosToPVMin, + CutDCANegToPVMin, + CutLifeTime, + CutRadiusMin, + CutRadiusMax, + CutRapidityMin, + CutRapidityMax, + CutArmPodMinVal, + CutDCABetDaug, + CutCompMassRej, + NumParticleCuts }; enum ResoParticleSwitches { - kUseCosPA = 0, - kMassBins, - kDCABetDaug, - kUseProperLifetime, - kUseV0Radius, - kUseArmPodCut, - kNParticleSwitches + UseCosPA = 0, + UseMassBins, + UseDCABetDaug, + UseProperLifetime, + UseV0Radius, + UseArmPodCut, + UseCompMassRej, + NumParticleSwitches + }; + + enum ResoSelectionFlags { + FillCandidate = 0, + FillDaughterPt, + FillMassCut, + FillRapidityCut, + FillDCAtoPV, + FillDCAxDaughters, + FillV0Radius, + FillCosPA, + FillProperLifetime, + FillArmPodCut, + FillCompetingMass, + FillDaughterTrackSelected, }; + enum EventCutTypes { - kFilteredEvents = 0, - kAfterSel8, - kUseNoTimeFrameBorder, - kUseNoITSROFrameBorder, - kUseNoSameBunchPileup, - kUseGoodZvtxFT0vsPV, - kUseNoCollInTimeRangeStandard, - kUseGoodITSLayersAll, - kUseNoCollInRofStandard, - kUseNoHighMultCollInPrevRof, - kUseOccupancy, - kUseMultCorrCut, - kUseT0AV0ACut, - kUseVertexITSTPC, - kUseTVXinTRD, - kNEventCuts + FilteredEvents = 0, + AfterSel8, + UseNoTimeFrameBorder, + UseNoITSROFrameBorder, + UseNoSameBunchPileup, + UseGoodZvtxFT0vsPV, + UseNoCollInTimeRangeStandard, + UseGoodITSLayersAll, + UseGoodITSLayer0123, + UseNoCollInRofStandard, + UseNoHighMultCollInPrevRof, + UseOccupancy, + UseMultCorrCut, + UseT0AV0ACut, + NumEventCuts + }; + enum TrackCuts { + TrkCutPtMin = 0, + TrkCutPtMax, + TrkCutEtaCut, + TrkCutChi2PrTpcCls, + TrkCutTpcCluster, + TrkCutTpcCrossedRows, + TrkCutItsCluster, + TrkCutDCAz, + TrkCutDCAzNsigma, + TrkCutDCAxyNsigma + }; + + enum TrackCutGroup { + UseGenTrkCuts = 0, + UseNchSelCuts, + NumTrackCutTypes }; enum CentEstimators { - kCentFT0C = 0, - kCentFT0CVariant1, - kCentFT0M, - kCentFV0A, - // Count the total number of enum - kCount_CentEstimators + UseCentFT0C = 0, + UseCentFT0CVariant1, + UseCentFT0M, + UseCentFV0A, + NumCentEstimators }; enum EventType { SameEvent = 1, MixedEvent = 3 }; enum DetectorType { - kTPC = 0, - kTOF, - kITS + UseTPC = 0, + UseTOF, + UseITS }; enum EventCutType { - kEvCut1 = 0, - kNEvCutTypes = 1 + EvCut1 = 0, + NumEvCutTypes = 1 + }; + enum Stage { + Before = 0, + After }; - std::array, 15> eventCuts; - std::array, 12> resoCutVals; - std::array, 7> resoSwitchVals; - std::array tofNsigmaCut; - std::array itsNsigmaCut; - std::array tpcNsigmaCut; - + std::array, 10> trackCuts{}; + std::array, 14> eventCuts{}; + std::array, 6> nSigmaVals{}; + std::array, 15> resoCutVals{}; + std::array, 7> resoSwitchVals{}; // persistent caches std::vector efficiencyAssociatedCache; + std::vector useAssociatedCache; void init(InitContext&) { - readMatrix(resonanceCuts->getData(), resoCutVals, kCosPA, kNParticleCuts, iK0, NResoParticles); - readMatrix(resonanceSwitches->getData(), resoSwitchVals, kUseCosPA, kNParticleSwitches, iK0, NResoParticles); - readMatrix(cfgUseEventCuts->getData(), eventCuts, kFilteredEvents, kNEventCuts, kEvCut1, kNEvCutTypes); - - tpcNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTPC]; - tpcNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTPC]; - tpcNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTPC]; - tpcNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTPC]; - tpcNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTPC]; - tpcNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTPC]; - - tofNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTOF]; - tofNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTOF]; - tofNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTOF]; - tofNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTOF]; - tofNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTOF]; - tofNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTOF]; - - itsNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kITS]; - itsNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kITS]; - itsNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kITS]; - itsNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kITS]; - itsNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kITS]; - itsNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kITS]; - - AxisSpec axisK0Mass = {resoSwitchVals[kMassBins][iK0], resoCutVals[kMassMin][iK0], resoCutVals[kMassMax][iK0]}; - AxisSpec axisLambdaMass = {resoSwitchVals[kMassBins][iLambda], resoCutVals[kMassMin][iLambda], resoCutVals[kMassMax][iLambda]}; - AxisSpec axisPhiMass = {resoSwitchVals[kMassBins][iPhi], resoCutVals[kMassMin][iPhi], resoCutVals[kMassMax][iPhi]}; - - if (cfgCentTableUnavailable && !cfgSelCollByNch) { + readMatrix(cfgTrkSel.cfgTrackCuts->getData(), trackCuts); + readMatrix(cfgEvSel.cfgUseEventCuts->getData(), eventCuts); + readMatrix(cfgPIDConfigs.cfgPIDnSigmas->getData(), nSigmaVals); + readMatrix(cfgPIDConfigs.cfgPIDResoCuts->getData(), resoCutVals); + readMatrix(cfgPIDConfigs.cfgPIDResoSwitches->getData(), resoSwitchVals); + + if (cfgEvSel.cfgCentTableUnavailable && !cfgEvSel.cfgSelCollByNch) { LOGF(fatal, "Centrality table is unavailable, cannot select collisions by centrality"); } const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; @@ -363,238 +402,263 @@ struct PidDiHadron { LOGF(info, "Starting init"); - // Creating mass axis depending on particle - 4 = kshort, 5 = lambda, 6 = phi - AxisSpec massAxisReso = {10, 0, 1, "mass"}; - if (cfgPIDParticle == kK0) - massAxisReso = {resoSwitchVals[kMassBins][iK0], resoCutVals[kMassMin][iK0], resoCutVals[kMassMax][iK0], "M_{#pi^{+}#pi^{-}} (GeV/c^{2})"}; - if (cfgPIDParticle == kLambda) - massAxisReso = {resoSwitchVals[kMassBins][iLambda], resoCutVals[kMassMin][iLambda], resoCutVals[kMassMax][iLambda], "M_{p#pi^{-}} (GeV/c^{2})"}; - if (cfgPIDParticle == kPhi) - massAxisReso = {resoSwitchVals[kMassBins][iPhi], resoCutVals[kMassMin][iPhi], resoCutVals[kMassMax][iPhi], "M_{K^{+}K^{-}} (GeV/c^{2})"}; + // Creating mass axis depending on particle - 4 = kshort, 5 = lambda + AxisSpec axisInvMass = {10, 0, 1, "mass"}; + if (cfgPIDConfigs.cfgPIDParticle == UseK0) { + const auto bins = resoSwitchVals[UseMassBins][IndexK0]; + const auto min = resoCutVals[CutMassMin][IndexK0]; + const auto max = resoCutVals[CutMassMax][IndexK0]; + + axisInvMass = {bins, min, max, "M_{#pi^{+}#pi^{-}} (GeV/c^{2})"}; + } + if (cfgPIDConfigs.cfgPIDParticle == UseLambda) { + const auto bins = resoSwitchVals[UseMassBins][IndexLambda]; + const auto min = resoCutVals[CutMassMin][IndexLambda]; + const auto max = resoCutVals[CutMassMax][IndexLambda]; + + axisInvMass = {bins, min, max, "M_{p#pi} (GeV/c^{2})"}; + } + + // Set the sample axis + auto maxSample = static_cast(cfgGeneral.cfgSampleSize); + AxisSpec axisSample{cfgGeneral.cfgSampleSize, 0, maxSample, "Sample"}; + + // Choose if it is Nch selection or Centrality selection + AxisSpec axisEventClass = {axisMultForCorr, "N_{ch}"}; + + if (!cfgEvSel.cfgSelCollByNch) { + axisEventClass = {axisCentForCorr, "Centrality"}; + } // Event Counter - if ((doprocessSame || doprocessSameReso || doprocessMC) && cfgUseAdditionalEventCut) { + if ((doprocessSame || doprocessSameReso || doprocessMC) && cfgEvSel.cfgUseAdditionalEventCut) { histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered event"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "MultCorrelation Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseVertexITSTPC + 1, "kIsVertexITSTPC"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseTVXinTRD + 1, "kTVXinTRD"); - } - - if (cfgPIDParticle == kK0) { // For K0 - histos.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); - histos.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(FilteredEvents + 1, "Filtered events"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(AfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseGoodITSLayer0123 + 1, "kIsGoodITSLayer0123"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseMultCorrCut + 1, "MultCorrelation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(UseT0AV0ACut + 1, "T0AV0A cut"); + } + + if (cfgPIDConfigs.cfgPIDUseReso && cfgPIDConfigs.cfgPIDParticle == UseK0) { // For K0 + histos.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTOF}}}); histos.add("hK0Phi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hK0Eta", "", {HistType::kTH1D, {axisEta}}); - histos.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{11, 0, 11}}}); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(1, "K0 candidates"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(3, "Mass cut"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(4, "Rapidity cut"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(5, "DCA to PV"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(6, "DCA between daughters"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(7, "V0radius"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(8, "CosPA"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(10, "ArmenterosPod"); - histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(11, "Daughter track selection"); - } - if (cfgPIDParticle == kLambda) { // For Lambda - histos.add("PrPlusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("PiMinusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("PrPlusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); - histos.add("PiMinusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCandidate + 1, "K0 candidates"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterPt + 1, "Daughter pt"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillMassCut + 1, "Mass cut"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillRapidityCut + 1, "Rapidity cut"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDCAtoPV + 1, "DCA to PV"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDCAxDaughters + 1, "DCA between daughters"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillV0Radius + 1, "V0radius"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCosPA + 1, "CosPA"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillProperLifetime + 1, "Proper lifetime"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillArmPodCut + 1, "ArmenterosPod"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillCompetingMass + 1, "CompetingMassRejection"); + histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected + 1, "Daughter track selection"); + } + if (cfgPIDConfigs.cfgPIDUseReso && cfgPIDConfigs.cfgPIDParticle == UseLambda) { // For Lambda + histos.add("PrPlusTPC_L", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_L", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTPC}}}); + histos.add("PrPlusTOF_L", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_L", "", {HistType::kTH2D, {{axisPtTrigger, axisNsigmaTOF}}}); histos.add("hLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hLambdaEta", "", {HistType::kTH1D, {axisEta}}); - histos.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(1, "Lambda candidates"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(3, "Mass cut"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(4, "Rapidity cut"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(5, "DCA to PV"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(6, "DCA between daughters"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(7, "V0radius"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(8, "CosPA"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); - histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); - } - if (cfgPIDParticle == kPhi) { // For Phi - histos.add("KaPlusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("KaMinusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); - histos.add("KaPlusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); - histos.add("KaMinusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); - histos.add("hPhiPhi", "", {HistType::kTH1D, {axisPhi}}); - histos.add("hPhiEta", "", {HistType::kTH1D, {axisEta}}); - histos.add("hPhiMass_sparse", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); - - histos.add("hPhiCount", "Number of Phi;; Count", {HistType::kTH1D, {{5, 0, 5}}}); - histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(1, "Phi candidates"); - histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(2, "Daughter track selection"); - histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(3, "Fake Kaon"); - histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(4, "CosPA"); - histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(5, "Rapidity cut"); + histos.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{12, -0.5, 11.5}}}); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCandidate + 1, "Lambda candidates"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterPt + 1, "Daughter pt"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillMassCut + 1, "Mass cut"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillRapidityCut + 1, "Rapidity cut"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAtoPV + 1, "DCA to PV"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDCAxDaughters + 1, "DCA between daughters"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillV0Radius + 1, "V0radius"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCosPA + 1, "CosPA"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillProperLifetime + 1, "Proper lifetime"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillArmPodCut + 1, "ArmenterosPod"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillCompetingMass + 1, "CompetingMassRejection"); + histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(FillDaughterTrackSelected + 1, "Daughter track selection"); } // Multiplicity correlation cuts - if (eventCuts[kUseMultCorrCut][kEvCut1]) { + if (eventCuts[UseMultCorrCut][EvCut1]) { cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; cfgFuncParas.multMultV0ACutPars = cfgFuncParas.cfgMultMultV0ACutPars; - cfgFuncParas.fMultPVT0CCutLow = new TF1("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); - cfgFuncParas.fMultPVT0CCutLow->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); - cfgFuncParas.fMultPVT0CCutHigh = new TF1("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); - cfgFuncParas.fMultPVT0CCutHigh->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); - - cfgFuncParas.fMultT0CCutLow = new TF1("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); - cfgFuncParas.fMultT0CCutLow->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); - cfgFuncParas.fMultT0CCutHigh = new TF1("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); - cfgFuncParas.fMultT0CCutHigh->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); - - cfgFuncParas.fMultGlobalPVCutLow = new TF1("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); - cfgFuncParas.fMultGlobalPVCutLow->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); - cfgFuncParas.fMultGlobalPVCutHigh = new TF1("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); - cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); - - cfgFuncParas.fMultMultV0ACutLow = new TF1("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); - cfgFuncParas.fMultMultV0ACutLow->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); - cfgFuncParas.fMultMultV0ACutHigh = new TF1("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); - cfgFuncParas.fMultMultV0ACutHigh->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); - } - if (eventCuts[kUseT0AV0ACut][kEvCut1]) { - cfgFuncParas.fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + + cfgFuncParas.fMultPVT0CCutLow = std::make_unique("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutLow->SetParameters(cfgFuncParas.multPVT0CCutPars.data()); + cfgFuncParas.fMultPVT0CCutHigh = std::make_unique("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutHigh->SetParameters(cfgFuncParas.multPVT0CCutPars.data()); + + cfgFuncParas.fMultT0CCutLow = std::make_unique("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutLow->SetParameters(cfgFuncParas.multT0CCutPars.data()); + cfgFuncParas.fMultT0CCutHigh = std::make_unique("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutHigh->SetParameters(cfgFuncParas.multT0CCutPars.data()); + + cfgFuncParas.fMultGlobalPVCutLow = std::make_unique("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutLow->SetParameters(cfgFuncParas.multGlobalPVCutPars.data()); + cfgFuncParas.fMultGlobalPVCutHigh = std::make_unique("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(cfgFuncParas.multGlobalPVCutPars.data()); + + cfgFuncParas.fMultMultV0ACutLow = std::make_unique("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutLow->SetParameters(cfgFuncParas.multMultV0ACutPars.data()); + cfgFuncParas.fMultMultV0ACutHigh = std::make_unique("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutHigh->SetParameters(cfgFuncParas.multMultV0ACutPars.data()); + } + if (eventCuts[UseT0AV0ACut][EvCut1] != 0) { + cfgFuncParas.fT0AV0AMean = std::make_unique("fT0AV0AMean", "[0]+[1]*x", 0, 200000); cfgFuncParas.fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); - cfgFuncParas.fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + cfgFuncParas.fT0AV0ASigma = std::make_unique("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } - cfgFuncParas.fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgFuncParas.cfgDCAxy->c_str()), 0.001, 100); - cfgFuncParas.fPtDepDCAxy->SetParameter(0, cfgFuncParas.cfgDCAxyNSigma); - LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgFuncParas.cfgDCAxy->c_str())); + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].empty()) { + cfgFuncParas.fPtDepDCAxy = std::make_unique("ptDepDCAxy", cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAxy->SetParameter(0, trackCuts[TrkCutDCAxyNsigma][UseGenTrkCuts]); + LOGF(info, "DCAxy pt-dependence function: %0.1f * %s", trackCuts[TrkCutDCAxyNsigma][UseGenTrkCuts], cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].c_str()); + } + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].empty()) { + cfgFuncParas.fPtDepDCAxyForNch = std::make_unique("ptDepDCAxyForNch", cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAxyForNch->SetParameter(0, trackCuts[TrkCutDCAxyNsigma][UseNchSelCuts]); + LOGF(info, "DCAxy pt-dependence function for Nch: %0.1f * %s", trackCuts[TrkCutDCAxyNsigma][UseNchSelCuts], cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].c_str()); + } + + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].empty()) { + cfgFuncParas.fPtDepDCAz = std::make_unique("ptDepDCAz", cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAz->SetParameter(0, trackCuts[TrkCutDCAzNsigma][UseGenTrkCuts]); + LOGF(info, "DCAz pt-dependence function: %0.1f * %s", trackCuts[TrkCutDCAzNsigma][UseGenTrkCuts], cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].c_str()); + } + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].empty()) { + cfgFuncParas.fPtDepDCAzForNch = std::make_unique("ptDepDCAzForNch", cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].c_str(), 0.001, 1000); + cfgFuncParas.fPtDepDCAzForNch->SetParameter(0, trackCuts[TrkCutDCAzNsigma][UseNchSelCuts]); + LOGF(info, "DCAz pt-dependence function for Nch: %0.1f * %s", trackCuts[TrkCutDCAzNsigma][UseNchSelCuts], cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].c_str()); + } + + std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgEvSel.cfgCentEstimator); - std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); // Make histograms to check the distributions after cuts if (doprocessSame || doprocessSameReso) { - histos.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution histos.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); - histos.add("Nch_used", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + histos.add("Nch_corrected", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); histos.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); histos.add("CentralityWeighted", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); - histos.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // histogram to see how many events are in the same and mixed event histos.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); - histos.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); - - if (cfgPIDParticle == kCharged || cfgPIDParticle == kPions || cfgPIDParticle == kKaons || cfgPIDParticle == kProtons) { - histos.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); - histos.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); - histos.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); - histos.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); - histos.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPtTrigger}}); - histos.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); - - if (cfgGetNsigmaQA) { - if (!cfgUseItsPID) { - histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - - if (cfgGetdEdx) { - histos.add("TpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpTpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpSigma_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); - - histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpTpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpSigma_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); - } - } // TPC-TOF PID QA hists - if (cfgUseItsPID) { - histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); - histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); - } // ITS-TOF PID QA hists - } // end of PID QA hists + histos.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + } + + if (doprocessSame) { + if (cfgGeneral.cfgQABasic) { + histos.add("Phi", "Phi", {HistType::kTH2D, {axisPhi, axisParticle}}); + histos.add("Eta", "Eta", {HistType::kTH2D, {axisEta, axisParticle}}); + histos.add("EtaCorrected", "EtaCorrected", {HistType::kTH2D, {axisEta, axisParticle}}); + histos.add("pTFiner", "pTFiner", {HistType::kTHnSparseF, {axisPt, axisParticle, axisEventClass}}); + histos.add("pTFinerCorrected", "pTFinerCorrected", {HistType::kTHnSparseF, {axisPt, axisParticle, axisEventClass}}); } - if (cfgPIDParticle == kK0 || cfgPIDParticle == kLambda || cfgPIDParticle == kPhi) { - histos.add("Trig_histReso", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger, massAxisReso}}}); + if (cfgPIDConfigs.cfgQANsigma) { + if (!cfgPIDConfigs.cfgPIDUseIts) { // TPC-TOF PID QA hists + histos.add("TofTpcNsigma_beforeCut", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPtTrigger, axisParticle}}}); + histos.add("TofTpcNsigma_afterCut", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPtTrigger, axisParticle}}}); + } + if (cfgPIDConfigs.cfgPIDUseIts) { // ITS-TOF PID QA hists + histos.add("TofItsNsigma_beforeCut", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPtTrigger, axisParticle}}}); + histos.add("TofItsNsigma_afterCut", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPtTrigger, axisParticle}}}); + } + } // end of PID nsigma QA hists + if (cfgPIDConfigs.cfgQAdEdx) { + histos.add("TpcdEdx_ptwise_beforeCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF, axisParticle}}}); + histos.add("ExpTpcdEdx_ptwise_beforeCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF, axisParticle}}}); + histos.add("ExpSigma_ptwise_beforeCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisSigma, axisNsigmaTOF, axisParticle}}}); + + histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF, axisParticle}}}); + histos.add("ExpTpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF, axisParticle}}}); + histos.add("ExpSigma_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisSigma, axisNsigmaTOF, axisParticle}}}); + } // end of PID dEdx QA hists + + // Trigger histogram + histos.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEventClass, axisPtTrigger, axisParticle}}}); + } + + if (doprocessSameReso) { + if (cfgPIDConfigs.cfgPIDParticle == UseK0 || cfgPIDConfigs.cfgPIDParticle == UseLambda) { + histos.add("Trig_histReso", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEventClass, axisPtTrigger, axisInvMass}}}); } } + if (doprocessMixed || doprocessMixedReso) { histos.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); } if (doprocessMC) { - histos.add("hNsigmaPionTruePositives", "hNsigmaPionTruePositives", {HistType::kTH1D, {axisPt}}); // Fraction of particles that are pions and selected as pions - histos.add("hNsigmaKaonTruePositives", "hNsigmaKaonTruePositives", {HistType::kTH1D, {axisPt}}); // Fraction of particles that are kaons and selected as kaons - histos.add("hNsigmaProtonTruePositives", "hNsigmaProtonTruePositives", {HistType::kTH1D, {axisPt}}); // Fraction of particles that are protons and selected as protons + histos.add("hNsigmaPionTruePositives", "hNsigmaPionTruePositives", {HistType::kTH1D, {axisPtTrigger}}); // Fraction of particles that are pions and selected as pions + histos.add("hNsigmaKaonTruePositives", "hNsigmaKaonTruePositives", {HistType::kTH1D, {axisPtTrigger}}); // Fraction of particles that are kaons and selected as kaons + histos.add("hNsigmaProtonTruePositives", "hNsigmaProtonTruePositives", {HistType::kTH1D, {axisPtTrigger}}); // Fraction of particles that are protons and selected as protons - histos.add("hNsigmaPionSelected", "hNsigmaPionSelected", {HistType::kTH1D, {axisPt}}); - histos.add("hNsigmaKaonSelected", "hNsigmaKaonSelected", {HistType::kTH1D, {axisPt}}); - histos.add("hNsigmaProtonSelected", "hNsigmaProtonSelected", {HistType::kTH1D, {axisPt}}); + histos.add("hNsigmaPionSelected", "hNsigmaPionSelected", {HistType::kTH1D, {axisPtTrigger}}); + histos.add("hNsigmaKaonSelected", "hNsigmaKaonSelected", {HistType::kTH1D, {axisPtTrigger}}); + histos.add("hNsigmaProtonSelected", "hNsigmaProtonSelected", {HistType::kTH1D, {axisPtTrigger}}); - histos.add("hNsigmaPionTrue", "hNsigmaPionTrue", {HistType::kTH1D, {axisPt}}); // All true pions from MC - histos.add("hNsigmaKaonTrue", "hNsigmaKaonTrue", {HistType::kTH1D, {axisPt}}); // All true kaons from MC - histos.add("hNsigmaProtonTrue", "hNsigmaProtonTrue", {HistType::kTH1D, {axisPt}}); // All true protons from MC + histos.add("hNsigmaPionTrue", "hNsigmaPionTrue", {HistType::kTH1D, {axisPtTrigger}}); // All true pions from MC + histos.add("hNsigmaKaonTrue", "hNsigmaKaonTrue", {HistType::kTH1D, {axisPtTrigger}}); // All true kaons from MC + histos.add("hNsigmaProtonTrue", "hNsigmaProtonTrue", {HistType::kTH1D, {axisPtTrigger}}); // All true protons from MC - histos.add("TpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpTpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpTpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("ExpTpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_pi_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_ka_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_pr_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pi_physprim", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka_physprim", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr_physprim", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); - histos.add("TpcdEdx_ptwise_all_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_all_physprim", "", {HistType::kTHnSparseD, {{axisPtTrigger, axisTpcSignal, axisNsigmaTOF}}}); } histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event LOGF(info, "Initializing correlation container"); - std::vector corrAxis = {{axisSample, "Sample"}, + std::vector corrAxis = {{axisSample}, {axisVertex, "z-vtx (cm)"}, + {axisEventClass}, {axisPtTrigger, "p_{T} (GeV/c)"}, - {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisParticle, "Particle, 0 = charged, 1 = pion, 2 = kaon, 3 = proton"}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEta, "#Delta#eta"}}; - std::vector corrAxisReso = {{axisSample, "Sample"}, + std::vector corrAxisReso = {{axisSample}, {axisVertex, "z-vtx (cm)"}, + {axisEventClass}, {axisPtTrigger, "p_{T} (GeV/c)"}, - {massAxisReso}, + {axisInvMass}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEta, "#Delta#eta"}}; - std::vector effAxis = { - {axisEtaEfficiency, "#eta"}, - {axisPtEfficiency, "p_{T} (GeV/c)"}, - {axisVertexEfficiency, "z-vtx (cm)"}, - }; - std::vector userAxis; - if (cfgPIDParticle == kCharged || cfgPIDParticle == kPions || cfgPIDParticle == kKaons || cfgPIDParticle == kProtons) { - same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + if (!cfgPIDConfigs.cfgPIDUseReso) { + same.setObject(new DihadronContainer("sameEvent", "sameEvent", corrAxis)); + mixed.setObject(new DihadronContainer("mixedEvent", "mixedEvent", corrAxis)); } - if (cfgPIDParticle == kK0 || cfgPIDParticle == kLambda || cfgPIDParticle == kPhi) { - sameReso.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxisReso, effAxis, userAxis)); - mixedReso.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxisReso, effAxis, userAxis)); + if (cfgPIDConfigs.cfgPIDUseReso && (cfgPIDConfigs.cfgPIDParticle == UseK0 || cfgPIDConfigs.cfgPIDParticle == UseLambda)) { + sameReso.setObject(new DihadronContainer("sameEvent", "sameEvent", corrAxisReso)); + mixedReso.setObject(new DihadronContainer("mixedEvent", "mixedEvent", corrAxisReso)); } LOGF(info, "End of init"); } @@ -618,17 +682,17 @@ struct PidDiHadron { float getCentrality(TCollision const& collision) { float cent; - switch (cfgCentEstimator) { - case kCentFT0C: + switch (cfgEvSel.cfgCentEstimator) { + case UseCentFT0C: cent = collision.centFT0C(); break; - case kCentFT0CVariant1: + case UseCentFT0CVariant1: cent = collision.centFT0CVariant1(); break; - case kCentFT0M: + case UseCentFT0M: cent = collision.centFT0M(); break; - case kCentFV0A: + case UseCentFV0A: cent = collision.centFV0A(); break; default: @@ -638,32 +702,69 @@ struct PidDiHadron { } template - bool trackSelected(const TTrack& track) + bool trackSelected(TTrack const& track) { - if (cfgFuncParas.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt()))) + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseGenTrkCuts].empty() && std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt())) { return false; - return ((track.tpcNClsFound() >= cfgTpcCluster) && (track.tpcNClsCrossedRows() >= cfgTpcCrossRows) && (track.itsNCls() >= cfgITScluster)); + } + + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseGenTrkCuts].empty()) { + if (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAz->Eval(track.pt())) { + return false; + } + } else { + if (std::fabs(track.dcaZ()) > trackCuts[TrkCutDCAz][UseGenTrkCuts]) { + return false; + } + } + + return ((track.pt() > trackCuts[TrkCutPtMin][UseGenTrkCuts]) && (track.pt() < trackCuts[TrkCutPtMax][UseGenTrkCuts]) && (std::abs(track.eta()) < trackCuts[TrkCutEtaCut][UseGenTrkCuts]) && (track.tpcChi2NCl() < trackCuts[TrkCutChi2PrTpcCls][UseGenTrkCuts]) && (track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseGenTrkCuts]) && (track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseGenTrkCuts]) && (track.itsNCls() >= trackCuts[TrkCutItsCluster][UseGenTrkCuts])); + } + + template + bool trackSelectedForNch(TTrack const& track) + { + if (!cfgTrkSel.cfgTrackCutsDCAxy.value[UseNchSelCuts].empty() && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxyForNch->Eval(track.pt()))) { + return false; + } + if (!cfgTrkSel.cfgTrackCutsDCAz.value[UseNchSelCuts].empty()) { + if (std::fabs(track.dcaZ()) > cfgFuncParas.fPtDepDCAzForNch->Eval(track.pt())) { + return false; + } + } else { + if (std::fabs(track.dcaZ()) > trackCuts[TrkCutDCAz][UseNchSelCuts]) { + return false; + } + } + return ((track.pt() > trackCuts[TrkCutPtMin][UseNchSelCuts]) && (track.pt() < trackCuts[TrkCutPtMax][UseNchSelCuts]) && (std::abs(track.eta()) < trackCuts[TrkCutEtaCut][UseNchSelCuts]) && (track.tpcChi2NCl() < trackCuts[TrkCutChi2PrTpcCls][UseNchSelCuts]) && (track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseNchSelCuts]) && (track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseNchSelCuts]) && (track.itsNCls() >= trackCuts[TrkCutItsCluster][UseNchSelCuts])); } template bool selectionV0Daughter(TTrack const& track, int pid) { - if (!(track.itsNCls() > cfgITScluster)) - return 0; - if (!track.hasTPC()) + if (!(track.itsNCls() >= trackCuts[TrkCutItsCluster][UseGenTrkCuts])) { return false; - if (track.tpcNClsFound() < cfgTpcCluster) + } + if (!track.hasTPC()) { return false; - if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) - return 0; + } + if (!(track.tpcNClsFound() >= trackCuts[TrkCutTpcCluster][UseGenTrkCuts])) { + return false; + } + if (!(track.tpcNClsCrossedRows() >= trackCuts[TrkCutTpcCrossedRows][UseGenTrkCuts])) { + return false; + } - if (cfgUseOnlyTPC) { - if (pid == kPions && std::abs(track.tpcNSigmaPi()) > cfgTpcCut) + if (cfgPIDConfigs.cfgPIDUseOnlyTpc) { + if (pid == UsePions && std::abs(track.tpcNSigmaPi()) > cfgPIDConfigs.cfgPIDOnlyTpcCut) { return false; - if (pid == kKaons && std::abs(track.tpcNSigmaKa()) > cfgTpcCut) + } + if (pid == UseKaons && std::abs(track.tpcNSigmaKa()) > cfgPIDConfigs.cfgPIDOnlyTpcCut) { return false; - if (pid == kProtons && std::abs(track.tpcNSigmaPr()) > cfgTpcCut) + } + if (pid == UseProtons && std::abs(track.tpcNSigmaPr()) > cfgPIDConfigs.cfgPIDOnlyTpcCut) { return false; + } } else { int partIndex = getNsigmaPID(track); int pidIndex = partIndex; // 1 = pion, 2 = kaon, 3 = proton @@ -683,21 +784,31 @@ struct PidDiHadron { std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; int pid = -1; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton - std::array nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS - std::array detectorNsigmaCut = cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS - - bool isPion, isKaon, isProton; - bool isDetectedPion = nSigmaToUse[iPionUp] < detectorNsigmaCut[iPionUp] && nSigmaToUse[iPionUp] > detectorNsigmaCut[iPionLow]; - bool isDetectedKaon = nSigmaToUse[iKaonUp] < detectorNsigmaCut[iKaonUp] && nSigmaToUse[iKaonUp] > detectorNsigmaCut[iKaonLow]; - bool isDetectedProton = nSigmaToUse[iProtonUp] < detectorNsigmaCut[iProtonUp] && nSigmaToUse[iProtonUp] > detectorNsigmaCut[iProtonLow]; - - bool isTofPion = nSigmaTOF[iPionUp] < tofNsigmaCut[iPionUp] && nSigmaTOF[iPionUp] > tofNsigmaCut[iPionLow]; - bool isTofKaon = nSigmaTOF[iKaonUp] < tofNsigmaCut[iKaonUp] && nSigmaTOF[iKaonUp] > tofNsigmaCut[iKaonLow]; - bool isTofProton = nSigmaTOF[iProtonUp] < tofNsigmaCut[iProtonUp] && nSigmaTOF[iProtonUp] > tofNsigmaCut[iProtonLow]; - - if (track.pt() > cfgTofPtCut && !track.hasTOF()) { + std::array nSigmaToUse = cfgPIDConfigs.cfgPIDUseIts ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + int useIndexDetector = UseTPC; + useIndexDetector = cfgPIDConfigs.cfgPIDUseIts ? UseITS : UseTPC; // Choose which nSigma to use: TPC or ITS + + bool isPion = false; + bool isKaon = false; + bool isProton = false; + bool isDetectedPion = false; + bool isDetectedKaon = false; + bool isDetectedProton = false; + bool isTofPion = false; + bool isTofKaon = false; + bool isTofProton = false; + + isDetectedPion = nSigmaToUse[IndexPionUp] < nSigmaVals[IndexPionUp][useIndexDetector] && nSigmaToUse[IndexPionUp] > nSigmaVals[IndexPionLow][useIndexDetector]; + isDetectedKaon = nSigmaToUse[IndexKaonUp] < nSigmaVals[IndexKaonUp][useIndexDetector] && nSigmaToUse[IndexKaonUp] > nSigmaVals[IndexKaonLow][useIndexDetector]; + isDetectedProton = nSigmaToUse[IndexProtonUp] < nSigmaVals[IndexProtonUp][useIndexDetector] && nSigmaToUse[IndexProtonUp] > nSigmaVals[IndexProtonLow][useIndexDetector]; + + isTofPion = nSigmaTOF[IndexPionUp] < nSigmaVals[IndexPionUp][UseTOF] && nSigmaTOF[IndexPionUp] > nSigmaVals[IndexPionLow][UseTOF]; + isTofKaon = nSigmaTOF[IndexKaonUp] < nSigmaVals[IndexKaonUp][UseTOF] && nSigmaTOF[IndexKaonUp] > nSigmaVals[IndexKaonLow][UseTOF]; + isTofProton = nSigmaTOF[IndexProtonUp] < nSigmaVals[IndexProtonUp][UseTOF] && nSigmaTOF[IndexProtonUp] > nSigmaVals[IndexProtonLow][UseTOF]; + + if (track.pt() > cfgPIDConfigs.cfgPIDTofPtCut && !track.hasTOF()) { return -1; - } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { + } else if (track.pt() > cfgPIDConfigs.cfgPIDTofPtCut && track.hasTOF()) { isPion = isTofPion && isDetectedPion; isKaon = isTofKaon && isDetectedKaon; isProton = isTofProton && isDetectedProton; @@ -707,16 +818,16 @@ struct PidDiHadron { isProton = isDetectedProton; } - if (cfgPIDUseRejection && ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton))) { + if (cfgPIDConfigs.cfgPIDUseRejection && ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton))) { return -1; // more than one particle satisfy the criteria } if (isPion) { - pid = kPions; + pid = UsePions; } else if (isKaon) { - pid = kKaons; + pid = UseKaons; } else if (isProton) { - pid = kProtons; + pid = UseProtons; } else { return -1; // no particle satisfies the criteria } @@ -729,29 +840,60 @@ struct PidDiHadron { if (correctionsLoaded) { return; } - if (cfgEfficiency.value.empty() == false) { - if (cfgLocalEfficiency > 0) { - TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); - mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + if (!cfgEffWeights.cfgEfficiency.value.empty()) { + if (cfgEffWeights.cfgLocalEfficiency) { + TFile* fEfficiencyTrigger = nullptr; + fEfficiencyTrigger = TFile::Open(cfgEffWeights.cfgEfficiency.value.c_str(), "READ"); + mEfficiency = dynamic_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { - mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + mEfficiency = ccdb->getForTimeStamp(cfgEffWeights.cfgEfficiency, timestamp); } if (mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgEfficiency.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgEfficiency.value.c_str(), static_cast(mEfficiency)); } + if (!cfgEffWeights.cfgEfficiencyNch.value.empty()) { + if (cfgEffWeights.cfgLocalEfficiencyNch) { + TFile* fEfficiencyTrigger = nullptr; + fEfficiencyTrigger = TFile::Open(cfgEffWeights.cfgEfficiencyNch.value.c_str(), "READ"); + mEfficiencyNch = dynamic_cast(fEfficiencyTrigger->Get("ccdb_object")); - if (cfgCentralityWeight.value.empty() == false) { - mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); + } else { + mEfficiencyNch = ccdb->getForTimeStamp(cfgEffWeights.cfgEfficiencyNch, timestamp); + } + if (!mEfficiencyNch) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgEfficiencyNch.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgEfficiencyNch.value.c_str(), static_cast(mEfficiencyNch)); + } + if (!cfgEffWeights.cfgCentralityWeight.value.empty()) { + mCentralityWeight = ccdb->getForTimeStamp(cfgEffWeights.cfgCentralityWeight, timestamp); if (mCentralityWeight == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCentralityWeight.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEffWeights.cfgCentralityWeight.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEffWeights.cfgCentralityWeight.value.c_str(), static_cast(mCentralityWeight)); } correctionsLoaded = true; } + bool getEfficiencyCorrectionNch(float& weightNch, float pt) + { + float effNch = 1.; + if (mEfficiencyNch) { + int ptBin = mEfficiencyNch->FindBin(pt); + effNch = mEfficiencyNch->GetBinContent(ptBin); + } else { + effNch = 1.0; + } + if (effNch == 0) { + return false; + } + weightNch = 1. / effNch; + return true; + } + bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) { float eff = 1.; @@ -763,93 +905,135 @@ struct PidDiHadron { } else { eff = 1.0; } - if (eff == 0) + if (eff == 0) { return false; + } weight_nue = 1. / eff; return true; } - bool getCentralityWeight(float& weightCent, const float centrality) + bool getCentralityWeight(float& weightCent, const double centrality) { float weight = 1.; - if (mCentralityWeight) + if (mCentralityWeight) { weight = mCentralityWeight->GetBinContent(mCentralityWeight->FindBin(centrality)); - else + } else { weight = 1.0; - if (weight == 0) + } + if (weight == 0) { return false; + } weightCent = weight; return true; } - // fill multiple histograms - template - void fillYield(const TCollision& collision, const TTracks& tracks) // function to fill the yield and etaphi histograms. + template + void nchCounter(const TTracks& tracks, double& multiplicity) // function to count the number of tracks in the event and fill the histogram { - float weff1 = 1; - float vtxz = collision.posZ(); - for (auto const& track1 : tracks) { - if (!trackSelected(track1)) + double nTracksCorrected = 0; + float weightNch = 1.0f; + for (auto const& track : tracks) { + if (!trackSelectedForNch(track)) { continue; - if (cfgPIDParticle && getNsigmaPID(track1) != cfgPIDParticle) - continue; // if PID is selected, check if the track has the right PID - if (!getEfficiencyCorrection(weff1, track1.eta(), track1.pt(), vtxz)) + } + + if (!getEfficiencyCorrectionNch(weightNch, track.pt())) { continue; - histos.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); - histos.fill(HIST("Eta"), track1.eta()); - histos.fill(HIST("EtaCorrected"), track1.eta(), weff1); - histos.fill(HIST("pT"), track1.pt()); - histos.fill(HIST("pTCorrected"), track1.pt(), weff1); + } + nTracksCorrected += weightNch; } + multiplicity = nTracksCorrected; } template - void fillNsigmaAfterCut(const TTrack& track1, Int_t pid) // function to fill the QA after Nsigma selection + void fillTrackQA(TTrack const& track, int pid, double eventClass, Stage stage, float weff) // function to fill the QA after Nsigma selection { - switch (pid) { - case 1: // For Pions - if (!cfgUseItsPID) { - if (cfgGetdEdx) { - double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); - - histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); - histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); - histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); + if (cfgGeneral.cfgQABasic) { + if (stage == Before && pid == UseCharged) { + histos.fill(HIST("Phi"), RecoDecay::constrainAngle(track.phi(), 0.0), UseCharged); + histos.fill(HIST("Eta"), track.eta(), UseCharged); + histos.fill(HIST("EtaCorrected"), track.eta(), UseCharged, weff); + histos.fill(HIST("pTFiner"), track.pt(), UseCharged, eventClass); + histos.fill(HIST("pTFinerCorrected"), track.pt(), UseCharged, eventClass, weff); + + } else if (stage == After && pid > UseCharged) { + histos.fill(HIST("Phi"), RecoDecay::constrainAngle(track.phi(), 0.0), pid); + histos.fill(HIST("Eta"), track.eta(), pid); + histos.fill(HIST("EtaCorrected"), track.eta(), pid, weff); + histos.fill(HIST("pTFiner"), track.pt(), pid, eventClass); + histos.fill(HIST("pTFinerCorrected"), track.pt(), pid, eventClass, weff); + } + } + + if (pid > UseCharged && (cfgPIDConfigs.cfgQANsigma || cfgPIDConfigs.cfgQAdEdx)) { + const bool useITS = cfgPIDConfigs.cfgPIDUseIts; + double tpcNSigma = 0.0; + double tpcExpSigma = 0.0; + double tofNSigma = 0.0; + double itsNSigma = 0.0; + switch (pid) { + case UsePions: // For Pions + tofNSigma = track.tofNSigmaPi(); + if (!useITS) { + tpcNSigma = track.tpcNSigmaPi(); + tpcExpSigma = track.tpcExpSigmaPi(); + } else { + itsNSigma = itsResponse.nSigmaITS(track); } - histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - } - if (cfgUseItsPID) - histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPi(), track1.pt()); - break; - case 2: // For Kaons - if (!cfgUseItsPID) { - if (cfgGetdEdx) { - double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); - - histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); - histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); - histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); + break; + case UseKaons: // For Kaons + tofNSigma = track.tofNSigmaKa(); + if (!useITS) { + tpcNSigma = track.tpcNSigmaKa(); + tpcExpSigma = track.tpcExpSigmaKa(); + } else { + itsNSigma = itsResponse.nSigmaITS(track); } - histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); - } - if (cfgUseItsPID) - histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaKa(), track1.pt()); - break; - case 3: // For Protons - if (!cfgUseItsPID) { - if (cfgGetdEdx) { - double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); - - histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); - histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); - histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); + break; + + case UseProtons: // For Protons + tofNSigma = track.tofNSigmaPr(); + if (!useITS) { + tpcNSigma = track.tpcNSigmaPr(); + tpcExpSigma = track.tpcExpSigmaPr(); + } else { + itsNSigma = itsResponse.nSigmaITS(track); + } + break; + default: + return; + } + + if (cfgPIDConfigs.cfgQANsigma) { + if (stage == Before) { + if (!useITS) { + histos.fill(HIST("TofTpcNsigma_beforeCut"), tpcNSigma, tofNSigma, track.pt(), pid); + } else { + histos.fill(HIST("TofItsNsigma_beforeCut"), itsNSigma, tofNSigma, track.pt(), pid); + } + } else if (stage == After) { + if (!useITS) { + histos.fill(HIST("TofTpcNsigma_afterCut"), tpcNSigma, tofNSigma, track.pt(), pid); + } else { + histos.fill(HIST("TofItsNsigma_afterCut"), itsNSigma, tofNSigma, track.pt(), pid); } - histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); } - if (cfgUseItsPID) - histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); - break; - } // end of switch + } + + if (cfgPIDConfigs.cfgQAdEdx) { + double tpcExpSignal = track.tpcSignal() - (tpcNSigma * tpcExpSigma); + + if (stage == Before) { + histos.fill(HIST("TpcdEdx_ptwise_beforeCut"), track.pt(), track.tpcSignal(), tofNSigma, pid); + histos.fill(HIST("ExpTpcdEdx_ptwise_beforeCut"), track.pt(), tpcExpSignal, tofNSigma, pid); + histos.fill(HIST("ExpSigma_ptwise_beforeCut"), track.pt(), tpcExpSigma, tofNSigma, pid); + } else if (stage == After) { + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track.pt(), track.tpcSignal(), tofNSigma, pid); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track.pt(), tpcExpSignal, tofNSigma, pid); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track.pt(), tpcExpSigma, tofNSigma, pid); + } + } + } // if not a charged particle } float getDPhiStar(float charge1, float charge2, float phi1, float phi2, float pt1, float pt2, float radius, int magField) @@ -866,238 +1050,230 @@ struct PidDiHadron { return dPhiStar; } - template - void fillCorrelations(const TTracks& tracks1, const TTracksAssoc& tracks2, float posZ, int system, int magneticField, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + template + void fillCorrelations(const TTracks& triggers, const TTracksAssoc& assocs, float posZ, int system, int magneticField, double eventClass, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { - // Cache efficiency for particles (too many FindBin lookups) - if (mEfficiency) { - efficiencyAssociatedCache.clear(); - efficiencyAssociatedCache.reserve(tracks2.size()); - for (const auto& track2 : tracks2) { - float weff = 1.; - getEfficiencyCorrection(weff, track2.eta(), track2.pt(), posZ); - efficiencyAssociatedCache.push_back(weff); + const int kNullIndex = -44; + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(assocs.size()); + useAssociatedCache.clear(); + useAssociatedCache.reserve(assocs.size()); + + for (const auto& assc : assocs) { // loading efficiencies for associated particles and simultaneously applying track selection + if (trackSelected(assc)) { + useAssociatedCache.push_back(1); + if (mEfficiency) { + float weff = 1.; + getEfficiencyCorrection(weff, assc.eta(), assc.pt(), posZ); + efficiencyAssociatedCache.push_back(weff); + } + } else { + useAssociatedCache.push_back(0); + if (mEfficiency) { + efficiencyAssociatedCache.push_back(kNullIndex); + } } - } - - if (system == SameEvent) { - if (!cfgCentTableUnavailable) - histos.fill(HIST("Centrality_used"), cent); - histos.fill(HIST("Nch_used"), tracks1.size()); - } + } // end of efficieny requirement - int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + int fSampleIndex = static_cast(fRandom.Uniform(0.0, cfgGeneral.cfgSampleSize)); float triggerWeight = 1.0f; float associatedWeight = 1.0f; // loop over all tracks - for (auto const& track1 : tracks1) { + for (auto const& trig : triggers) { - if (!trackSelected(track1)) + if (!trackSelected(trig)) { continue; - - // Fill Nsigma QA - if (cfgGetNsigmaQA && !cfgUseItsPID) { - if (cfgPIDParticle == kPions) { - histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - if (cfgGetdEdx) { - double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); - - histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); - histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); - histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); - } - } - if (cfgPIDParticle == kKaons) { - histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); - if (cfgGetdEdx) { - double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); - - histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); - histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); - histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); - } - } - if (cfgPIDParticle == kProtons) { - histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); - if (cfgGetdEdx) { - double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); - - histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); - histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); - histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); - } - } } - if (cfgGetNsigmaQA && cfgUseItsPID) { - if (cfgPIDParticle == kPions) - histos.fill(HIST("TofItsNsigma_before"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPi(), track1.pt()); - if (cfgPIDParticle == kKaons) - histos.fill(HIST("TofItsNsigma_before"), itsResponse.nSigmaITS(track1), track1.tofNSigmaKa(), track1.pt()); - if (cfgPIDParticle == kProtons) - histos.fill(HIST("TofItsNsigma_before"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); + + if (cfgEffWeights.cfgUseTrigWeight && !getEfficiencyCorrection(triggerWeight, trig.eta(), trig.pt(), posZ)) { + continue; } - if (cfgPIDParticle && getNsigmaPID(track1) != cfgPIDParticle) - continue; // if PID is selected, check if the track has the right PID + if (system == SameEvent) { + fillTrackQA(trig, UseCharged, eventClass, Before, triggerWeight); + fillTrackQA(trig, UsePions, eventClass, Before, triggerWeight); + fillTrackQA(trig, UseKaons, eventClass, Before, triggerWeight); + fillTrackQA(trig, UseProtons, eventClass, Before, triggerWeight); + } - if (cfgGetNsigmaQA) - fillNsigmaAfterCut(track1, cfgPIDParticle); + int pidIndex = getNsigmaPID(trig); - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) - continue; if (system == SameEvent) { - histos.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + histos.fill(HIST("Trig_hist"), fSampleIndex, posZ, eventClass, trig.pt(), UseCharged, eventWeight * triggerWeight); + if (pidIndex > UseCharged) { + fillTrackQA(trig, pidIndex, eventClass, After, triggerWeight); + histos.fill(HIST("Trig_hist"), fSampleIndex, posZ, eventClass, trig.pt(), pidIndex, eventWeight * triggerWeight); + } } - for (auto const& track2 : tracks2) { + for (auto const& assc : assocs) { - if (!trackSelected(track2)) + if (useAssociatedCache[assc.filteredIndex()] == 0) { // rejecting associated tracks continue; - if (mEfficiency) { - associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; } - if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) + if (mEfficiency && efficiencyAssociatedCache[assc.filteredIndex()] != kNullIndex) { // loading associated efficiency + associatedWeight = efficiencyAssociatedCache[assc.filteredIndex()]; + } + + if (!cfgGeneral.cfgUsePtOrder && trig.globalIndex() == assc.globalIndex()) { continue; // For pt-differential correlations, skip if the trigger and associate are the same track - if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) + } + if (cfgGeneral.cfgUsePtOrder && system == SameEvent && trig.pt() <= assc.pt()) { continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt - if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + } + if (cfgGeneral.cfgUsePtOrder && system == MixedEvent && cfgGeneral.cfgUsePtOrderInMixEvent && trig.pt() <= assc.pt()) { continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt + } - float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); - float deltaEta = track1.eta() - track2.eta(); + float deltaPhi = RecoDecay::constrainAngle(trig.phi() - assc.phi(), -PIHalf); + float deltaEta = trig.eta() - assc.eta(); - if (std::abs(deltaEta) < cfgCutMerging) { + if (std::abs(deltaEta) < cfgGeneral.cfgCutMerging && cfgGeneral.cfgUseCutMerging) { - double dPhiStarHigh = getDPhiStar(track1.sign(), track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), cfgRadiusHigh, magneticField); - double dPhiStarLow = getDPhiStar(track1.sign(), track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), cfgRadiusLow, magneticField); + double dPhiStarHigh = getDPhiStar(trig.sign(), assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), cfgGeneral.cfgRadiusHigh, magneticField); + double dPhiStarLow = getDPhiStar(trig.sign(), assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), cfgGeneral.cfgRadiusLow, magneticField); - const double kLimit = 3.0 * cfgCutMerging; + const double kLimit = 3.0 * cfgGeneral.cfgCutMerging; bool bIsBelow = false; if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { - for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { - double dPhiStar = getDPhiStar(track1.sign(), track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), rad, magneticField); + for (double rad(cfgGeneral.cfgRadiusLow); rad < cfgGeneral.cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(trig.sign(), assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), rad, magneticField); if (std::abs(dPhiStar) < kLimit) { bIsBelow = true; break; } } - if (bIsBelow) + if (bIsBelow) { continue; + } } - } + } // End of merging cut condition // fill the right sparse and histograms if (system == SameEvent) { - - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + same->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), UseCharged, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + if (pidIndex > UseCharged) { + same->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), pidIndex, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } histos.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } else if (system == MixedEvent) { - - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + mixed->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), UseCharged, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + if (pidIndex > UseCharged) { + mixed->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), pidIndex, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } histos.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } } } - template - void fillCorrelationsReso(const TV0Tracks& tracks1, const TTracksAssoc& tracks2, float posZ, float posY, float posX, int system, int magneticField, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + template + void fillCorrelationsReso(const TV0Tracks& triggers, const TTracksAssoc& assocs, float posZ, float posY, float posX, int system, int magneticField, double eventClass, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { - // Cache efficiency for particles (too many FindBin lookups) - if (mEfficiency) { - efficiencyAssociatedCache.clear(); - efficiencyAssociatedCache.reserve(tracks2.size()); - for (const auto& track2 : tracks2) { - float weff = 1.; - getEfficiencyCorrection(weff, track2.eta(), track2.pt(), posZ); - efficiencyAssociatedCache.push_back(weff); + const int kNullIndex = -44; + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(assocs.size()); + useAssociatedCache.clear(); + useAssociatedCache.reserve(assocs.size()); + + for (const auto& assc : assocs) { // loading efficiencies for associated particles and simultaneously applying track selection + if (trackSelected(assc)) { + useAssociatedCache.push_back(1); + if (mEfficiency) { + float weff = 1.; + getEfficiencyCorrection(weff, assc.eta(), assc.pt(), posZ); + efficiencyAssociatedCache.push_back(weff); + } + } else { + useAssociatedCache.push_back(0); + if (mEfficiency) { + efficiencyAssociatedCache.push_back(kNullIndex); + } } - } - - if (system == SameEvent) { - if (!cfgCentTableUnavailable) - histos.fill(HIST("Centrality_used"), cent); - histos.fill(HIST("Nch_used"), tracks2.size()); // Taking Nch from tracks2 since tracks1 are V0s - } + } // end of efficieny requirement - int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + int fSampleIndex = static_cast(fRandom.Uniform(0.0, cfgGeneral.cfgSampleSize)); float triggerWeight = 1.0f; float associatedWeight = 1.0f; // loop over all tracks - for (auto const& track1 : tracks1) { + for (auto const& trig : triggers) { double resoMass = -1; - // 4 = kshort, 5 = lambda, 6 = phi - if (cfgPIDParticle == kK0) { - if (!isSelectedK0(track1, posZ, posY, posX)) + // 4 = kshort, 5 = lambda + if (cfgPIDConfigs.cfgPIDParticle == UseK0) { + if (!isSelectedK0(trig, posZ, posY, posX, system)) { continue; // Reject if called for K0 but V0 is not K0 + } - resoMass = track1.mK0Short(); + resoMass = trig.mK0Short(); } - if (cfgPIDParticle == kLambda) { - if (!isSelectedLambda(track1, posZ, posY, posX)) + if (cfgPIDConfigs.cfgPIDParticle == UseLambda) { + if (!isSelectedLambda(trig, posZ, posY, posX, system)) { continue; // Reject if called for Lambda but V0 is not lambda - - resoMass = track1.mLambda(); + } + resoMass = trig.mLambda(); } if (system == SameEvent) { - histos.fill(HIST("Trig_histReso"), fSampleIndex, posZ, track1.pt(), resoMass, eventWeight * triggerWeight); + histos.fill(HIST("Trig_histReso"), fSampleIndex, posZ, eventClass, trig.pt(), resoMass, eventWeight * triggerWeight); } - for (auto const& track2 : tracks2) { + for (auto const& assc : assocs) { - if (!trackSelected(track2)) - continue; - if (track2.pt() < cfgCutPtMin || track2.pt() > cfgCutPtMax) // Select associated particles in the pt range 0.2 - 3.0 GeV/c - continue; - if (mEfficiency) { - associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; + if (useAssociatedCache[assc.filteredIndex()] == 0) { + continue; // rejecting associated tracks + } + + if (mEfficiency && efficiencyAssociatedCache[assc.filteredIndex()] != kNullIndex) { + associatedWeight = efficiencyAssociatedCache[assc.filteredIndex()]; // loading associated efficiency } - if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) + if (cfgGeneral.cfgUsePtOrder && system == SameEvent && trig.pt() <= assc.pt()) { continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt - if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + } + if (cfgGeneral.cfgUsePtOrder && system == MixedEvent && cfgGeneral.cfgUsePtOrderInMixEvent && trig.pt() <= assc.pt()) { continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt + } - float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); - float deltaEta = track1.eta() - track2.eta(); + float deltaPhi = RecoDecay::constrainAngle(trig.phi() - assc.phi(), -PIHalf); + float deltaEta = trig.eta() - assc.eta(); - if (std::abs(deltaEta) < cfgCutMerging) { + if (std::abs(deltaEta) < cfgGeneral.cfgCutMerging && cfgGeneral.cfgUseCutMerging) { - double dPhiStarHigh = getDPhiStar(0, track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), cfgRadiusHigh, magneticField); - double dPhiStarLow = getDPhiStar(0, track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), cfgRadiusLow, magneticField); + double dPhiStarHigh = getDPhiStar(0, assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), cfgGeneral.cfgRadiusHigh, magneticField); + double dPhiStarLow = getDPhiStar(0, assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), cfgGeneral.cfgRadiusLow, magneticField); - const double kLimit = 3.0 * cfgCutMerging; + const double kLimit = 3.0 * cfgGeneral.cfgCutMerging; bool bIsBelow = false; if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { - for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { - double dPhiStar = getDPhiStar(0, track2.sign(), track1.phi(), track2.phi(), track1.pt(), track2.pt(), rad, magneticField); + for (double rad(cfgGeneral.cfgRadiusLow); rad < cfgGeneral.cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(0, assc.sign(), trig.phi(), assc.phi(), trig.pt(), assc.pt(), rad, magneticField); if (std::abs(dPhiStar) < kLimit) { bIsBelow = true; break; } } - if (bIsBelow) + if (bIsBelow) { continue; + } } } // fill the right sparse and histograms if (system == SameEvent) { - sameReso->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + sameReso->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), resoMass, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); histos.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } else if (system == MixedEvent) { - mixedReso->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), resoMass, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + mixedReso->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, trig.pt(), resoMass, deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); histos.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } @@ -1105,144 +1281,165 @@ struct PidDiHadron { } template - bool selectionEvent(const TCollision& collision, const int mult, const float cent, const bool fillCounter) + bool selectionEvent(TCollision const& collision, const int mult, const double cent, const bool fillCounter) { - if (fillCounter) - histos.fill(HIST("hEventCount"), kFilteredEvents); + if (fillCounter) { + histos.fill(HIST("hEventCount"), FilteredEvents); + } if (!collision.sel8()) { - return 0; + return false; + } + if (fillCounter) { + histos.fill(HIST("hEventCount"), AfterSel8); } - if (fillCounter) - histos.fill(HIST("hEventCount"), kAfterSel8); - if (eventCuts[kUseNoTimeFrameBorder][kEvCut1] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return 0; + if (eventCuts[UseNoTimeFrameBorder][EvCut1] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (fillCounter && eventCuts[UseNoTimeFrameBorder][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoTimeFrameBorder); } - if (fillCounter && eventCuts[kUseNoTimeFrameBorder][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); - if (eventCuts[kUseNoITSROFrameBorder][kEvCut1] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return 0; + if (eventCuts[UseNoITSROFrameBorder][EvCut1] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (fillCounter && eventCuts[UseNoITSROFrameBorder][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoITSROFrameBorder); } - if (fillCounter && eventCuts[kUseNoITSROFrameBorder][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); - if (eventCuts[kUseNoSameBunchPileup][kEvCut1] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (eventCuts[UseNoSameBunchPileup][EvCut1] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { // rejects collisions which are associated with the same "found-by-T0" bunch crossing // https://indico.cern.ch/event/1396220/#1-event-selection-with-its-rof - return 0; + return false; + } + if (fillCounter && eventCuts[UseNoSameBunchPileup][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoSameBunchPileup); } - if (fillCounter && eventCuts[kUseNoSameBunchPileup][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoSameBunchPileup); - if (eventCuts[kUseGoodZvtxFT0vsPV][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (eventCuts[UseGoodZvtxFT0vsPV][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference // use this cut at low multiplicities with caution - return 0; + return false; + } + if (fillCounter && eventCuts[UseGoodZvtxFT0vsPV][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodZvtxFT0vsPV); } - if (fillCounter && eventCuts[kUseGoodZvtxFT0vsPV][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); - if (eventCuts[kUseNoCollInTimeRangeStandard][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (eventCuts[UseNoCollInTimeRangeStandard][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // no collisions in specified time range - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoCollInTimeRangeStandard][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); - if (eventCuts[kUseGoodITSLayersAll][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (fillCounter && eventCuts[UseNoCollInTimeRangeStandard][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoCollInTimeRangeStandard); + } + + if (eventCuts[UseGoodITSLayersAll][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { // from Jan 9 2025 AOT meeting // cut time intervals with dead ITS staves - return 0; + return false; + } + + if (fillCounter && eventCuts[UseGoodITSLayersAll][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodITSLayersAll); + } + + if (eventCuts[UseGoodITSLayer0123][EvCut1] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + return false; + } + if (fillCounter && eventCuts[UseGoodITSLayer0123][EvCut1]) { + histos.fill(HIST("hEventCount"), UseGoodITSLayer0123); } - if (fillCounter && eventCuts[kUseGoodITSLayersAll][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseGoodITSLayersAll); - if (eventCuts[kUseNoCollInRofStandard][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (eventCuts[UseNoCollInRofStandard][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold - return 0; + return false; } - if (fillCounter && eventCuts[kUseNoCollInRofStandard][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoCollInRofStandard); - if (eventCuts[kUseNoHighMultCollInPrevRof][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (fillCounter && eventCuts[UseNoCollInRofStandard][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoCollInRofStandard); + } + + if (eventCuts[UseNoHighMultCollInPrevRof][EvCut1] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold - return 0; + return false; + } + if (fillCounter && eventCuts[UseNoHighMultCollInPrevRof][EvCut1]) { + histos.fill(HIST("hEventCount"), UseNoHighMultCollInPrevRof); } - if (fillCounter && eventCuts[kUseNoHighMultCollInPrevRof][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[kUseOccupancy][kEvCut1] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { - return 0; + if (eventCuts[UseOccupancy][EvCut1] && (occupancy < cfgEvSel.cfgCutOccupancyMin || occupancy > cfgEvSel.cfgCutOccupancyMax)) { + return false; + } + if (fillCounter && eventCuts[UseOccupancy][EvCut1]) { + histos.fill(HIST("hEventCount"), UseOccupancy); } - if (fillCounter && eventCuts[kUseOccupancy][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseOccupancy); - if (eventCuts[kUseMultCorrCut][kEvCut1]) { - if (cfgFuncParas.cfgMultPVT0CCutEnabled && !cfgCentTableUnavailable) { - if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(cent)) - return 0; - if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(cent)) - return 0; + if (eventCuts[UseMultCorrCut][EvCut1]) { + if (cfgFuncParas.cfgMultPVT0CCutEnabled) { + if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(cent)) { + return false; + } + if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(cent)) { + return false; + } } - if (cfgFuncParas.cfgMultT0CCutEnabled && !cfgCentTableUnavailable) { - if (mult < cfgFuncParas.fMultT0CCutLow->Eval(cent)) - return 0; - if (mult > cfgFuncParas.fMultT0CCutHigh->Eval(cent)) - return 0; + if (cfgFuncParas.cfgMultT0CCutEnabled) { + if (mult < cfgFuncParas.fMultT0CCutLow->Eval(cent)) { + return false; + } + if (mult > cfgFuncParas.fMultT0CCutHigh->Eval(cent)) { + return false; + } } if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { - if (mult < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) - return 0; - if (mult > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) - return 0; + if (mult < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) { + return false; + } + if (mult > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) { + return false; + } } if (cfgFuncParas.cfgMultMultV0ACutEnabled) { - if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(mult)) - return 0; - if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(mult)) - return 0; + if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(mult)) { + return false; + } + if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(mult)) { + return false; + } } } - if (fillCounter && eventCuts[kUseMultCorrCut][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseMultCorrCut); + if (fillCounter && eventCuts[UseMultCorrCut][EvCut1]) { + histos.fill(HIST("hEventCount"), UseMultCorrCut); + } // V0A T0A 5 sigma cut - if (eventCuts[kUseT0AV0ACut][kEvCut1] && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) - return 0; - if (fillCounter && eventCuts[kUseT0AV0ACut][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseT0AV0ACut); - - if (eventCuts[kUseVertexITSTPC][kEvCut1] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) - return 0; - if (fillCounter && eventCuts[kUseVertexITSTPC][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseVertexITSTPC); - - if (eventCuts[kUseTVXinTRD][kEvCut1] && collision.alias_bit(kTVXinTRD)) { - return 0; + if (eventCuts[UseT0AV0ACut][EvCut1] && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > cfgFuncParas.cfgV0AT0Acut * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) { + return false; + } + if (fillCounter && eventCuts[UseT0AV0ACut][EvCut1]) { + histos.fill(HIST("hEventCount"), UseT0AV0ACut); } - if (fillCounter && eventCuts[kUseTVXinTRD][kEvCut1]) - histos.fill(HIST("hEventCount"), kUseTVXinTRD); - return 1; + return true; } void processSame(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) { auto bc = collision.bc_as(); - float cent = -1.; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) - cent = getCentrality(collision); - if (cfgUseAdditionalEventCut && !selectionEvent(collision, tracks.size(), cent, true)) + float cent = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision); + + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision, tracks.size(), cent, true)) { return; + } loadCorrection(bc.timestamp()); - if (!cfgCentTableUnavailable) { + if (!cfgEvSel.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent); histos.fill(HIST("Centrality"), cent); histos.fill(HIST("CentralityWeighted"), cent, weightCent); @@ -1250,24 +1447,32 @@ struct PidDiHadron { histos.fill(HIST("Nch"), tracks.size()); histos.fill(HIST("zVtx"), collision.posZ()); - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + auto multiplicity = static_cast(tracks.size()); + + if (cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks, multiplicity); + } + histos.fill(HIST("Nch_corrected"), multiplicity); + + if (cfgEvSel.cfgSelCollByNch && (multiplicity < cfgEvSel.cfgCutMultMin || multiplicity >= cfgEvSel.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent < cfgEvSel.cfgCutCentMin || cent >= cfgEvSel.cfgCutCentMax)) { return; } histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - fillYield(collision, tracks); - same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent, weightCent); + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent; + + auto assocs = asscTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + fillCorrelations(tracks, assocs, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), eventClass, weightCent); } PROCESS_SWITCH(PidDiHadron, processSame, "Process same event", true); // the process for filling the mixed events void processMixed(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) { - auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); auto mult = associatedTracks.size(); @@ -1279,53 +1484,71 @@ struct PidDiHadron { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - if (!collision1.sel8() || !collision2.sel8()) + if (!collision1.sel8() || !collision2.sel8()) { continue; + } - if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) - continue; + float cent1 = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision1); + float cent2 = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision2); - if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision1, tracks1.size(), cent1, false)) { continue; - - float cent1 = -1; - float cent2 = -1; - if (!cfgCentTableUnavailable) { - cent1 = getCentrality(collision1); - cent2 = getCentrality(collision2); } - if (cfgUseAdditionalEventCut && !selectionEvent(collision1, tracks1.size(), cent1, false)) + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision2, tracks2.size(), cent2, false)) { continue; - if (cfgUseAdditionalEventCut && !selectionEvent(collision2, tracks2.size(), cent2, false)) + } + + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent1 < cfgEvSel.cfgCutCentMin || cent1 >= cfgEvSel.cfgCutCentMax)) { + continue; + } + + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent2 < cfgEvSel.cfgCutCentMin || cent2 >= cfgEvSel.cfgCutCentMax)) { continue; + } + + auto multiplicity1 = static_cast(tracks1.size()); + auto multiplicity2 = static_cast(tracks2.size()); - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + if (cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks1, multiplicity1); + if (cfgEvSel.cfgUseCol2ForMixedEvSel) { + nchCounter(tracks2, multiplicity2); + } + } + + if (cfgEvSel.cfgSelCollByNch && (multiplicity1 < cfgEvSel.cfgCutMultMin || multiplicity1 >= cfgEvSel.cfgCutMultMax)) { continue; + } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + if (cfgEvSel.cfgSelCollByNch && (multiplicity2 < cfgEvSel.cfgCutMultMin || multiplicity2 >= cfgEvSel.cfgCutMultMax)) { continue; + } - histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin auto bc = collision1.bc_as(); loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - if (cfgUseEventWeights) { + if (cfgEffWeights.cfgUseEventWeights) { eventWeight = 1.0f / it.currentWindowNeighbours(); } + + histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity1 : cent1; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) + if (!cfgEvSel.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent1); + } - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight * weightCent); + auto assocs = asscTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + fillCorrelations(tracks1, assocs, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), eventClass, eventWeight * weightCent); } } PROCESS_SWITCH(PidDiHadron, processMixed, "Process mixed events", true); template - bool isSelectedK0(V0 const& candidate, float posZ, float posY, float posX) + bool isSelectedK0(V0 const& candidate, float posZ, float posY, float posX, int system) { double mk0 = candidate.mK0Short(); @@ -1333,58 +1556,103 @@ struct PidDiHadron { auto postrack = candidate.template posTrack_as(); auto negtrack = candidate.template negTrack_as(); - histos.fill(HIST("hK0Count"), 0.5); - if (postrack.pt() < resoCutVals[kPosTrackPt][iK0] || negtrack.pt() < resoCutVals[kNegTrackPt][iK0]) + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillCandidate); + } + if (postrack.pt() < resoCutVals[CutPosTrackPt][IndexK0] || negtrack.pt() < resoCutVals[CutNegTrackPt][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 1.5); - if (mk0 < resoCutVals[kMassMin][iK0] && mk0 > resoCutVals[kMassMax][iK0]) + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillDaughterPt); + } + if (mk0 < resoCutVals[CutMassMin][IndexK0] || mk0 > resoCutVals[CutMassMax][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 2.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillMassCut); + } // Rapidity correction - if (candidate.yK0Short() > resoCutVals[kRapidity][iK0]) + if (candidate.yK0Short() > resoCutVals[CutRapidityMax][IndexK0] || candidate.yK0Short() < resoCutVals[CutRapidityMin][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 3.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillRapidityCut); + } // DCA cuts for K0short - if (std::abs(candidate.dcapostopv()) < resoCutVals[kDCAPosToPVMin][iK0] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCANegToPVMin][iK0]) + if (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCAPosToPVMin][IndexK0] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCANegToPVMin][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[kDCABetDaug][iK0]) + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillDCAtoPV); + } + if (resoSwitchVals[UseDCABetDaug][IndexK0] && std::abs(candidate.dcaV0daughters()) > resoCutVals[CutDCABetDaug][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 5.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillDCAxDaughters); + } // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][iK0] && (candidate.v0radius() < resoCutVals[kRadiusMin][iK0] || candidate.v0radius() > resoCutVals[kRadiusMax][iK0])) + if (resoSwitchVals[UseV0Radius][IndexK0] && (candidate.v0radius() < resoCutVals[CutRadiusMin][IndexK0] || candidate.v0radius() > resoCutVals[CutRadiusMax][IndexK0])) { return false; - histos.fill(HIST("hK0Count"), 6.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillV0Radius); + } // cosine pointing angle cuts - if (candidate.v0cosPA() < resoCutVals[kCosPA][iK0]) + if (resoSwitchVals[UseCosPA][IndexK0] && candidate.v0cosPA() < resoCutVals[CutCosPA][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 7.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillCosPA); + } // Proper lifetime float cTauK0 = candidate.distovertotmom(posX, posY, posZ) * massK0Short; - if (resoSwitchVals[kUseProperLifetime][iK0] && std::abs(cTauK0) > resoCutVals[kLifeTime][iK0]) + if (resoSwitchVals[UseProperLifetime][IndexK0] && cTauK0 > resoCutVals[CutLifeTime][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 8.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillProperLifetime); + } // ArmenterosPodolanskiCut - if (resoSwitchVals[kUseArmPodCut][iK0] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[kArmPodMinVal][iK0]) + if (resoSwitchVals[UseArmPodCut][IndexK0] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[CutArmPodMinVal][IndexK0]) { return false; - histos.fill(HIST("hK0Count"), 9.5); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillArmPodCut); + } + + if (resoSwitchVals[UseCompMassRej][IndexK0]) { + if (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda) < resoCutVals[CutCompMassRej][IndexK0]) { + return false; + } + if (std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda) < resoCutVals[CutCompMassRej][IndexK0]) { + return false; + } + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillCompetingMass); + } + // Selection on V0 daughters - if (!selectionV0Daughter(postrack, kPions) || !selectionV0Daughter(negtrack, kPions)) + if (!selectionV0Daughter(postrack, UsePions) || !selectionV0Daughter(negtrack, UsePions)) { return false; - histos.fill(HIST("hK0Count"), 10.5); - - histos.fill(HIST("hK0Phi"), candidate.phi()); - histos.fill(HIST("hK0Eta"), candidate.eta()); - histos.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaPi()); - histos.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaPi()); - histos.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaPi()); - histos.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaPi()); + } + if (system == SameEvent) { + histos.fill(HIST("hK0Count"), FillDaughterTrackSelected); + histos.fill(HIST("hK0Phi"), candidate.phi()); + histos.fill(HIST("hK0Rap"), candidate.yK0Short()); + histos.fill(HIST("hK0Eta"), candidate.eta()); + histos.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaPi()); + histos.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaPi()); + histos.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaPi()); + histos.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaPi()); + } return true; } template - bool isSelectedLambda(V0 const& candidate, float posZ, float posY, float posX) + bool isSelectedLambda(V0 const& candidate, float posZ, float posY, float posX, int system) { bool isL = false; // Is lambda candidate bool isAL = false; // Is anti-lambda candidate @@ -1396,71 +1664,127 @@ struct PidDiHadron { auto postrack = candidate.template posTrack_as(); auto negtrack = candidate.template negTrack_as(); - histos.fill(HIST("hLambdaCount"), 0.5); - if (postrack.pt() < resoCutVals[kPosTrackPt][iLambda] || negtrack.pt() < resoCutVals[kNegTrackPt][iLambda]) + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillCandidate); + } + if (postrack.pt() < resoCutVals[CutPosTrackPt][IndexLambda] || negtrack.pt() < resoCutVals[CutNegTrackPt][IndexLambda]) { return false; - - histos.fill(HIST("hLambdaCount"), 1.5); - if (mlambda > resoCutVals[kMassMin][iLambda] && mlambda < resoCutVals[kMassMax][iLambda]) + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillDaughterPt); + } + if (mlambda > resoCutVals[CutMassMin][IndexLambda] && mlambda < resoCutVals[CutMassMax][IndexLambda]) { isL = true; - if (mantilambda > resoCutVals[kMassMin][iLambda] && mantilambda < resoCutVals[kMassMax][iLambda]) + } + if (mantilambda > resoCutVals[CutMassMin][IndexLambda] && mantilambda < resoCutVals[CutMassMax][IndexLambda]) { isAL = true; + } if (!isL && !isAL) { return false; } - histos.fill(HIST("hLambdaCount"), 2.5); + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillMassCut); + } // Rapidity correction - if (candidate.yLambda() > resoCutVals[kRapidity][iLambda]) + if (candidate.yLambda() > resoCutVals[CutRapidityMax][IndexLambda] || candidate.yLambda() < resoCutVals[CutRapidityMin][IndexLambda]) { return false; - histos.fill(HIST("hLambdaCount"), 3.5); + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillRapidityCut); + } + // DCA cuts for lambda and antilambda - if (isL) { - if (std::abs(candidate.dcapostopv()) < resoCutVals[kDCAPosToPVMin][iLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCANegToPVMin][iLambda]) - return false; + if (isL && (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCAPosToPVMin][IndexLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCANegToPVMin][IndexLambda])) { + isL = false; } - if (isAL) { - if (std::abs(candidate.dcapostopv()) < resoCutVals[kDCANegToPVMin][iLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[kDCAPosToPVMin][iLambda]) - return false; + if (isAL && (std::abs(candidate.dcapostopv()) < resoCutVals[CutDCANegToPVMin][IndexLambda] || std::abs(candidate.dcanegtopv()) < resoCutVals[CutDCAPosToPVMin][IndexLambda])) { + isAL = false; + } + if (!isL && !isAL) { + return false; + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillDCAtoPV); } - histos.fill(HIST("hLambdaCount"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[kDCABetDaug][iLambda]) + if (resoSwitchVals[UseDCABetDaug][IndexLambda] && std::abs(candidate.dcaV0daughters()) > resoCutVals[CutDCABetDaug][IndexLambda]) { return false; - histos.fill(HIST("hLambdaCount"), 5.5); + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillDCAxDaughters); + } // v0 radius cuts - if (resoSwitchVals[kUseV0Radius][iLambda] && (candidate.v0radius() < resoCutVals[kRadiusMin][iLambda] || candidate.v0radius() > resoCutVals[kRadiusMax][iLambda])) + if (resoSwitchVals[UseV0Radius][IndexLambda] && (candidate.v0radius() < resoCutVals[CutRadiusMin][IndexLambda] || candidate.v0radius() > resoCutVals[CutRadiusMax][IndexLambda])) { return false; - histos.fill(HIST("hLambdaCount"), 6.5); + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillV0Radius); + } // cosine pointing angle cuts - if (candidate.v0cosPA() < resoCutVals[kCosPA][iLambda]) + if (resoSwitchVals[UseCosPA][IndexLambda] && candidate.v0cosPA() < resoCutVals[CutCosPA][IndexLambda]) { return false; - histos.fill(HIST("hLambdaCount"), 7.5); + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillCosPA); + } // Proper lifetime float cTauLambda = candidate.distovertotmom(posX, posY, posZ) * massLambda; - if (resoSwitchVals[kUseProperLifetime][iLambda] && cTauLambda > resoCutVals[kLifeTime][iLambda]) + if (resoSwitchVals[UseProperLifetime][IndexLambda] && cTauLambda > resoCutVals[CutLifeTime][IndexLambda]) { return false; - histos.fill(HIST("hLambdaCount"), 8.5); - if (isL) { - if (!selectionV0Daughter(postrack, kProtons) || !selectionV0Daughter(negtrack, kPions)) - return false; } - if (isAL) { - if (!selectionV0Daughter(postrack, kPions) || !selectionV0Daughter(negtrack, kProtons)) - return false; + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillProperLifetime); } - histos.fill(HIST("hLambdaCount"), 9.5); - if (!cfgUseAntiLambda && isAL) { // Reject the track if it is antilambda + // ArmenterosPodolanskiCut + if (resoSwitchVals[UseArmPodCut][IndexLambda] && (candidate.qtarm() / std::abs(candidate.alpha())) < resoCutVals[CutArmPodMinVal][IndexLambda]) { return false; } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillArmPodCut); + } + + if (resoSwitchVals[UseCompMassRej][IndexLambda]) { + if (std::abs(candidate.mK0Short() - o2::constants::physics::MassK0Short) < resoCutVals[CutCompMassRej][IndexLambda]) { + return false; + } + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillCompetingMass); + } - histos.fill(HIST("hLambdaPhi"), candidate.phi()); - histos.fill(HIST("hLambdaEta"), candidate.eta()); - histos.fill(HIST("PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaPr()); - histos.fill(HIST("PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaPr()); - histos.fill(HIST("PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaPi()); - histos.fill(HIST("PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaPi()); + if (isL) { + if (!selectionV0Daughter(postrack, UseProtons) || !selectionV0Daughter(negtrack, UsePions)) { + isL = false; + } + } + if (isAL) { + if (!selectionV0Daughter(postrack, UsePions) || !selectionV0Daughter(negtrack, UseProtons)) { + isAL = false; + } + } + if (!isL && !isAL) { + return false; + } + if (system == SameEvent) { + histos.fill(HIST("hLambdaCount"), FillDaughterTrackSelected); + histos.fill(HIST("hLambdaPhi"), candidate.phi()); + histos.fill(HIST("hLambdaEta"), candidate.eta()); + histos.fill(HIST("hLambdaRap"), candidate.yLambda()); + } + if (isL && system == SameEvent) { + histos.fill(HIST("PrPlusTPC_La"), postrack.pt(), postrack.tpcNSigmaPr()); + histos.fill(HIST("PrPlusTOF_La"), postrack.pt(), postrack.tofNSigmaPr()); + histos.fill(HIST("PiMinusTPC_La"), negtrack.pt(), negtrack.tpcNSigmaPi()); + histos.fill(HIST("PiMinusTOF_La"), negtrack.pt(), negtrack.tofNSigmaPi()); + } + if (isAL && system == SameEvent) { + histos.fill(HIST("PrMinusTPC_Al"), negtrack.pt(), negtrack.tpcNSigmaPr()); + histos.fill(HIST("PrMinusTOF_Al"), negtrack.pt(), negtrack.tofNSigmaPr()); + histos.fill(HIST("PiPlusTPC_Al"), postrack.pt(), postrack.tpcNSigmaPi()); + histos.fill(HIST("PiPlusTOF_Al"), postrack.pt(), postrack.tofNSigmaPi()); + } return true; } @@ -1472,15 +1796,15 @@ struct PidDiHadron { void processSameReso(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::BCsWithTimestamps const&, aod::V0Datas const& V0s) { auto bc = collision.bc_as(); - float cent = -1.; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) - cent = getCentrality(collision); - if (cfgUseAdditionalEventCut && !selectionEvent(collision, tracks.size(), cent, true)) + float cent = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision); + + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision, tracks.size(), cent, true)) { return; + } loadCorrection(bc.timestamp()); - if (!cfgCentTableUnavailable) { + if (!cfgEvSel.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent); histos.fill(HIST("Centrality"), cent); histos.fill(HIST("CentralityWeighted"), cent, weightCent); @@ -1488,17 +1812,28 @@ struct PidDiHadron { histos.fill(HIST("Nch"), tracks.size()); histos.fill(HIST("zVtx"), collision.posZ()); - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + auto multiplicity = static_cast(tracks.size()); + + if (cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks, multiplicity); + } + + histos.fill(HIST("Nch_corrected"), multiplicity); + + if (cfgEvSel.cfgSelCollByNch && (multiplicity < cfgEvSel.cfgCutMultMin || multiplicity >= cfgEvSel.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent < cfgEvSel.cfgCutCentMin || cent >= cfgEvSel.cfgCutCentMax)) { return; } histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - sameReso->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); - fillCorrelationsReso(V0s, tracks, collision.posZ(), collision.posY(), collision.posX(), SameEvent, getMagneticField(bc.timestamp()), cent, weightCent); + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent; + + auto assocs = asscTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + fillCorrelationsReso(V0s, assocs, collision.posZ(), collision.posY(), collision.posX(), SameEvent, getMagneticField(bc.timestamp()), eventClass, weightCent); } PROCESS_SWITCH(PidDiHadron, processSameReso, "Process same event for resonances", true); @@ -1515,48 +1850,69 @@ struct PidDiHadron { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}}; auto tracksTuple = std::make_tuple(V0s, tracks); - Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pairs{binningOnVtxAndMult, cfgGeneral.cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, v0s1, collision2, tracks2] = *it; - if (!collision1.sel8() || !collision2.sel8()) + if (!collision1.sel8() || !collision2.sel8()) { continue; + } auto tracks1 = tracks.sliceByCached(o2::aod::track::collisionId, collision1.globalIndex(), this->cache); - if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) - continue; - if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) - continue; + float cent2 = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision2); + float cent1 = cfgEvSel.cfgCentTableUnavailable ? -1.f : getCentrality(collision1); - float cent1 = -1; - float cent2 = -1; - if (!cfgCentTableUnavailable) { - cent1 = getCentrality(collision1); - cent2 = getCentrality(collision2); + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision1, tracks1.size(), cent1, false)) { + continue; } - if (cfgUseAdditionalEventCut && !selectionEvent(collision1, tracks1.size(), cent1, false)) + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision2, tracks2.size(), cent2, false)) { continue; - if (cfgUseAdditionalEventCut && !selectionEvent(collision2, tracks2.size(), cent2, false)) + } + + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent1 < cfgEvSel.cfgCutCentMin || cent1 >= cfgEvSel.cfgCutCentMax)) { continue; + } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent2 < cfgEvSel.cfgCutCentMin || cent2 >= cfgEvSel.cfgCutCentMax)) { continue; + } + + auto multiplicity1 = static_cast(tracks1.size()); + auto multiplicity2 = static_cast(tracks2.size()); - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + if (cfgGeneral.cfgStrictTrackCounter) { + nchCounter(tracks1, multiplicity1); + + if (cfgEvSel.cfgUseCol2ForMixedEvSel) { + nchCounter(tracks2, multiplicity2); + } + } + + if (cfgEvSel.cfgSelCollByNch && (multiplicity1 < cfgEvSel.cfgCutMultMin || multiplicity1 >= cfgEvSel.cfgCutMultMax)) { continue; + } + + if (cfgEvSel.cfgSelCollByNch && (multiplicity2 < cfgEvSel.cfgCutMultMin || multiplicity2 >= cfgEvSel.cfgCutMultMax)) { + continue; + } - histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin auto bc = collision1.bc_as(); loadCorrection(bc.timestamp()); float eventWeight = 1.0f; - if (cfgUseEventWeights) { + if (cfgEffWeights.cfgUseEventWeights) { eventWeight = 1.0f / it.currentWindowNeighbours(); } + + histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity1 : cent1; float weightCent = 1.0f; - if (!cfgCentTableUnavailable) + if (!cfgEvSel.cfgCentTableUnavailable) { getCentralityWeight(weightCent, cent1); + } - fillCorrelationsReso(v0s1, tracks2, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight * weightCent); + auto assocs = asscTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + + fillCorrelationsReso(v0s1, assocs, collision1.posZ(), collision1.posY(), collision1.posX(), MixedEvent, getMagneticField(bc.timestamp()), eventClass, eventWeight * weightCent); } } PROCESS_SWITCH(PidDiHadron, processMixedReso, "Process mixed events", true); @@ -1564,15 +1920,17 @@ struct PidDiHadron { void processMC(FilteredCollisions::iterator const& collision, FilteredMcTracks const& tracksmc, aod::BCsWithTimestamps const&, aod::McParticles const&) { float cent = -1.; - if (!cfgCentTableUnavailable) + if (!cfgEvSel.cfgCentTableUnavailable) { cent = getCentrality(collision); - if (cfgUseAdditionalEventCut && !selectionEvent(collision, tracksmc.size(), cent, true)) + } + if (cfgEvSel.cfgUseAdditionalEventCut && !selectionEvent(collision, tracksmc.size(), cent, true)) { return; + } - if (cfgSelCollByNch && (tracksmc.size() < cfgCutMultMin || tracksmc.size() >= cfgCutMultMax)) { + if (cfgEvSel.cfgSelCollByNch && (tracksmc.size() < cfgEvSel.cfgCutMultMin || tracksmc.size() >= cfgEvSel.cfgCutMultMax)) { return; } - if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + if (!cfgEvSel.cfgSelCollByNch && !cfgEvSel.cfgCentTableUnavailable && (cent < cfgEvSel.cfgCutCentMin || cent >= cfgEvSel.cfgCutCentMax)) { return; } @@ -1585,33 +1943,40 @@ struct PidDiHadron { int pidIndex = getNsigmaPID(track); // Fill Counts for selection through Nsigma cuts - if (pidIndex == kPions) + if (pidIndex == UsePions) { histos.fill(HIST("hNsigmaPionSelected"), track.pt()); - if (pidIndex == kKaons) + } + if (pidIndex == UseKaons) { histos.fill(HIST("hNsigmaKaonSelected"), track.pt()); - if (pidIndex == kProtons) + } + if (pidIndex == UseProtons) { histos.fill(HIST("hNsigmaProtonSelected"), track.pt()); + } if (track.mcParticle().isPhysicalPrimary()) { - if (cfgPIDParticle == kPions) + if (cfgPIDConfigs.cfgPIDParticle == UsePions) { histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); - if (cfgPIDParticle == kKaons) + } + if (cfgPIDConfigs.cfgPIDParticle == UseKaons) { histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); - if (cfgPIDParticle == kProtons) + } + if (cfgPIDConfigs.cfgPIDParticle == UseProtons) { histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + } } // Check the PDG code for the particles (MC truth) and match with analysed Nsigma PID if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { histos.fill(HIST("hNsigmaPionTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_pi"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); - if (track.mcParticle().isPhysicalPrimary()) + if (track.mcParticle().isPhysicalPrimary()) { histos.fill(HIST("TpcdEdx_ptwise_pi_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + } double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); histos.fill(HIST("ExpTpcdEdx_ptwise_pi"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); - if (pidIndex == kPions) { + if (pidIndex == UsePions) { histos.fill(HIST("hNsigmaPionTruePositives"), track.pt()); } } // Pion condition @@ -1619,13 +1984,14 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { histos.fill(HIST("hNsigmaKaonTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_ka"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); - if (track.mcParticle().isPhysicalPrimary()) + if (track.mcParticle().isPhysicalPrimary()) { histos.fill(HIST("TpcdEdx_ptwise_ka_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + } double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); histos.fill(HIST("ExpTpcdEdx_ptwise_ka"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); - if (pidIndex == kKaons) { + if (pidIndex == UseKaons) { histos.fill(HIST("hNsigmaKaonTruePositives"), track.pt()); } } // Kaon condition @@ -1633,13 +1999,14 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { histos.fill(HIST("hNsigmaProtonTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_pr"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); - if (track.mcParticle().isPhysicalPrimary()) + if (track.mcParticle().isPhysicalPrimary()) { histos.fill(HIST("TpcdEdx_ptwise_pr_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + } double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); histos.fill(HIST("ExpTpcdEdx_ptwise_pr"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); - if (pidIndex == kProtons) { + if (pidIndex == UseProtons) { histos.fill(HIST("hNsigmaProtonTruePositives"), track.pt()); } } // Proton condition diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidLongRange.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidLongRange.cxx index 90d7de1838e..555d4f8de81 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidLongRange.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidLongRange.cxx @@ -111,10 +111,9 @@ struct PidLongRange { O2_DEFINE_CONFIGURABLE(cfgGlobalPtMin, float, 0.2f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgGlobalPtMax, float, 10.0f, "maximum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgGlobalEta, float, 0.8f, "Eta cut") - O2_DEFINE_CONFIGURABLE(cfgGlobalChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgGlobalDCAz, float, 2.0f, "DCAz range for tracks") - O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") - Configurable> cfgTrackCutsDCAxy{"cfgTrackCutsDCAxy", std::vector{"(0.0026+0.005/(x^1.01))", "(0.0026+0.005/(x^1.01))"}, "Functional form of pt-dependent DCAxy cut"}; + O2_DEFINE_CONFIGURABLE(cfgGlobalChi2prTPCcls, float, 2.5f, "Maximum chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgGlobalDCAz, float, 2.0f, "Maximum DCA to vertex z") + Configurable> cfgTrackCutsDCAxy{"cfgTrackCutsDCAxy", std::vector{"[0]*(0.0026+0.005/(x^1.01))", "[0]*(0.0026+0.005/(x^1.01))"}, "Functional form of pt-dependent DCAxy cut"}; Configurable> cfgTrackCutsDCAz{"cfgTrackCutsDCAz", std::vector{"", ""}, "Functional form of pt-dependent DCAz cut"}; Configurable> cfgTrackCuts{"cfgTrackCuts", {LongArrayFloat.front().data(), 10, 2, {"PtMin", "PtMax", "EtaCut", "Chi2PrTpcCls", "TpcCluster", "TpcCrossedRows", "ItsCluster", "DCAz", "DCAzNsigma", "DCAxyNsigma"}, {"General", "SelNch"}}, "Labeled array for track selections"}; } cfgTrkSel; @@ -127,8 +126,10 @@ struct PidLongRange { O2_DEFINE_CONFIGURABLE(cfgMinMultForCorrelations, int, 0, "minimum multiplicity for correlations") O2_DEFINE_CONFIGURABLE(cfgMaxMultForCorrelations, int, 20, "maximum multiplicity for correlations") O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") O2_DEFINE_CONFIGURABLE(cfgMinCentForCorrelations, int, 0, "minimum centrality for correlations") O2_DEFINE_CONFIGURABLE(cfgMaxCentForCorrelations, int, 20, "maximum centrality for correlations") + O2_DEFINE_CONFIGURABLE(cfgUseCol2ForMixedEvSel, bool, true, "Use Mult/Cent cut on collision 2 during mixed event"); O2_DEFINE_CONFIGURABLE(cfgEvSelRCTflags, std::string, "", "keep empty to disable, usage: 'CentralBarrelTracking (CBT)', 'CBT_hadronPID' ") Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt.front().data(), 14, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kIsGoodITSLayer0123", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; } cfgEvSel; @@ -204,7 +205,7 @@ struct PidLongRange { ConfigurableAxis axisTpcNcls{"axisTpcNcls", {500, 0, 500}, "number of TPC clusters used for PID"}; // Axes for long-range correlations QA - ConfigurableAxis axisAmplitudeFt0{"axisAmplitudeFt0a", {5000, 0, 1000}, "FT0A amplitude"}; + ConfigurableAxis axisAmplitudeFt0{"axisAmplitudeFt0", {5000, 0, 1000}, "FT0A amplitude"}; ConfigurableAxis axisChannelFt0aAxis{"axisChannelFt0aAxis", {96, 0.0, 96.0}, "FT0A channel"}; ConfigurableAxis axisChannelFt0cAxis{"axisChannelFt0cAxis", {96, 0.0, 96.0}, "FT0C channel"}; ConfigurableAxis cfgFITamp{"cfgFITamp", {1000, 0, 5000}, "FT0 amplitude"}; @@ -281,7 +282,7 @@ struct PidLongRange { }; enum DetectorType { UseTPC = 0, - UseTof, + UseTOF, UseITS }; enum Stage { @@ -512,7 +513,6 @@ struct PidLongRange { histos.add("Nch_corrected", "N_{ch} corrected", {HistType::kTH1D, {axisMult}}); histos.add("Centrality", "Centrality", {HistType::kTH1D, {axisCent}}); histos.add("CentralityWeighted", "Centrality (weighted)", {HistType::kTH1D, {axisCent}}); - histos.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisMult, axisMult}}); } if (doprocessSameTpcFt0 || doprocessQA) { @@ -566,7 +566,6 @@ struct PidLongRange { histos.add("FT0Amp", "", {HistType::kTH2F, {axisChID, cfgFITamp}}); histos.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, cfgFITamp}}); - histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event } if (doprocessSameFt0aFt0c) { @@ -581,27 +580,29 @@ struct PidLongRange { histos.add("FT0Amp", "", {HistType::kTH2F, {axisChID, cfgFITamp}}); histos.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, cfgFITamp}}); - histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event } + histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + histos.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisMult, axisMult}}); + LOGF(info, "Initializing correlation container"); - // Initialize Nch-related histograms and containers + // Initialize containers std::vector corrAxisTpcFt0a = {{axisSample}, {axisVertex, "z-vtx (cm)"}, {axisEventClass}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEtaTpcFt0a, "#Delta#eta"}, {axisPtTrigger, "p_{T} (GeV/c)"}, - {axisParticle, "Particle, 0 = charged, 1 = pion, 2 = kaon, 3 = proton"}}; + {axisParticle, "Particle, 0 = charged, 1 = pion, 2 = kaon, 3 = proton"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; std::vector corrAxisTpcFt0c = {{axisSample}, {axisVertex, "z-vtx (cm)"}, {axisEventClass}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEtaTpcFt0c, "#Delta#eta"}, {axisPtTrigger, "p_{T} (GeV/c)"}, - {axisParticle, "Particle, 0 = charged, 1 = pion, 2 = kaon, 3 = proton"}}; + {axisParticle, "Particle, 0 = charged, 1 = pion, 2 = kaon, 3 = proton"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; std::vector corrAxisFt0aFt0c = {{axisSample}, {axisVertex, "z-vtx (cm)"}, @@ -636,7 +637,7 @@ struct PidLongRange { double getCentrality(TCollision const& collision) { double cent = 0.0; - switch (cfgTrkSel.cfgCentEstimator) { + switch (cfgEvSel.cfgCentEstimator) { case UseCentFT0C: cent = collision.centFT0C(); break; @@ -866,7 +867,7 @@ struct PidLongRange { } auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[UseOccupancy][EvCut1] && (occupancy > cfgEvSel.cfgCutOccupancyLow || occupancy < cfgEvSel.cfgCutOccupancyHigh)) { + if (eventCuts[UseOccupancy][EvCut1] && (occupancy > cfgEvSel.cfgCutOccupancyLow && occupancy < cfgEvSel.cfgCutOccupancyHigh)) { histos.fill(HIST("hPassedEventSelection"), UseOccupancy); } } @@ -1029,9 +1030,9 @@ struct PidLongRange { isDetectedKaon = nSigmaToUse[IndexKaonUp] < nSigmaVals[IndexKaonUp][useIndexDetector] && nSigmaToUse[IndexKaonUp] > nSigmaVals[IndexKaonLow][useIndexDetector]; isDetectedProton = nSigmaToUse[IndexProtonUp] < nSigmaVals[IndexProtonUp][useIndexDetector] && nSigmaToUse[IndexProtonUp] > nSigmaVals[IndexProtonLow][useIndexDetector]; - isTofPion = nSigmaTOF[IndexPionUp] < nSigmaVals[IndexPionUp][UseTof] && nSigmaTOF[IndexPionUp] > nSigmaVals[IndexPionLow][UseTof]; - isTofKaon = nSigmaTOF[IndexKaonUp] < nSigmaVals[IndexKaonUp][UseTof] && nSigmaTOF[IndexKaonUp] > nSigmaVals[IndexKaonLow][UseTof]; - isTofProton = nSigmaTOF[IndexProtonUp] < nSigmaVals[IndexProtonUp][UseTof] && nSigmaTOF[IndexProtonUp] > nSigmaVals[IndexProtonLow][UseTof]; + isTofPion = nSigmaTOF[IndexPionUp] < nSigmaVals[IndexPionUp][UseTOF] && nSigmaTOF[IndexPionUp] > nSigmaVals[IndexPionLow][UseTOF]; + isTofKaon = nSigmaTOF[IndexKaonUp] < nSigmaVals[IndexKaonUp][UseTOF] && nSigmaTOF[IndexKaonUp] > nSigmaVals[IndexKaonLow][UseTOF]; + isTofProton = nSigmaTOF[IndexProtonUp] < nSigmaVals[IndexProtonUp][UseTOF] && nSigmaTOF[IndexProtonUp] > nSigmaVals[IndexProtonLow][UseTOF]; if (track.pt() > cfgPIDConfigs.cfgTofPtCut && !track.hasTOF()) { return -1; @@ -1305,22 +1306,23 @@ struct PidLongRange { if (!trackSelected(track1)) { continue; } - if (!getEfficiencyCorrection(triggerWeight, track1.pt(), track1.eta(), posZ)) { + if (!getEfficiencyCorrection(triggerWeight, track1.pt(), track1.eta(), posZ)) { // Keep efficiency string empty to disable, efficiency is not used for tpc-ft0 correlations continue; } - fillTrackQA(track1, UseCharged, eventClass, Before, triggerWeight); - fillTrackQA(track1, UsePions, eventClass, Before, triggerWeight); - fillTrackQA(track1, UseKaons, eventClass, Before, triggerWeight); - fillTrackQA(track1, UseProtons, eventClass, Before, triggerWeight); + if (system == SameEvent) { + fillTrackQA(track1, UseCharged, eventClass, Before, triggerWeight); + fillTrackQA(track1, UsePions, eventClass, Before, triggerWeight); + fillTrackQA(track1, UseKaons, eventClass, Before, triggerWeight); + fillTrackQA(track1, UseProtons, eventClass, Before, triggerWeight); + } int pidIndex = getNsigmaPID(track1); - if (pidIndex > UseCharged) { - fillTrackQA(track1, pidIndex, eventClass, After, triggerWeight); - } - if (system == SameEvent) { + if (pidIndex > UseCharged) { + fillTrackQA(track1, pidIndex, eventClass, After, triggerWeight); + } if (corType == IndexFT0C) { histos.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, eventClass, track1.pt(), UseCharged, eventWeight * triggerWeight); if (pidIndex > UseCharged) { @@ -1359,18 +1361,18 @@ struct PidLongRange { histos.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); histos.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } - sameTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), UseCharged, ampl * eventWeight * triggerWeight); + sameTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), UseCharged, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); if (pidIndex > UseCharged) { - sameTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), pidIndex, ampl * eventWeight * triggerWeight); + sameTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), pidIndex, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } else if (corType == IndexFT0C) { if (cfgGeneral.cfgQABasic) { histos.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); histos.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } - sameTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), UseCharged, ampl * eventWeight * triggerWeight); + sameTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), UseCharged, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); if (pidIndex > UseCharged) { - sameTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), pidIndex, ampl * eventWeight * triggerWeight); + sameTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), pidIndex, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } } else if (system == MixedEvent) { @@ -1379,18 +1381,18 @@ struct PidLongRange { histos.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); histos.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } - mixedTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), UseCharged, ampl * eventWeight * triggerWeight); + mixedTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), UseCharged, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); if (pidIndex > UseCharged) { - mixedTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), pidIndex, ampl * eventWeight * triggerWeight); + mixedTpcFt0a->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), pidIndex, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } else if (corType == IndexFT0C) { if (cfgGeneral.cfgQABasic) { histos.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); histos.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } - mixedTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), UseCharged, ampl * eventWeight * triggerWeight); + mixedTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), UseCharged, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); if (pidIndex > UseCharged) { - mixedTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, deltaPhi, deltaEta, track1.pt(), pidIndex, ampl * eventWeight * triggerWeight); + mixedTpcFt0c->getCorrHist()->Fill(0, fSampleIndex, posZ, eventClass, track1.pt(), pidIndex, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } } @@ -1499,8 +1501,6 @@ struct PidLongRange { histos.fill(HIST("zVtx"), collision.posZ()); - histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - auto multiplicity = static_cast(tracks.size()); if (cfgGeneral.cfgQABasic) { @@ -1522,6 +1522,8 @@ struct PidLongRange { return; } + histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent; const auto& ft0 = collision.foundFT0(); @@ -1536,7 +1538,6 @@ struct PidLongRange { void processMixedTpcFt0(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) { - auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); auto mult = associatedTracks.size(); @@ -1574,8 +1575,6 @@ struct PidLongRange { continue; } - histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); int currentRunNumber = bc.runNumber(); if (!cfgGeneral.cfgRunRemoveList.value.empty()) { @@ -1587,23 +1586,31 @@ struct PidLongRange { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); - auto multiplicity = static_cast(tracks1.size()); + auto multiplicity1 = static_cast(tracks1.size()); + auto multiplicity2 = static_cast(tracks2.size()); if (cfgGeneral.cfgStrictTrackCounter) { - nchCounter(tracks1, multiplicity, false); + nchCounter(tracks1, multiplicity1, false); + if (cfgEvSel.cfgUseCol2ForMixedEvSel) { + nchCounter(tracks2, multiplicity2, false); + } } - if (cfgEvSel.cfgSelCollByNch && (multiplicity > cfgEvSel.cfgMaxMultForCorrelations || multiplicity < cfgEvSel.cfgMinMultForCorrelations)) { + if (cfgEvSel.cfgSelCollByNch && (multiplicity1 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity1 < cfgEvSel.cfgMinMultForCorrelations)) { + continue; + } + if (cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (multiplicity2 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity2 < cfgEvSel.cfgMinMultForCorrelations)) { continue; } if (!cfgEvSel.cfgSelCollByNch && (cent1 > cfgEvSel.cfgMaxCentForCorrelations || cent1 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - if (!cfgEvSel.cfgSelCollByNch && (cent2 > cfgEvSel.cfgMaxCentForCorrelations || cent2 < cfgEvSel.cfgMinCentForCorrelations)) { + if (!cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (cent2 > cfgEvSel.cfgMaxCentForCorrelations || cent2 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent1; + histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity1 : cent1; float eventWeight = 1.0f; @@ -1663,7 +1670,6 @@ struct PidLongRange { histos.fill(HIST("CentralityWeighted"), cent, weightCent); histos.fill(HIST("zVtx"), collision.posZ()); - histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYieldFt0aFt0c(collision, tracks); @@ -1688,6 +1694,8 @@ struct PidLongRange { return; } + histos.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent; const auto& ft0 = collision.foundFT0(); @@ -1737,8 +1745,6 @@ struct PidLongRange { continue; } - histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); int currentRunNumber = bc.runNumber(); if (!cfgGeneral.cfgRunRemoveList.value.empty()) { @@ -1749,23 +1755,32 @@ struct PidLongRange { loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); - auto multiplicity = static_cast(tracks1.size()); + auto multiplicity1 = static_cast(tracks1.size()); + auto multiplicity2 = static_cast(tracks2.size()); if (cfgGeneral.cfgStrictTrackCounter) { - nchCounter(tracks1, multiplicity, false); + nchCounter(tracks1, multiplicity1, false); + if (cfgEvSel.cfgUseCol2ForMixedEvSel) { + nchCounter(tracks2, multiplicity2, false); + } } - if (cfgEvSel.cfgSelCollByNch && (multiplicity > cfgEvSel.cfgMaxMultForCorrelations || multiplicity < cfgEvSel.cfgMinMultForCorrelations)) { + if (cfgEvSel.cfgSelCollByNch && (multiplicity1 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity1 < cfgEvSel.cfgMinMultForCorrelations)) { + continue; + } + if (cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (multiplicity2 > cfgEvSel.cfgMaxMultForCorrelations || multiplicity2 < cfgEvSel.cfgMinMultForCorrelations)) { continue; } if (!cfgEvSel.cfgSelCollByNch && (cent1 > cfgEvSel.cfgMaxCentForCorrelations || cent1 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - if (!cfgEvSel.cfgSelCollByNch && (cent2 > cfgEvSel.cfgMaxCentForCorrelations || cent2 < cfgEvSel.cfgMinCentForCorrelations)) { + if (!cfgEvSel.cfgSelCollByNch && cfgEvSel.cfgUseCol2ForMixedEvSel && (cent2 > cfgEvSel.cfgMaxCentForCorrelations || cent2 < cfgEvSel.cfgMinCentForCorrelations)) { continue; } - auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity : cent1; + histos.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + + auto eventClass = (cfgEvSel.cfgSelCollByNch) ? multiplicity1 : cent1; float eventWeight = 1.0f;