From 6ea2f1643fb5d4709e17a083ee3a7d07b6e79c02 Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty Date: Sat, 25 Apr 2026 14:56:20 +0200 Subject: [PATCH 1/4] Add sperate task for SH analysis with ITS PIDNsigma --- PWGCF/FemtoUniverse/Tasks/CMakeLists.txt | 7 +- ...TrackTrackSpherHarMultKtExtendedITSPID.cxx | 1511 +++++++++++++++++ 2 files changed, 1517 insertions(+), 1 deletion(-) create mode 100644 PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index 346188d08fd..16c82dbaf26 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -44,11 +44,16 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-track-threedrelmom-mult-kt-e PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(o2-analysis-cf-femtouniverse-pair-track-track-spherhar-mult-kt-extended +o2physics_add_dpl_workflow(femtouniverse-pair-track-track-spherhar-mult-kt-extended SOURCES femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-pair-track-track-spherhar-mult-kt-extended-itspid + SOURCES femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-debug-track SOURCES femtoUniverseDebugTrack.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx new file mode 100644 index 00000000000..bb155febb7e --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx @@ -0,0 +1,1511 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks and compute relative pair-momentum in three dimesnions +/// \remark This file is inherited from ~/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx on 17/06/2024 +/// \author Pritam Chakraborty, WUT Warsaw, pritam.chakraborty@pw.edu.pl + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis::femto_universe; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int NPart = 2; +static constexpr int NCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[NPart][NCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +enum ParticleNumber { + First, + Second +}; + +enum PairType { + PlusMinus, + PlusPlus, + MinusMinus +}; + +struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID { + + Service pdg; + + /// Particle selection part + + /// Table for both particles + struct : o2::framework::ConfigurableGroup { + Configurable confNsigmaCombined{"confNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > confTOFPtMin"}; + Configurable confNsigmaTPC{"confNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < confTOFPtMin"}; + Configurable confNsigmaITSTPCCombined{"confNsigmaITSTPCCombined", 3.0f, "ITS and TPC Pion Sigma (combined) for momentum < confTOFPtMin"}; + Configurable confIsElReject{"confIsElReject", false, "Is electron rejection activated"}; + Configurable confIsAddITSNsigma{"confIsAddITSNsigma", false, "Is ITS Pions nsigma added"}; + Configurable confNsigmaTPCElRejectMin{"confNsigmaTPCElRejectMin", 2.0f, "TPC Electron SigmaMin for momentum < confTOFPtMin"}; + Configurable confNsigmaTPCElRejectMax{"confNsigmaTPCElRejectMax", 2.0f, "TPC Electron SigmaMax for momentum < confTOFPtMin"}; + Configurable confTOFPtMin{"confTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; + Configurable confEtaMax{"confEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + Configurable confKaonPIDP1{"confKaonPIDP1", 0.3f, "mom range 1 for kaon PID."}; + Configurable confKaonPIDP2{"confKaonPIDP2", 0.45f, "mom range 2 for kaon PID."}; + Configurable confKaonPIDP3{"confKaonPIDP3", 0.55f, "mom range 3 for kaon PID."}; + Configurable confKaonPIDP4{"confKaonPIDP4", 1.5f, "mom range 4 for kaon PID."}; + + Configurable confKaonTPCNsigma1{"confKaonTPCNsigma1", 3.0f, "TPC Kaon NSigma for mom range 1."}; + Configurable confKaonTPCNsigma2{"confKaonTPCNsigma2", 2.0f, "TPC Kaon NSigma for mom range 2."}; + Configurable confKaonTPCNsigma3{"confKaonTPCNsigma3", 1.0f, "TPC Kaon NSigma for mom range 3."}; + Configurable confKaonTPCNsigma4{"confKaonTPCNsigma4", 3.0f, "TPC Kaon NSigma for mom range 4."}; + Configurable confKaonTPCNsigma5{"confKaonTPCNsigma5", 2.0f, "TPC Kaon NSigma for mom range 5."}; + Configurable confKaonTOFNsigma4{"confKaonTOFNsigma4", 3.0f, "TOF Kaon NSigma for mom range 4."}; + Configurable confKaonTOFNsigma5{"confKaonTOFNsigma5", 3.0f, "TOF Kaon NSigma for mom range 5."}; + + Configurable> confCutTable{"confCutTable", {cutsTable[0], NPart, NCuts, partNames, cutNames}, "Particle selections"}; + Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; + Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This Configurable needs to be the same as the one used in the producer task"}; + Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; + Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; + Configurable confIsCPRatITS{"confIsCPRatITS", false, "Close Pair check at ITS"}; + Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; + Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; + Configurable confIsCPRkT{"confIsCPRkT", true, "kT dependent deltaEta-deltaPhi cut for Close Pair Rejection"}; + Configurable confIsCPRFraction{"confIsCPRFraction", true, "Close Pair Rejection with fraction of merged points"}; + Configurable confTrkDCAxyMax{"confTrkDCAxyMax", 0.2, "Max DCA in xy "}; + Configurable confTrkDCAzMax{"confTrkDCAzMax", 0.2, "Max DCA in z "}; + Configurable confTrkTPCcRowsMin{"confTrkTPCcRowsMin", 80, "Min of TPC crossed rows"}; + Configurable confTrkTPCfClsMin{"confTrkTPCfClsMin", 0.83, "Min. fraction of crossed rows/findable TPC clusters"}; + Configurable confTrkTPCfracsClsMax{"confTrkTPCfracsClsMax", 1.0, "Max of fraction of TPC shared cluster "}; + Configurable confTrkTPCnClsMin{"confTrkTPCnClsMin", 80, "Min number of TPC clusters"}; + Configurable confTrkTPCsClsMax{"confTrkTPCsClsMax", 160, "Max number of TPC shared clusters"}; + Configurable confPairFracSharedTPCclsMin{"confPairFracSharedTPCclsMin", 0.0, "Min. fraction of TPC shared clusters between two closed tracks"}; + Configurable confPairFracSharedTPCclsMax{"confPairFracSharedTPCclsMax", 1.0, "Miax. fraction of TPC shared clusters between two closed tracks"}; + Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; + Configurable confUseCCImCut{"confUseCCImCut", false, "Fill SH within specific quadrants of qout-qside"}; + Configurable confMinqTcut{"confMinqTcut", 0.005, "Min. qT cut on filling SH"}; + Configurable confUse1stand3rd{"confUse1stand3rd", false, "Use first and third quadrants of qout-qside"}; + Configurable confUse2ndand4th{"confUse2ndand4th", false, "Use second and fourth quadrants of qout-qside"}; + Configurable confIsFillAngqLCMS{"confIsFillAngqLCMS", true, "Fill qLCMS vs dEta vs dPhi"}; + Configurable confCPRDistMax{"confCPRDistMax", 0.0, "Max. radial seperation between two closed-pairs"}; + Configurable confCPRFracMax{"confCPRFracMax", 0.0, "Max. allowed fraction bad to all TPC points of radial seperation between two closed-pairs"}; + Configurable confCPRDphiAvgOrDist{"confCPRDphiAvgOrDist", true, "Close Pair Rejection by radial or angular seperation"}; + Configurable confIsCircularCut{"confIsCircularCut", true, "Close Pair Rejection within circular area"}; + Configurable confIs1D{"confIs1D", true, "Filling 1D 2k* dist. in MC truth"}; + Configurable confisIdenLCMS{"confisIdenLCMS", true, "Choosing identical or non-identical pairs in LCMS"}; + Configurable confIsWeight{"confIsWeight", true, "Fill quantum weight"}; + Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; + Configurable confIsfilldEtadPhiTPCcls{"confIsfilldEtadPhiTPCcls", false, "Filling of 3D histogram PairFracSharedTPCcls vs. dEta vs. dPhiStar"}; + Configurable confRandValue{"confRandValue", 0.5, "Value of random-number generator to shuffle pair"}; + + Configurable> confCPRdeltaEtaCutMaxVec{"confCPRdeltaEtaCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR"}; + Configurable> confCPRdeltaEtaCutMinVec{"confCPRdeltaEtaCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR"}; + Configurable> confCPRdeltaPhiCutMaxVec{"confCPRdeltaPhiCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR"}; + Configurable> confCPRdeltaPhiCutMinVec{"confCPRdeltaPhiCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR"}; + + Configurable> confCPRdeltaEtaCutFractionMaxVec{"confCPRdeltaEtaCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR Fraction"}; + Configurable> confCPRdeltaEtaCutFractionMinVec{"confCPRdeltaEtaCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR Fraction"}; + Configurable> confCPRdeltaPhiCutFractionMaxVec{"confCPRdeltaPhiCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR Fraction"}; + Configurable> confCPRdeltaPhiCutFractionMinVec{"confCPRdeltaPhiCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR Fraction"}; + + ConfigurableAxis confDeltaEtaAxis{"confDeltaEtaAxis", {100, -0.15, 0.15}, "DeltaEta"}; + ConfigurableAxis confDeltaPhiStarAxis{"confDeltaPhiStarAxis", {100, -0.15, 0.15}, "DeltaPhiStar"}; + } twotracksconfigs; + + using FemtoFullParticles = soa::Join; + // Filters for selecting particles (both p1 and p2) + Filter trackAdditionalfilter = ((nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax) && + (aod::track::dcaXY <= twotracksconfigs.confTrkDCAxyMax) && + (aod::track::dcaZ <= twotracksconfigs.confTrkDCAzMax) && + (aod::femtouniverseparticle::tpcNClsCrossedRows >= static_cast(twotracksconfigs.confTrkTPCcRowsMin)) && + (aod::femtouniverseparticle::tpcFractionSharedCls <= twotracksconfigs.confTrkTPCfracsClsMax) && + (aod::femtouniverseparticle::tpcNClsFound >= static_cast(twotracksconfigs.confTrkTPCnClsMin)) && + (aod::track::tpcNClsShared <= static_cast(twotracksconfigs.confTrkTPCsClsMax))); + + using FilteredFemtoFullParticles = soa::Filtered; + // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this optionconfIsCPRkT + using FemtoRecoParticles = soa::Join; + using FilteredFemtoRecoParticles = soa::Filtered; + + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + using FemtoTruthParticles = soa::Join; + Preslice perColMCTruth = aod::femtouniverseparticle::fdCollisionId; + + /// Particle 1 + struct : o2::framework::ConfigurableGroup { + Configurable confPDGCodePartOne{"confPDGCodePartOne", 211, "Particle 1 - PDG code"}; + Configurable confPIDPartOne{"confPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable confPtLowPart1{"confPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable confPtHighPart1{"confPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable confChargePart1{"confChargePart1", 1, "Particle 1 sign"}; + } trackonefilter; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; + Partition partsOneMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); + + // + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + struct : o2::framework::ConfigurableGroup { + Configurable confPDGCodePartTwo{"confPDGCodePartTwo", 211, "Particle 2 - PDG code"}; + // Configurable confCutPartTwo{"confCutPartTwo", 5542474, "Particle 2 - Selection bit"}; + Configurable confPIDPartTwo{"confPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + Configurable confPtLowPart2{"confPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable confPtHighPart2{"confPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable confChargePart2{"confChargePart2", -1, "Particle 2 sign"}; + } tracktwofilter; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; + Partition partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; + Partition partsTwoMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The Configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// Event part + Configurable confV0MLow{"confV0MLow", 0.0, "Lower limit for V0M multiplicity"}; + Configurable confV0MHigh{"confV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; + Configurable confTPCOccupancyLow{"confTPCOccupancyLow", 0, "Lower limit for TPC occupancy"}; + Configurable confTPCOccupancyHigh{"confTPCOccupancyHigh", 500, "Higher limit for TPC occupancy"}; + Configurable confIntRateLow{"confIntRateLow", 0.0, "Lower limit for interaction rate"}; + Configurable confIntRateHigh{"confIntRateHigh", 10000.0, "Higher limit for interaction rate"}; + Configurable confIsCent{"confIsCent", true, "Condition to choose centrality of multiplicity for mixing"}; + + Filter collfilterFDtable = (o2::aod::femtouniversecollision::multV0M > confV0MLow) && (o2::aod::femtouniversecollision::multV0M < confV0MHigh); + Filter collfilterFDExttable = (o2::aod::femtouniversecollision::interactionRate > confIntRateLow) && (o2::aod::femtouniversecollision::interactionRate < confIntRateHigh) && + (o2::aod::femtouniversecollision::occupancy >= confTPCOccupancyLow) && (o2::aod::femtouniversecollision::occupancy < confTPCOccupancyHigh); + using FilteredFDCollisions = soa::Filtered>; + using FilteredFDCollision = FilteredFDCollisions::iterator; + // Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on Configurable + + /// Particle part + ConfigurableAxis confTempFitVarBins{"confTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 12.5f, 15.0f, 17.5f, 20.0f, 22.5f, 25.0f, 27.5f, 30.0f, 32.5f, 35.0f, 37.5f, 40.0f, 42.5f, 45.0f, 47.5f, 50.0f, 52.5f, 55.0f, 57.5f, 60.0f, 62.5f, 65.0f, 67.5f, 70.5f, 75.0f, 80.0f, 90.0f, 100.0f, 99999.f}, "Mixing bins - centrality"}; + ConfigurableAxis confMultBinsMult{"confMultBinsMult", {VARIABLE_WIDTH, 0.0f, 400.0f, 800.0f, 1200.0f, 1600.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f, 10000.0f, 11000.0f, 12000.0f, 13000.0f, 14000.0f, 15000.0f, 16000.0f, 17000.0f, 18000.0f, 99999.f}, "Mixing bins - centrality"}; + ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; + ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; + ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis confmultBins3D{"confmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBinsCent}, true}; + ColumnBinningPolicy colBinningNtr{{confVtxBins, confMultBinsMult}, true}; + + ConfigurableAxis confkstarBins{"confkstarBins", {60, 0.0, 0.3}, "binning kstar"}; + ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable confIsLCMS{"confIsLCMS", true, "Choosing LCMS or PRF"}; + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; + Configurable confLMax{"confLMax", 2, "Maximum value of l"}; + Configurable cfgProcessPM{"cfgProcessPM", false, "Process particles of the opposite charge"}; + Configurable cfgProcessPP{"cfgProcessPP", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMM{"cfgProcessMM", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; + Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; + Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; + + Configurable confRejectGammaPair{"confRejectGammaPair", false, "Additional check to reject e+e- pairs base on theta and minv"}; + Configurable confMaxEEMinv{"confMaxEEMinv", 0.002, "Max. minv of e-e+ pair for gamma pair rejection"}; + Configurable confMaxDTheta{"confMaxDTheta", 0.008, "Max. DeltaTheta of pair for gamma pair rejection"}; + + FemtoUniverseSHContainer sameEventCont; + FemtoUniverseSHContainer mixedEventCont; + + FemtoUniverseSHContainer sameEventContPP; + FemtoUniverseSHContainer mixedEventContPP; + + FemtoUniverseSHContainer sameEventContMM; + FemtoUniverseSHContainer mixedEventContMM; + + FemtoUniverseContainer sameEventCont1dpp; + FemtoUniverseContainer mixedEventCont1dpp; + FemtoUniverseContainer sameEventCont1dmm; + FemtoUniverseContainer mixedEventCont1dmm; + + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseTrackSelection trackCuts; + + PairSHCentMultKt sameEventMultCont; + PairSHCentMultKt mixedEventMultCont; + + PairSHCentMultKt sameEventMultContPP; + PairSHCentMultKt mixedEventMultContPP; + + PairSHCentMultKt sameEventMultContMM; + PairSHCentMultKt mixedEventMultContMM; + + float mass1 = -1; + float mass2 = -1; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistry1D{"Correlations1D", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPM{"CorrelationsPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPP{"CorrelationsPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryMM{"CorrelationsMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + HistogramRegistry sameMultRegistryPM{"sameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPM{"mixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry sameMultRegistryPP{"sameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPP{"mixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry sameMultRegistryMM{"sameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryMM{"mixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + TRandom2* randgen; + + // PID for protons + bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using Configurables: + // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // confNsigmaTPC -> TPC Sigma for momentum < 0.5 + // confNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 + + if (mom < twotracksconfigs.confTOFPtMin) { + if (std::abs(nsigmaTPCPr) < twotracksconfigs.confNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.confNsigmaCombined) { + return true; + } else { + return false; + } + } + return false; + } + + bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < twotracksconfigs.confKaonPIDP1) { // 0.0-0.3 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma1) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP2) { // 0.30 - 0.45 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma2) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP3) { // 0.45-0.55 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma3) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP4) { // 0.55-1.5 (now we use TPC and TOF) + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma4) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma4)) { + { + return true; + } + } else { + return false; + } + } else if (mom > twotracksconfigs.confKaonPIDP4) { // 1.5 - + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma5) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma5)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool isPionNSigma(float mom, float nsigmaITSPi, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCElReject) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using Configurables: + // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // confNsigmaTPC -> TPC Sigma for momentum < 0.5 + // confNsigmaCombined -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < twotracksconfigs.confTOFPtMin) { + if (twotracksconfigs.confIsElReject) { + if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC) && (nsigmaTPCElReject < twotracksconfigs.confNsigmaTPCElRejectMin || nsigmaTPCElReject > twotracksconfigs.confNsigmaTPCElRejectMax)) { + return true; + } else { + return false; + } + } else if (twotracksconfigs.confIsAddITSNsigma) { + if (std::hypot(nsigmaITSPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaITSTPCCombined) { + return true; + } else { + return false; + } + } else { + if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC)) { + return true; + } else { + return false; + } + } + } else { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool isParticleNSigma(ParticleNumber particle_number, float mom, float nsigmaITSPi, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCElReject) + { + if (particle_number == ParticleNumber::First) { + switch (trackonefilter.confPDGCodePartOne) { + case 2212: // Proton + case -2212: // Antiproton + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + break; + case 321: // Kaon+ + case -321: // Kaon- + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else if (particle_number == ParticleNumber::Second) { + switch (tracktwofilter.confPDGCodePartTwo) { + case 2212: // Proton + case -2212: // Antiproton + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + break; + case 321: // Kaon+ + case -321: // Kaon- + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else { + LOGF(fatal, "Wrong number of particle chosen! It should be First or Second."); + } + return false; + } + + void init(InitContext&) + { + + colBinningCent = ColumnBinningPolicy{{confVtxBins, confMultBinsCent}, true}; + colBinningNtr = ColumnBinningPolicy{{confVtxBins, confMultBinsMult}, true}; + + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + + trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + + mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); + mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); + + if (cfgProcessPM) { + if (!cfgProcessKtMt3DCF) { + sameEventCont.init(&resultRegistryPM, confkstarBins, confLMax); + mixedEventCont.init(&resultRegistryPM, confkstarBins, confLMax); + sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultCont.init(&sameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultCont.init(&mixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + } + + if (cfgProcessPP) { + if (!cfgProcessKtMt3DCF) { + sameEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); + mixedEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); + sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultContPP.init(&sameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContPP.init(&mixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + sameEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } + + if (cfgProcessMM) { + if (!cfgProcessKtMt3DCF) { + sameEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); + mixedEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); + sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultContMM.init(&sameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContMM.init(&mixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + sameEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } + + pairCleaner.init(&qaRegistry); + if (twotracksconfigs.confIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMin.value, twotracksconfigs.confCPRdeltaPhiCutMax.value, twotracksconfigs.confCPRdeltaEtaCutMin.value, twotracksconfigs.confCPRdeltaEtaCutMax.value, twotracksconfigs.confCPRChosenRadii.value, twotracksconfigs.confCPRPlotPerRadii.value); + pairCloseRejection.init_kT(&resultRegistry, confKtKstarBins, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMinVec.value, twotracksconfigs.confCPRdeltaPhiCutMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutMinVec.value, twotracksconfigs.confCPRdeltaEtaCutMaxVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMinVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMinVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMaxVec.value, twotracksconfigs.confIsfilldEtadPhiTPCcls); + } + + vPIDPartOne = trackonefilter.confPIDPartOne.value; + vPIDPartTwo = tracktwofilter.confPIDPartTwo.value; + kNsigma = twotracksconfigs.confTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col, bool IsCent) + { + if (IsCent) { + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningCent.getBin({col.posZ(), col.multV0M()})); + } else { + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningNtr.getBin({col.posZ(), col.multNtr()})); + } + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, PairType contType, bool fillQA) + { + /// Histogramming same event + if ((contType == PairType::PlusMinus || contType == PairType::PlusPlus) && fillQA) { + for (const auto& part : groupPartsOne) { + if (!isParticleNSigma(ParticleNumber::First, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + continue; + } + trackHistoPartOne.fillQA(part); + if (twotracksconfigs.confIsAddITSNsigma) { + trackHistoPartOne.fillQAITSPID<>(part); + } + trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); + } + } + + if ((contType == PairType::PlusMinus || contType == PairType::MinusMinus) && fillQA) { + for (const auto& part : groupPartsTwo) { + if (!isParticleNSigma(ParticleNumber::Second, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + continue; + } + trackHistoPartTwo.fillQA(part); + if (twotracksconfigs.confIsAddITSNsigma) { + trackHistoPartTwo.fillQAITSPID<>(part); + } + } + } + + if (contType == PairType::PlusMinus) { + + /// Now build the combinations for non-identical particle pairs + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!isParticleNSigma(ParticleNumber::First, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + } else { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { + + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + if (twotracksconfigs.confIsCPRFraction) { + if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::same, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { + continue; + } + } + } else { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(part1, part2, parts)) { + continue; + } + + std::vector f3d; + double kv; + float outsideref = 0.0; + switch (contType) { + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); + } + break; + } + + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); + } + break; + } + default: + break; + } + } + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(FilteredFDCollision const& col, + FilteredFemtoFullParticles const& parts) + { + fillCollision(col, confIsCent); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + bool fillQA = true; + randgen = new TRandom2(0); + + if (confIsCent) { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); + } + } else { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FdCollision const& col, + FilteredFemtoRecoParticles const& parts, + aod::FdMCParticles const&) + { + fillCollision(col, confIsCent); + + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + bool fillQA = true; + randgen = new TRandom2(0); + + if (confIsCent) { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); + } + } else { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType, bool fillQA) + { + + randgen = new TRandom2(0); + /// Histogramming same event + if ((cfgProcessPM || cfgProcessPP) && fillQA) { + for (const auto& part : groupPartsOne) { + if (part.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) { + int pdgCode = static_cast(part.tempFitVar()); + const auto& pdgParticle = pdg->GetParticle(pdgCode); + if (pdgParticle) { + trackHistoPartOne.fillQA(part); + } + } + } + } + + if ((cfgProcessPM || cfgProcessMM) && fillQA) { + for (const auto& part : groupPartsTwo) { + if (part.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) { + int pdgCode = static_cast(part.tempFitVar()); + const auto& pdgParticle = pdg->GetParticle(pdgCode); + if (pdgParticle) { + trackHistoPartTwo.fillQA(part); + } + } + } + } + + if (cfgProcessPM) { + + /// Now build the combinations for non-identical particle pairs + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + int pdgCodePartOne = static_cast(p1.tempFitVar()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.tempFitVar()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); + if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } else { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { + + int pdgCodePartOne = static_cast(p1.tempFitVar()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.tempFitVar()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + double rand; + rand = randgen->Rndm(); + std::vector f3d; + if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { + + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + + switch (contType) { + case PairType::PlusPlus: { + if (twotracksconfigs.confIs1D) { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + float weight = f3d[5]; + sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } else { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + break; + } + + case PairType::MinusMinus: { + if (twotracksconfigs.confIs1D) { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + float weight = f3d[5]; + sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } else { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + break; + } + default: + break; + } + } + } + } + delete randgen; + } + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMCTruth(o2::aod::FdCollision const& col, + FemtoTruthParticles const&) + { + fillCollision(col, confIsCent); + + auto thegroupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + bool fillQA = true; + + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + if (confIsCent) { + if (cfgProcessPM) { + doSameEventMCTruth(thegroupPartsOne, thegroupPartsTwo, col.multV0M(), pairType, fillQA); + } + if (cfgProcessPP) { + doSameEventMCTruth(thegroupPartsOne, thegroupPartsOne, col.multV0M(), pairType, fillQA); + } + if (cfgProcessMM) { + doSameEventMCTruth(thegroupPartsTwo, thegroupPartsTwo, col.multV0M(), pairType, fillQA); + } + } else { + if (cfgProcessPM) { + doSameEventMCTruth(thegroupPartsOne, thegroupPartsTwo, col.multNtr(), pairType, fillQA); + } + if (cfgProcessPP) { + doSameEventMCTruth(thegroupPartsOne, thegroupPartsOne, col.multNtr(), pairType, fillQA); + } + if (cfgProcessMM) { + doSameEventMCTruth(thegroupPartsTwo, thegroupPartsTwo, col.multNtr(), pairType, fillQA); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEventMCTruth, "Enable processing same event for MC truth", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, PairType contType) + { + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::mixed, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + if (twotracksconfigs.confIsCPRFraction) { + if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::mixed, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { + continue; + } + } + } else { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + std::vector f3d; + double kv; + float outsideref = 0.0; + + switch (contType) { + case PairType::PlusMinus: { + mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + break; + } + + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); + } + break; + } + + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); + } + break; + } + + default: + break; + } + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param subscribe to the femtoUniverseParticleTable + void processMixedEventCent(FilteredFDCollisions const& cols, + FilteredFemtoFullParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + if (cfgProcessPM) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventCent, "Enable processing mixed events for centrality", true); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventNtr(FilteredFDCollisions const& cols, + FilteredFemtoFullParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + if (cfgProcessPM) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventNtr, "Enable processing mixed events for centrality", false); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMCCent(o2::aod::FdCollisions const& cols, + soa::Join const&, + o2::aod::FdMCParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + if (cfgProcessPM) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventMCCent, "Enable processing mixed events MC", false); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMCNtr(o2::aod::FdCollisions const& cols, + soa::Join const&, + o2::aod::FdMCParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + if (cfgProcessPM) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventMCNtr, "Enable processing mixed events MC", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType) + { + randgen = new TRandom2(0); + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + int pdgCodePartOne = static_cast(p1.tempFitVar()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.tempFitVar()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + double rand; + rand = randgen->Rndm(); + std::vector f3d; + + if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { + + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + switch (contType) { + case PairType::PlusMinus: { + mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + break; + } + + case PairType::PlusPlus: { + if (twotracksconfigs.confIs1D) { + float weight = 1.0; + mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } else { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + break; + } + + case PairType::MinusMinus: { + if (twotracksconfigs.confIs1D) { + float weight = 1.0; + mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } else { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + break; + } + default: + break; + } + } + } + delete randgen; + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventNtrMCTruth(o2::aod::FdCollisions const& cols, + FemtoTruthParticles const&) + { + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + if (cfgProcessPM) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventNtrMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventCentMCTruth(o2::aod::FdCollisions const& cols, + FemtoTruthParticles const&) + { + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + if (cfgProcessPM) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventCentMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} \ No newline at end of file From 11a4cd959caa37215db907311cf26a0b94850f85 Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty Date: Sat, 25 Apr 2026 14:57:03 +0200 Subject: [PATCH 2/4] Remove ITS PID segment, fix O2-linter errors --- ...irTaskTrackTrackSpherHarMultKtExtended.cxx | 235 +++++++++--------- 1 file changed, 120 insertions(+), 115 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 4c5ff1b4cc5..7d81dafaa05 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -62,22 +62,27 @@ using namespace o2::soa; namespace { -static constexpr int nPart = 2; -static constexpr int nCuts = 5; +static constexpr int NPart = 2; +static constexpr int NCuts = 5; static const std::vector partNames{"PartOne", "PartTwo"}; static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; -static const float cutsTable[nPart][nCuts]{ +static const float cutsTable[NPart][NCuts]{ {4.05f, 1.f, 3.f, 3.f, 100.f}, {4.05f, 1.f, 3.f, 3.f, 100.f}}; } // namespace +enum ParticleNumber { + First, + Second +}; + enum PairType { PlusMinus, PlusPlus, MinusMinus }; -struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { +struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Service pdg; @@ -89,13 +94,25 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable confNsigmaTPC{"confNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < confTOFPtMin"}; Configurable confNsigmaITSTPCCombined{"confNsigmaITSTPCCombined", 3.0f, "ITS and TPC Pion Sigma (combined) for momentum < confTOFPtMin"}; Configurable confIsElReject{"confIsElReject", false, "Is electron rejection activated"}; - Configurable confIsAddITSNsigma{"confIsAddITSNsigma", false, "Is ITS Pions nsigma added"}; Configurable confNsigmaTPCElRejectMin{"confNsigmaTPCElRejectMin", 2.0f, "TPC Electron SigmaMin for momentum < confTOFPtMin"}; Configurable confNsigmaTPCElRejectMax{"confNsigmaTPCElRejectMax", 2.0f, "TPC Electron SigmaMax for momentum < confTOFPtMin"}; Configurable confTOFPtMin{"confTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; Configurable confEtaMax{"confEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; - Configurable> confCutTable{"confCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable confKaonPIDP1{"confKaonPIDP1", 0.3f, "mom range 1 for kaon PID."}; + Configurable confKaonPIDP2{"confKaonPIDP2", 0.45f, "mom range 2 for kaon PID."}; + Configurable confKaonPIDP3{"confKaonPIDP3", 0.55f, "mom range 3 for kaon PID."}; + Configurable confKaonPIDP4{"confKaonPIDP4", 1.5f, "mom range 4 for kaon PID."}; + + Configurable confKaonTPCNsigma1{"confKaonTPCNsigma1", 3.0f, "TPC Kaon NSigma for mom range 1."}; + Configurable confKaonTPCNsigma2{"confKaonTPCNsigma2", 2.0f, "TPC Kaon NSigma for mom range 2."}; + Configurable confKaonTPCNsigma3{"confKaonTPCNsigma3", 1.0f, "TPC Kaon NSigma for mom range 3."}; + Configurable confKaonTPCNsigma4{"confKaonTPCNsigma4", 3.0f, "TPC Kaon NSigma for mom range 4."}; + Configurable confKaonTPCNsigma5{"confKaonTPCNsigma5", 2.0f, "TPC Kaon NSigma for mom range 5."}; + Configurable confKaonTOFNsigma4{"confKaonTOFNsigma4", 3.0f, "TOF Kaon NSigma for mom range 4."}; + Configurable confKaonTOFNsigma5{"confKaonTOFNsigma5", 3.0f, "TOF Kaon NSigma for mom range 5."}; + + Configurable> confCutTable{"confCutTable", {cutsTable[0], NPart, NCuts, partNames, cutNames}, "Particle selections"}; Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This Configurable needs to be the same as the one used in the producer task"}; @@ -135,6 +152,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable confIsWeight{"confIsWeight", true, "Fill quantum weight"}; Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; Configurable confIsfilldEtadPhiTPCcls{"confIsfilldEtadPhiTPCcls", false, "Filling of 3D histogram PairFracSharedTPCcls vs. dEta vs. dPhiStar"}; + Configurable confRandValue{"confRandValue", 0.5, "Value of random-number generator to shuffle pair"}; Configurable> confCPRdeltaEtaCutMaxVec{"confCPRdeltaEtaCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR"}; Configurable> confCPRdeltaEtaCutMinVec{"confCPRdeltaEtaCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR"}; @@ -150,7 +168,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { ConfigurableAxis confDeltaPhiStarAxis{"confDeltaPhiStarAxis", {100, -0.15, 0.15}, "DeltaPhiStar"}; } twotracksconfigs; - using FemtoFullParticles = soa::Join; + using FemtoFullParticles = soa::Join; // Filters for selecting particles (both p1 and p2) Filter trackAdditionalfilter = ((nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax) && (aod::track::dcaXY <= twotracksconfigs.confTrkDCAxyMax) && @@ -161,14 +179,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { (aod::track::tpcNClsShared <= static_cast(twotracksconfigs.confTrkTPCsClsMax))); using FilteredFemtoFullParticles = soa::Filtered; - // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this optionconfIsCPRkT - using FemtoRecoParticles = soa::Join; + using FemtoRecoParticles = soa::Join; using FilteredFemtoRecoParticles = soa::Filtered; SliceCache cache; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; - using FemtoTruthParticles = soa::Join; + using FemtoTruthParticles = soa::Join; Preslice perColMCTruth = aod::femtouniverseparticle::fdCollisionId; /// Particle 1 @@ -182,7 +199,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// Partition for particle 1 Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; - Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; Partition partsOneMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); // @@ -233,7 +250,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { // Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on Configurable /// Particle part - ConfigurableAxis confTempFitVarBins{"confDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarBins{"confTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; /// Correlation part @@ -275,10 +292,10 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { FemtoUniverseSHContainer sameEventContMM; FemtoUniverseSHContainer mixedEventContMM; - FemtoUniverseContainer sameEventCont1D_PP; - FemtoUniverseContainer mixedEventCont1D_PP; - FemtoUniverseContainer sameEventCont1D_MM; - FemtoUniverseContainer mixedEventCont1D_MM; + FemtoUniverseContainer sameEventCont1dpp; + FemtoUniverseContainer mixedEventCont1dpp; + FemtoUniverseContainer sameEventCont1dmm; + FemtoUniverseContainer mixedEventCont1dmm; FemtoUniversePairCleaner pairCleaner; FemtoUniverseDetaDphiStar pairCloseRejection; @@ -303,21 +320,21 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { HistogramRegistry resultRegistryPM{"CorrelationsPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry resultRegistryPP{"CorrelationsPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry resultRegistryMM{"CorrelationsMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry SameMultRegistryPM{"SameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry MixedMultRegistryPM{"MixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry sameMultRegistryPM{"sameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPM{"mixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry SameMultRegistryPP{"SameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry MixedMultRegistryPP{"MixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry sameMultRegistryPP{"sameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPP{"mixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry SameMultRegistryMM{"SameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry MixedMultRegistryMM{"MixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry sameMultRegistryMM{"sameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryMM{"mixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; TRandom2* randgen; // PID for protons - bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { //|nsigma_TPC| < 3 for p < 0.5 GeV/c //|nsigma_combined| < 3 for p > 0.5 @@ -343,36 +360,36 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { return false; } - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) { - if (mom < 0.3) { // 0.0-0.3 - if (std::abs(nsigmaTPCK) < 3.0) { + if (mom < twotracksconfigs.confKaonPIDP1) { // 0.0-0.3 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma1) { return true; } else { return false; } - } else if (mom < 0.45) { // 0.30 - 0.45 - if (std::abs(nsigmaTPCK) < 2.0) { + } else if (mom < twotracksconfigs.confKaonPIDP2) { // 0.30 - 0.45 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma2) { return true; } else { return false; } - } else if (mom < 0.55) { // 0.45-0.55 - if (std::abs(nsigmaTPCK) < 1.0) { + } else if (mom < twotracksconfigs.confKaonPIDP3) { // 0.45-0.55 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma3) { return true; } else { return false; } - } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) - if ((std::abs(nsigmaTOFK) < 3.0) && (std::abs(nsigmaTPCK) < 3.0)) { + } else if (mom < twotracksconfigs.confKaonPIDP4) { // 0.55-1.5 (now we use TPC and TOF) + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma4) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma4)) { { return true; } } else { return false; } - } else if (mom > 1.5) { // 1.5 - - if ((std::abs(nsigmaTOFK) < 2.0) && (std::abs(nsigmaTPCK) < 3.0)) { + } else if (mom > twotracksconfigs.confKaonPIDP4) { // 1.5 - + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma5) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma5)) { return true; } else { return false; @@ -382,7 +399,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } - bool IsPionNSigma(float mom, float nsigmaITSPi, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCElReject) + bool isPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCElReject) { //|nsigma_TPC| < 3 for p < 0.5 GeV/c //|nsigma_combined| < 3 for p > 0.5 @@ -399,12 +416,6 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } else { return false; } - } else if (twotracksconfigs.confIsAddITSNsigma) { - if (std::hypot(nsigmaITSPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaITSTPCCombined) { - return true; - } else { - return false; - } } else { if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC)) { return true; @@ -423,46 +434,46 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { return false; } - bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaITSPi, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCElReject) + bool isParticleNSigma(ParticleNumber particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCElReject) { - if (particle_number == 1) { + if (particle_number == ParticleNumber::First) { switch (trackonefilter.confPDGCodePartOne) { case 2212: // Proton case -2212: // Antiproton - return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); break; case 211: // Pion+ case -211: // Pion- - return IsPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + return isPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); break; case 321: // Kaon+ case -321: // Kaon- - return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); break; default: return false; } return false; - } else if (particle_number == 2) { + } else if (particle_number == ParticleNumber::Second) { switch (tracktwofilter.confPDGCodePartTwo) { case 2212: // Proton case -2212: // Antiproton - return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); break; case 211: // Pion+ case -211: // Pion- - return IsPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + return isPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); break; case 321: // Kaon+ case -321: // Kaon- - return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); break; default: return false; } return false; } else { - LOGF(fatal, "Wrong number of particle chosen! It should be 1 or 2. It is -> %d", particle_number); + LOGF(fatal, "Wrong number of particle chosen! It should be 1 or 2."); } return false; } @@ -474,12 +485,12 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { colBinningNtr = ColumnBinningPolicy{{confVtxBins, confMultBinsMult}, true}; eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true); - trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true); - MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); @@ -491,8 +502,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultCont.init(&SameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultCont.init(&MixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + sameEventMultCont.init(&sameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultCont.init(&mixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } } @@ -503,13 +514,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultContPP.init(&SameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultContPP.init(&MixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + sameEventMultContPP.init(&sameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContPP.init(&mixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } - sameEventCont1D_PP.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - sameEventCont1D_PP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventCont1D_PP.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - mixedEventCont1D_PP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + sameEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } if (cfgProcessMM) { @@ -519,13 +530,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultContMM.init(&SameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultContMM.init(&MixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + sameEventMultContMM.init(&sameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContMM.init(&mixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } - sameEventCont1D_MM.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - sameEventCont1D_MM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventCont1D_MM.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - mixedEventCont1D_MM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + sameEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } pairCleaner.init(&qaRegistry); @@ -543,9 +554,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { void fillCollision(CollisionType col, bool IsCent) { if (IsCent) { - MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningCent.getBin({col.posZ(), col.multV0M()})); + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningCent.getBin({col.posZ(), col.multV0M()})); } else { - MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningNtr.getBin({col.posZ(), col.multNtr()})); + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningNtr.getBin({col.posZ(), col.multNtr()})); } eventHisto.fillQA(col); } @@ -566,26 +577,20 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// Histogramming same event if ((contType == PairType::PlusMinus || contType == PairType::PlusPlus) && fillQA) { for (const auto& part : groupPartsOne) { - if (!IsParticleNSigma((int8_t)1, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::First, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { continue; } trackHistoPartOne.fillQA(part); - if (twotracksconfigs.confIsAddITSNsigma) { - trackHistoPartOne.fillQAITSPID<>(part); - } trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); } } if ((contType == PairType::PlusMinus || contType == PairType::MinusMinus) && fillQA) { for (const auto& part : groupPartsTwo) { - if (!IsParticleNSigma((int8_t)2, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { continue; } trackHistoPartTwo.fillQA(part); - if (twotracksconfigs.confIsAddITSNsigma) { - trackHistoPartTwo.fillQAITSPID<>(part); - } } } @@ -594,11 +599,11 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// Now build the combinations for non-identical particle pairs for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (!IsParticleNSigma((int8_t)1, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::First, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { continue; } @@ -645,11 +650,11 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } else { for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { - if (!IsParticleNSigma((int8_t)2, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { continue; } @@ -671,7 +676,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { auto part1 = p1; auto part2 = p2; - if (rand > 0.5) { + if (rand > twotracksconfigs.confRandValue) { part1 = p2; part2 = p1; } @@ -725,7 +730,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -751,7 +756,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -765,7 +770,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } } - + /// process function for to call doSameEvent with Data /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoUniverseParticleTable @@ -803,7 +808,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEvent, "Enable processing same event", true); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEvent, "Enable processing same event", true); /// process function for to call doSameEvent with Monte Carlo /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) @@ -843,7 +848,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEventMC, "Enable processing same event for Monte Carlo", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEventMC, "Enable processing same event for Monte Carlo", false); /// This function processes the same event and takes care of all the histogramming /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... @@ -916,7 +921,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { auto part1 = p1; auto part2 = p2; - if (rand > 0.5) { + if (rand > twotracksconfigs.confRandValue) { part1 = p2; part2 = p1; } @@ -926,7 +931,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (twotracksconfigs.confIs1D) { f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); float weight = f3d[5]; - sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } @@ -937,7 +942,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (twotracksconfigs.confIs1D) { f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); float weight = f3d[5]; - sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } @@ -996,7 +1001,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEventMCTruth, "Enable processing same event for MC truth", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processSameEventMCTruth, "Enable processing same event for MC truth", false); /// This function processes the mixed event /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... @@ -1014,11 +1019,11 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (!IsParticleNSigma((int8_t)2, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { continue; } - if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { continue; } @@ -1043,7 +1048,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { auto part1 = p1; auto part2 = p2; - if (rand > 0.5) { + if (rand > twotracksconfigs.confRandValue) { part1 = p2; part2 = p1; } @@ -1098,7 +1103,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { @@ -1125,7 +1130,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -1159,7 +1164,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -1186,7 +1191,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventCent, "Enable processing mixed events for centrality", true); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventCent, "Enable processing mixed events for centrality", true); /// process function for to call doMixedEvent with Data /// @param cols subscribe to the collisions table (Data) @@ -1207,7 +1212,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -1234,7 +1239,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventNtr, "Enable processing mixed events for centrality", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventNtr, "Enable processing mixed events for centrality", false); /// brief process function for to call doMixedEvent with Monte Carlo /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) @@ -1257,7 +1262,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -1286,7 +1291,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventMCCent, "Enable processing mixed events MC", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventMCCent, "Enable processing mixed events MC", false); /// brief process function for to call doMixedEvent with Monte Carlo /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) @@ -1309,7 +1314,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -1338,7 +1343,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } delete randgen; } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventMCNtr, "Enable processing mixed events MC", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventMCNtr, "Enable processing mixed events MC", false); /// This function processes the mixed event /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... @@ -1371,7 +1376,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { auto part1 = p1; auto part2 = p2; - if (rand > 0.5) { + if (rand > twotracksconfigs.confRandValue) { part1 = p2; part2 = p1; } @@ -1384,7 +1389,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case PairType::PlusPlus: { if (twotracksconfigs.confIs1D) { float weight = 1.0; - mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } @@ -1394,7 +1399,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case PairType::MinusMinus: { if (twotracksconfigs.confIs1D) { float weight = 1.0; - mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } @@ -1426,7 +1431,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); if (cfgProcessPM) { auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); @@ -1445,7 +1450,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventNtrMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventNtrMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); /// process function for to call doMixedEvent with Data /// @param cols subscribe to the collisions table (Data) @@ -1465,7 +1470,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); if (cfgProcessPM) { auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); @@ -1484,13 +1489,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventCentMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventCentMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; return workflow; } From 34bf0aeea924a4f0a5dda33f08ac3d768307d39b Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty Date: Sat, 25 Apr 2026 16:16:55 +0200 Subject: [PATCH 3/4] Fix O2-linter error, clang-format error, add new task with fixed name --- PWGCF/FemtoUniverse/Tasks/CMakeLists.txt | 8 +- ...irTaskTrackTrackSpherHarMultKtExtended.cxx | 4 +- ...TrackTrackSpherHarMultKtExtendedItsPid.cxx | 1060 +++++++++++++++++ 3 files changed, 1066 insertions(+), 6 deletions(-) create mode 100644 PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index 16c82dbaf26..607386c1d4b 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -44,13 +44,13 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-track-threedrelmom-mult-kt-e PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(femtouniverse-pair-track-track-spherhar-mult-kt-extended +o2physics_add_dpl_workflow(femto-universe-pair-task-track-track-spher-har-mult-kt-extended SOURCES femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(femtouniverse-pair-track-track-spherhar-mult-kt-extended-itspid - SOURCES femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx +o2physics_add_dpl_workflow(femto-universe-pair-task-track-track-spher-har-mult-kt-extended-its-pid + SOURCES femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -112,4 +112,4 @@ o2physics_add_dpl_workflow(femtouniverse-efficiency-base o2physics_add_executable(femtouniverse-cutculator SOURCES femtoUniverseCutCulator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 7d81dafaa05..694a1406ddd 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -199,7 +199,7 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// Partition for particle 1 Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; - Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; Partition partsOneMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); // @@ -770,7 +770,7 @@ struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } } - + /// process function for to call doSameEvent with Data /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoUniverseParticleTable diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx new file mode 100644 index 00000000000..be4cd60e788 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx @@ -0,0 +1,1060 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks and compute relative pair-momentum in three dimesnions +/// \remark This file is inherited from ~/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx on 17/06/2024 +/// \author Pritam Chakraborty, WUT Warsaw, pritam.chakraborty@pw.edu.pl + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis::femto_universe; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int NPart = 2; +static constexpr int NCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[NPart][NCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +enum ParticleNumber { + First, + Second +}; + +enum PairType { + PlusMinus, + PlusPlus, + MinusMinus +}; + +struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid { + + Service pdg; + + /// Particle selection part + + /// Table for both particles + struct : o2::framework::ConfigurableGroup { + Configurable confNsigmaCombined{"confNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > confTOFPtMin"}; + Configurable confNsigmaTPC{"confNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < confTOFPtMin"}; + Configurable confNsigmaITSTPCCombined{"confNsigmaITSTPCCombined", 3.0f, "ITS and TPC Pion Sigma (combined) for momentum < confTOFPtMin"}; + Configurable confIsElReject{"confIsElReject", false, "Is electron rejection activated"}; + Configurable confIsAddITSNsigma{"confIsAddITSNsigma", false, "Is ITS Pions nsigma added"}; + Configurable confNsigmaTPCElRejectMin{"confNsigmaTPCElRejectMin", 2.0f, "TPC Electron SigmaMin for momentum < confTOFPtMin"}; + Configurable confNsigmaTPCElRejectMax{"confNsigmaTPCElRejectMax", 2.0f, "TPC Electron SigmaMax for momentum < confTOFPtMin"}; + Configurable confTOFPtMin{"confTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; + Configurable confEtaMax{"confEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + Configurable confKaonPIDP1{"confKaonPIDP1", 0.3f, "mom range 1 for kaon PID."}; + Configurable confKaonPIDP2{"confKaonPIDP2", 0.45f, "mom range 2 for kaon PID."}; + Configurable confKaonPIDP3{"confKaonPIDP3", 0.55f, "mom range 3 for kaon PID."}; + Configurable confKaonPIDP4{"confKaonPIDP4", 1.5f, "mom range 4 for kaon PID."}; + + Configurable confKaonTPCNsigma1{"confKaonTPCNsigma1", 3.0f, "TPC Kaon NSigma for mom range 1."}; + Configurable confKaonTPCNsigma2{"confKaonTPCNsigma2", 2.0f, "TPC Kaon NSigma for mom range 2."}; + Configurable confKaonTPCNsigma3{"confKaonTPCNsigma3", 1.0f, "TPC Kaon NSigma for mom range 3."}; + Configurable confKaonTPCNsigma4{"confKaonTPCNsigma4", 3.0f, "TPC Kaon NSigma for mom range 4."}; + Configurable confKaonTPCNsigma5{"confKaonTPCNsigma5", 2.0f, "TPC Kaon NSigma for mom range 5."}; + Configurable confKaonTOFNsigma4{"confKaonTOFNsigma4", 3.0f, "TOF Kaon NSigma for mom range 4."}; + Configurable confKaonTOFNsigma5{"confKaonTOFNsigma5", 3.0f, "TOF Kaon NSigma for mom range 5."}; + + Configurable> confCutTable{"confCutTable", {cutsTable[0], NPart, NCuts, partNames, cutNames}, "Particle selections"}; + Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; + Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This Configurable needs to be the same as the one used in the producer task"}; + Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; + Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; + Configurable confIsCPRatITS{"confIsCPRatITS", false, "Close Pair check at ITS"}; + Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; + Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; + Configurable confIsCPRkT{"confIsCPRkT", true, "kT dependent deltaEta-deltaPhi cut for Close Pair Rejection"}; + Configurable confIsCPRFraction{"confIsCPRFraction", true, "Close Pair Rejection with fraction of merged points"}; + Configurable confTrkDCAxyMax{"confTrkDCAxyMax", 0.2, "Max DCA in xy "}; + Configurable confTrkDCAzMax{"confTrkDCAzMax", 0.2, "Max DCA in z "}; + Configurable confTrkTPCcRowsMin{"confTrkTPCcRowsMin", 80, "Min of TPC crossed rows"}; + Configurable confTrkTPCfClsMin{"confTrkTPCfClsMin", 0.83, "Min. fraction of crossed rows/findable TPC clusters"}; + Configurable confTrkTPCfracsClsMax{"confTrkTPCfracsClsMax", 1.0, "Max of fraction of TPC shared cluster "}; + Configurable confTrkTPCnClsMin{"confTrkTPCnClsMin", 80, "Min number of TPC clusters"}; + Configurable confTrkTPCsClsMax{"confTrkTPCsClsMax", 160, "Max number of TPC shared clusters"}; + Configurable confPairFracSharedTPCclsMin{"confPairFracSharedTPCclsMin", 0.0, "Min. fraction of TPC shared clusters between two closed tracks"}; + Configurable confPairFracSharedTPCclsMax{"confPairFracSharedTPCclsMax", 1.0, "Miax. fraction of TPC shared clusters between two closed tracks"}; + Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; + Configurable confUseCCImCut{"confUseCCImCut", false, "Fill SH within specific quadrants of qout-qside"}; + Configurable confMinqTcut{"confMinqTcut", 0.005, "Min. qT cut on filling SH"}; + Configurable confUse1stand3rd{"confUse1stand3rd", false, "Use first and third quadrants of qout-qside"}; + Configurable confUse2ndand4th{"confUse2ndand4th", false, "Use second and fourth quadrants of qout-qside"}; + Configurable confIsFillAngqLCMS{"confIsFillAngqLCMS", true, "Fill qLCMS vs dEta vs dPhi"}; + Configurable confCPRDistMax{"confCPRDistMax", 0.0, "Max. radial seperation between two closed-pairs"}; + Configurable confCPRFracMax{"confCPRFracMax", 0.0, "Max. allowed fraction bad to all TPC points of radial seperation between two closed-pairs"}; + Configurable confCPRDphiAvgOrDist{"confCPRDphiAvgOrDist", true, "Close Pair Rejection by radial or angular seperation"}; + Configurable confIsCircularCut{"confIsCircularCut", true, "Close Pair Rejection within circular area"}; + Configurable confIs1D{"confIs1D", true, "Filling 1D 2k* dist. in MC truth"}; + Configurable confisIdenLCMS{"confisIdenLCMS", true, "Choosing identical or non-identical pairs in LCMS"}; + Configurable confIsWeight{"confIsWeight", true, "Fill quantum weight"}; + Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; + Configurable confIsfilldEtadPhiTPCcls{"confIsfilldEtadPhiTPCcls", false, "Filling of 3D histogram PairFracSharedTPCcls vs. dEta vs. dPhiStar"}; + Configurable confRandValue{"confRandValue", 0.5, "Value of random-number generator to shuffle pair"}; + + Configurable> confCPRdeltaEtaCutMaxVec{"confCPRdeltaEtaCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR"}; + Configurable> confCPRdeltaEtaCutMinVec{"confCPRdeltaEtaCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR"}; + Configurable> confCPRdeltaPhiCutMaxVec{"confCPRdeltaPhiCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR"}; + Configurable> confCPRdeltaPhiCutMinVec{"confCPRdeltaPhiCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR"}; + + Configurable> confCPRdeltaEtaCutFractionMaxVec{"confCPRdeltaEtaCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR Fraction"}; + Configurable> confCPRdeltaEtaCutFractionMinVec{"confCPRdeltaEtaCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR Fraction"}; + Configurable> confCPRdeltaPhiCutFractionMaxVec{"confCPRdeltaPhiCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR Fraction"}; + Configurable> confCPRdeltaPhiCutFractionMinVec{"confCPRdeltaPhiCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR Fraction"}; + + ConfigurableAxis confDeltaEtaAxis{"confDeltaEtaAxis", {100, -0.15, 0.15}, "DeltaEta"}; + ConfigurableAxis confDeltaPhiStarAxis{"confDeltaPhiStarAxis", {100, -0.15, 0.15}, "DeltaPhiStar"}; + } twotracksconfigs; + + using FemtoFullParticles = soa::Join; + // Filters for selecting particles (both p1 and p2) + Filter trackAdditionalfilter = ((nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax) && + (aod::track::dcaXY <= twotracksconfigs.confTrkDCAxyMax) && + (aod::track::dcaZ <= twotracksconfigs.confTrkDCAzMax) && + (aod::femtouniverseparticle::tpcNClsCrossedRows >= static_cast(twotracksconfigs.confTrkTPCcRowsMin)) && + (aod::femtouniverseparticle::tpcFractionSharedCls <= twotracksconfigs.confTrkTPCfracsClsMax) && + (aod::femtouniverseparticle::tpcNClsFound >= static_cast(twotracksconfigs.confTrkTPCnClsMin)) && + (aod::track::tpcNClsShared <= static_cast(twotracksconfigs.confTrkTPCsClsMax))); + + using FilteredFemtoFullParticles = soa::Filtered; + + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle 1 + struct : o2::framework::ConfigurableGroup { + Configurable confPDGCodePartOne{"confPDGCodePartOne", 211, "Particle 1 - PDG code"}; + Configurable confPIDPartOne{"confPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable confPtLowPart1{"confPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable confPtHighPart1{"confPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable confChargePart1{"confChargePart1", 1, "Particle 1 sign"}; + } trackonefilter; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + struct : o2::framework::ConfigurableGroup { + Configurable confPDGCodePartTwo{"confPDGCodePartTwo", 211, "Particle 2 - PDG code"}; + // Configurable confCutPartTwo{"confCutPartTwo", 5542474, "Particle 2 - Selection bit"}; + Configurable confPIDPartTwo{"confPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + Configurable confPtLowPart2{"confPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable confPtHighPart2{"confPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable confChargePart2{"confChargePart2", -1, "Particle 2 sign"}; + } tracktwofilter; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The Configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// Event part + Configurable confV0MLow{"confV0MLow", 0.0, "Lower limit for V0M multiplicity"}; + Configurable confV0MHigh{"confV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; + Configurable confTPCOccupancyLow{"confTPCOccupancyLow", 0, "Lower limit for TPC occupancy"}; + Configurable confTPCOccupancyHigh{"confTPCOccupancyHigh", 500, "Higher limit for TPC occupancy"}; + Configurable confIntRateLow{"confIntRateLow", 0.0, "Lower limit for interaction rate"}; + Configurable confIntRateHigh{"confIntRateHigh", 10000.0, "Higher limit for interaction rate"}; + Configurable confIsCent{"confIsCent", true, "Condition to choose centrality of multiplicity for mixing"}; + + Filter collfilterFDtable = (o2::aod::femtouniversecollision::multV0M > confV0MLow) && (o2::aod::femtouniversecollision::multV0M < confV0MHigh); + Filter collfilterFDExttable = (o2::aod::femtouniversecollision::interactionRate > confIntRateLow) && (o2::aod::femtouniversecollision::interactionRate < confIntRateHigh) && + (o2::aod::femtouniversecollision::occupancy >= confTPCOccupancyLow) && (o2::aod::femtouniversecollision::occupancy < confTPCOccupancyHigh); + using FilteredFDCollisions = soa::Filtered>; + using FilteredFDCollision = FilteredFDCollisions::iterator; + // Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on Configurable + + /// Particle part + ConfigurableAxis confTempFitVarBins{"confTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 12.5f, 15.0f, 17.5f, 20.0f, 22.5f, 25.0f, 27.5f, 30.0f, 32.5f, 35.0f, 37.5f, 40.0f, 42.5f, 45.0f, 47.5f, 50.0f, 52.5f, 55.0f, 57.5f, 60.0f, 62.5f, 65.0f, 67.5f, 70.5f, 75.0f, 80.0f, 90.0f, 100.0f, 99999.f}, "Mixing bins - centrality"}; + ConfigurableAxis confMultBinsMult{"confMultBinsMult", {VARIABLE_WIDTH, 0.0f, 400.0f, 800.0f, 1200.0f, 1600.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f, 10000.0f, 11000.0f, 12000.0f, 13000.0f, 14000.0f, 15000.0f, 16000.0f, 17000.0f, 18000.0f, 99999.f}, "Mixing bins - centrality"}; + ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; + ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; + ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis confmultBins3D{"confmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBinsCent}, true}; + ColumnBinningPolicy colBinningNtr{{confVtxBins, confMultBinsMult}, true}; + + ConfigurableAxis confkstarBins{"confkstarBins", {60, 0.0, 0.3}, "binning kstar"}; + ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable confIsLCMS{"confIsLCMS", true, "Choosing LCMS or PRF"}; + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; + Configurable confLMax{"confLMax", 2, "Maximum value of l"}; + Configurable cfgProcessPM{"cfgProcessPM", false, "Process particles of the opposite charge"}; + Configurable cfgProcessPP{"cfgProcessPP", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMM{"cfgProcessMM", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; + Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; + Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; + + Configurable confRejectGammaPair{"confRejectGammaPair", false, "Additional check to reject e+e- pairs base on theta and minv"}; + Configurable confMaxEEMinv{"confMaxEEMinv", 0.002, "Max. minv of e-e+ pair for gamma pair rejection"}; + Configurable confMaxDTheta{"confMaxDTheta", 0.008, "Max. DeltaTheta of pair for gamma pair rejection"}; + + FemtoUniverseSHContainer sameEventCont; + FemtoUniverseSHContainer mixedEventCont; + + FemtoUniverseSHContainer sameEventContPP; + FemtoUniverseSHContainer mixedEventContPP; + + FemtoUniverseSHContainer sameEventContMM; + FemtoUniverseSHContainer mixedEventContMM; + + FemtoUniverseContainer sameEventCont1dpp; + FemtoUniverseContainer mixedEventCont1dpp; + FemtoUniverseContainer sameEventCont1dmm; + FemtoUniverseContainer mixedEventCont1dmm; + + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseTrackSelection trackCuts; + + PairSHCentMultKt sameEventMultCont; + PairSHCentMultKt mixedEventMultCont; + + PairSHCentMultKt sameEventMultContPP; + PairSHCentMultKt mixedEventMultContPP; + + PairSHCentMultKt sameEventMultContMM; + PairSHCentMultKt mixedEventMultContMM; + + float mass1 = -1; + float mass2 = -1; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistry1D{"Correlations1D", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPM{"CorrelationsPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPP{"CorrelationsPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryMM{"CorrelationsMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + HistogramRegistry sameMultRegistryPM{"sameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPM{"mixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry sameMultRegistryPP{"sameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryPP{"mixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry sameMultRegistryMM{"sameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mixedMultRegistryMM{"mixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + TRandom2* randgen; + + // PID for protons + bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using Configurables: + // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // confNsigmaTPC -> TPC Sigma for momentum < 0.5 + // confNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 + + if (mom < twotracksconfigs.confTOFPtMin) { + if (std::abs(nsigmaTPCPr) < twotracksconfigs.confNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.confNsigmaCombined) { + return true; + } else { + return false; + } + } + return false; + } + + bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < twotracksconfigs.confKaonPIDP1) { // 0.0-0.3 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma1) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP2) { // 0.30 - 0.45 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma2) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP3) { // 0.45-0.55 + if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma3) { + return true; + } else { + return false; + } + } else if (mom < twotracksconfigs.confKaonPIDP4) { // 0.55-1.5 (now we use TPC and TOF) + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma4) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma4)) { + { + return true; + } + } else { + return false; + } + } else if (mom > twotracksconfigs.confKaonPIDP4) { // 1.5 - + if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma5) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma5)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool isPionNSigma(float mom, float nsigmaITSPi, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCElReject) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using Configurables: + // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // confNsigmaTPC -> TPC Sigma for momentum < 0.5 + // confNsigmaCombined -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < twotracksconfigs.confTOFPtMin) { + if (twotracksconfigs.confIsElReject) { + if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC) && (nsigmaTPCElReject < twotracksconfigs.confNsigmaTPCElRejectMin || nsigmaTPCElReject > twotracksconfigs.confNsigmaTPCElRejectMax)) { + return true; + } else { + return false; + } + } else if (twotracksconfigs.confIsAddITSNsigma) { + if (std::hypot(nsigmaITSPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaITSTPCCombined) { + return true; + } else { + return false; + } + } else { + if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC)) { + return true; + } else { + return false; + } + } + } else { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool isParticleNSigma(ParticleNumber particle_number, float mom, float nsigmaITSPi, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCElReject) + { + if (particle_number == ParticleNumber::First) { + switch (trackonefilter.confPDGCodePartOne) { + case 2212: // Proton + case -2212: // Antiproton + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + break; + case 321: // Kaon+ + case -321: // Kaon- + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else if (particle_number == ParticleNumber::Second) { + switch (tracktwofilter.confPDGCodePartTwo) { + case 2212: // Proton + case -2212: // Antiproton + return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); + break; + case 321: // Kaon+ + case -321: // Kaon- + return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else { + LOGF(fatal, "Wrong number of particle chosen! It should be First or Second."); + } + return false; + } + + void init(InitContext&) + { + + colBinningCent = ColumnBinningPolicy{{confVtxBins, confMultBinsCent}, true}; + colBinningNtr = ColumnBinningPolicy{{confVtxBins, confMultBinsMult}, true}; + + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + + trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); + + mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); + mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); + + if (cfgProcessPM) { + if (!cfgProcessKtMt3DCF) { + sameEventCont.init(&resultRegistryPM, confkstarBins, confLMax); + mixedEventCont.init(&resultRegistryPM, confkstarBins, confLMax); + sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultCont.init(&sameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultCont.init(&mixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + } + + if (cfgProcessPP) { + if (!cfgProcessKtMt3DCF) { + sameEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); + mixedEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); + sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultContPP.init(&sameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContPP.init(&mixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + sameEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } + + if (cfgProcessMM) { + if (!cfgProcessKtMt3DCF) { + sameEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); + mixedEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); + sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } else { + sameEventMultContMM.init(&sameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContMM.init(&mixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + } + sameEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + } + + pairCleaner.init(&qaRegistry); + if (twotracksconfigs.confIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMin.value, twotracksconfigs.confCPRdeltaPhiCutMax.value, twotracksconfigs.confCPRdeltaEtaCutMin.value, twotracksconfigs.confCPRdeltaEtaCutMax.value, twotracksconfigs.confCPRChosenRadii.value, twotracksconfigs.confCPRPlotPerRadii.value); + pairCloseRejection.init_kT(&resultRegistry, confKtKstarBins, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMinVec.value, twotracksconfigs.confCPRdeltaPhiCutMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutMinVec.value, twotracksconfigs.confCPRdeltaEtaCutMaxVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMinVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMinVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMaxVec.value, twotracksconfigs.confIsfilldEtadPhiTPCcls); + } + + vPIDPartOne = trackonefilter.confPIDPartOne.value; + vPIDPartTwo = tracktwofilter.confPIDPartTwo.value; + kNsigma = twotracksconfigs.confTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col, bool IsCent) + { + if (IsCent) { + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningCent.getBin({col.posZ(), col.multV0M()})); + } else { + mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningNtr.getBin({col.posZ(), col.multNtr()})); + } + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, PairType contType, bool fillQA) + { + /// Histogramming same event + if ((contType == PairType::PlusMinus || contType == PairType::PlusPlus) && fillQA) { + for (const auto& part : groupPartsOne) { + if (!isParticleNSigma(ParticleNumber::First, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + continue; + } + trackHistoPartOne.fillQA(part); + if (twotracksconfigs.confIsAddITSNsigma) { + trackHistoPartOne.fillQAITSPID<>(part); + } + trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); + } + } + + if ((contType == PairType::PlusMinus || contType == PairType::MinusMinus) && fillQA) { + for (const auto& part : groupPartsTwo) { + if (!isParticleNSigma(ParticleNumber::Second, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { + continue; + } + trackHistoPartTwo.fillQA(part); + if (twotracksconfigs.confIsAddITSNsigma) { + trackHistoPartTwo.fillQAITSPID<>(part); + } + } + } + + if (contType == PairType::PlusMinus) { + + /// Now build the combinations for non-identical particle pairs + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!isParticleNSigma(ParticleNumber::First, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + } else { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { + + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + if (twotracksconfigs.confIsCPRFraction) { + if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::same, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { + continue; + } + } + } else { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(part1, part2, parts)) { + continue; + } + + std::vector f3d; + double kv; + float outsideref = 0.0; + switch (contType) { + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); + } + break; + } + + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); + } + break; + } + default: + break; + } + } + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(FilteredFDCollision const& col, + FilteredFemtoFullParticles const& parts) + { + fillCollision(col, confIsCent); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + bool fillQA = true; + randgen = new TRandom2(0); + + if (confIsCent) { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); + } + } else { + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); + } + if (cfgProcessPP) { + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); + } + if (cfgProcessMM) { + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid, processSameEvent, "Enable processing same event", true); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, PairType contType) + { + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { + continue; + } + + if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { + continue; + } + + if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { + continue; + } + + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + float lastElement = confKtKstarBins.value.back(); + float firstRealElement = confKtKstarBins.value[1]; + + if (kT < firstRealElement || kT > lastElement) + continue; + + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + auto part1 = p1; + auto part2 = p2; + + if (rand > twotracksconfigs.confRandValue) { + part1 = p2; + part2 = p1; + } + + if (twotracksconfigs.confIsCPR.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed)) { + continue; + } + } else { + if (twotracksconfigs.confIsCPRkT) { + if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::mixed, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { + continue; + } + if (twotracksconfigs.confIsCPRFraction) { + if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::mixed, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { + continue; + } + } + } else { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { + continue; + } + } + } + } + + std::vector f3d; + double kv; + float outsideref = 0.0; + + switch (contType) { + case PairType::PlusMinus: { + mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + break; + } + + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); + } + break; + } + + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + if (!twotracksconfigs.confUseCCImCut) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } else { + if (twotracksconfigs.confUse1stand3rd) { + if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } else if (twotracksconfigs.confUse2ndand4th) { + if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); + } + } + } + if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { + float weight = 1.0f; + mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); + } + if (twotracksconfigs.confIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); + } + break; + } + + default: + break; + } + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param subscribe to the femtoUniverseParticleTable + void processMixedEventCent(FilteredFDCollisions const& cols, + FilteredFemtoFullParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + if (cfgProcessPM) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid, processMixedEventCent, "Enable processing mixed events for centrality", true); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventNtr(FilteredFDCollisions const& cols, + FilteredFemtoFullParticles const&) + { + randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + if (cfgProcessPM) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); + } + } + delete randgen; + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedItsPid, processMixedEventNtr, "Enable processing mixed events for centrality", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From a97c597780a4ecdcc2dec59c6f2bd29f07f8afb0 Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty Date: Sat, 25 Apr 2026 16:21:53 +0200 Subject: [PATCH 4/4] Remove file with bad name --- ...TrackTrackSpherHarMultKtExtendedITSPID.cxx | 1511 ----------------- 1 file changed, 1511 deletions(-) delete mode 100644 PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx deleted file mode 100644 index bb155febb7e..00000000000 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx +++ /dev/null @@ -1,1511 +0,0 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file femtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID.cxx -/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks and compute relative pair-momentum in three dimesnions -/// \remark This file is inherited from ~/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx on 17/06/2024 -/// \author Pritam Chakraborty, WUT Warsaw, pritam.chakraborty@pw.edu.pl - -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSHContainer.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" - -#include "Common/DataModel/TrackSelectionTables.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::analysis::femto_universe; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; - -namespace -{ -static constexpr int NPart = 2; -static constexpr int NCuts = 5; -static const std::vector partNames{"PartOne", "PartTwo"}; -static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; -static const float cutsTable[NPart][NCuts]{ - {4.05f, 1.f, 3.f, 3.f, 100.f}, - {4.05f, 1.f, 3.f, 3.f, 100.f}}; -} // namespace - -enum ParticleNumber { - First, - Second -}; - -enum PairType { - PlusMinus, - PlusPlus, - MinusMinus -}; - -struct FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID { - - Service pdg; - - /// Particle selection part - - /// Table for both particles - struct : o2::framework::ConfigurableGroup { - Configurable confNsigmaCombined{"confNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > confTOFPtMin"}; - Configurable confNsigmaTPC{"confNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < confTOFPtMin"}; - Configurable confNsigmaITSTPCCombined{"confNsigmaITSTPCCombined", 3.0f, "ITS and TPC Pion Sigma (combined) for momentum < confTOFPtMin"}; - Configurable confIsElReject{"confIsElReject", false, "Is electron rejection activated"}; - Configurable confIsAddITSNsigma{"confIsAddITSNsigma", false, "Is ITS Pions nsigma added"}; - Configurable confNsigmaTPCElRejectMin{"confNsigmaTPCElRejectMin", 2.0f, "TPC Electron SigmaMin for momentum < confTOFPtMin"}; - Configurable confNsigmaTPCElRejectMax{"confNsigmaTPCElRejectMax", 2.0f, "TPC Electron SigmaMax for momentum < confTOFPtMin"}; - Configurable confTOFPtMin{"confTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; - Configurable confEtaMax{"confEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; - - Configurable confKaonPIDP1{"confKaonPIDP1", 0.3f, "mom range 1 for kaon PID."}; - Configurable confKaonPIDP2{"confKaonPIDP2", 0.45f, "mom range 2 for kaon PID."}; - Configurable confKaonPIDP3{"confKaonPIDP3", 0.55f, "mom range 3 for kaon PID."}; - Configurable confKaonPIDP4{"confKaonPIDP4", 1.5f, "mom range 4 for kaon PID."}; - - Configurable confKaonTPCNsigma1{"confKaonTPCNsigma1", 3.0f, "TPC Kaon NSigma for mom range 1."}; - Configurable confKaonTPCNsigma2{"confKaonTPCNsigma2", 2.0f, "TPC Kaon NSigma for mom range 2."}; - Configurable confKaonTPCNsigma3{"confKaonTPCNsigma3", 1.0f, "TPC Kaon NSigma for mom range 3."}; - Configurable confKaonTPCNsigma4{"confKaonTPCNsigma4", 3.0f, "TPC Kaon NSigma for mom range 4."}; - Configurable confKaonTPCNsigma5{"confKaonTPCNsigma5", 2.0f, "TPC Kaon NSigma for mom range 5."}; - Configurable confKaonTOFNsigma4{"confKaonTOFNsigma4", 3.0f, "TOF Kaon NSigma for mom range 4."}; - Configurable confKaonTOFNsigma5{"confKaonTOFNsigma5", 3.0f, "TOF Kaon NSigma for mom range 5."}; - - Configurable> confCutTable{"confCutTable", {cutsTable[0], NPart, NCuts, partNames, cutNames}, "Particle selections"}; - Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; - Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; - Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This Configurable needs to be the same as the one used in the producer task"}; - Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; - Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; - Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; - Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; - Configurable confIsCPRatITS{"confIsCPRatITS", false, "Close Pair check at ITS"}; - Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; - Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; - Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; - Configurable confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; - Configurable confIsCPRkT{"confIsCPRkT", true, "kT dependent deltaEta-deltaPhi cut for Close Pair Rejection"}; - Configurable confIsCPRFraction{"confIsCPRFraction", true, "Close Pair Rejection with fraction of merged points"}; - Configurable confTrkDCAxyMax{"confTrkDCAxyMax", 0.2, "Max DCA in xy "}; - Configurable confTrkDCAzMax{"confTrkDCAzMax", 0.2, "Max DCA in z "}; - Configurable confTrkTPCcRowsMin{"confTrkTPCcRowsMin", 80, "Min of TPC crossed rows"}; - Configurable confTrkTPCfClsMin{"confTrkTPCfClsMin", 0.83, "Min. fraction of crossed rows/findable TPC clusters"}; - Configurable confTrkTPCfracsClsMax{"confTrkTPCfracsClsMax", 1.0, "Max of fraction of TPC shared cluster "}; - Configurable confTrkTPCnClsMin{"confTrkTPCnClsMin", 80, "Min number of TPC clusters"}; - Configurable confTrkTPCsClsMax{"confTrkTPCsClsMax", 160, "Max number of TPC shared clusters"}; - Configurable confPairFracSharedTPCclsMin{"confPairFracSharedTPCclsMin", 0.0, "Min. fraction of TPC shared clusters between two closed tracks"}; - Configurable confPairFracSharedTPCclsMax{"confPairFracSharedTPCclsMax", 1.0, "Miax. fraction of TPC shared clusters between two closed tracks"}; - Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; - Configurable confUseCCImCut{"confUseCCImCut", false, "Fill SH within specific quadrants of qout-qside"}; - Configurable confMinqTcut{"confMinqTcut", 0.005, "Min. qT cut on filling SH"}; - Configurable confUse1stand3rd{"confUse1stand3rd", false, "Use first and third quadrants of qout-qside"}; - Configurable confUse2ndand4th{"confUse2ndand4th", false, "Use second and fourth quadrants of qout-qside"}; - Configurable confIsFillAngqLCMS{"confIsFillAngqLCMS", true, "Fill qLCMS vs dEta vs dPhi"}; - Configurable confCPRDistMax{"confCPRDistMax", 0.0, "Max. radial seperation between two closed-pairs"}; - Configurable confCPRFracMax{"confCPRFracMax", 0.0, "Max. allowed fraction bad to all TPC points of radial seperation between two closed-pairs"}; - Configurable confCPRDphiAvgOrDist{"confCPRDphiAvgOrDist", true, "Close Pair Rejection by radial or angular seperation"}; - Configurable confIsCircularCut{"confIsCircularCut", true, "Close Pair Rejection within circular area"}; - Configurable confIs1D{"confIs1D", true, "Filling 1D 2k* dist. in MC truth"}; - Configurable confisIdenLCMS{"confisIdenLCMS", true, "Choosing identical or non-identical pairs in LCMS"}; - Configurable confIsWeight{"confIsWeight", true, "Fill quantum weight"}; - Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; - Configurable confIsfilldEtadPhiTPCcls{"confIsfilldEtadPhiTPCcls", false, "Filling of 3D histogram PairFracSharedTPCcls vs. dEta vs. dPhiStar"}; - Configurable confRandValue{"confRandValue", 0.5, "Value of random-number generator to shuffle pair"}; - - Configurable> confCPRdeltaEtaCutMaxVec{"confCPRdeltaEtaCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR"}; - Configurable> confCPRdeltaEtaCutMinVec{"confCPRdeltaEtaCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR"}; - Configurable> confCPRdeltaPhiCutMaxVec{"confCPRdeltaPhiCutMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR"}; - Configurable> confCPRdeltaPhiCutMinVec{"confCPRdeltaPhiCutMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR"}; - - Configurable> confCPRdeltaEtaCutFractionMaxVec{"confCPRdeltaEtaCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta eta cut in CPR Fraction"}; - Configurable> confCPRdeltaEtaCutFractionMinVec{"confCPRdeltaEtaCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta eta cut in CPR Fraction"}; - Configurable> confCPRdeltaPhiCutFractionMaxVec{"confCPRdeltaPhiCutFractionMaxVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for max delta phi cut in CPR Fraction"}; - Configurable> confCPRdeltaPhiCutFractionMinVec{"confCPRdeltaPhiCutFractionMinVec", std::vector{0.0f, 0.0f, 0.0f, 0.0f}, "Bins for min delta phi cut in CPR Fraction"}; - - ConfigurableAxis confDeltaEtaAxis{"confDeltaEtaAxis", {100, -0.15, 0.15}, "DeltaEta"}; - ConfigurableAxis confDeltaPhiStarAxis{"confDeltaPhiStarAxis", {100, -0.15, 0.15}, "DeltaPhiStar"}; - } twotracksconfigs; - - using FemtoFullParticles = soa::Join; - // Filters for selecting particles (both p1 and p2) - Filter trackAdditionalfilter = ((nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax) && - (aod::track::dcaXY <= twotracksconfigs.confTrkDCAxyMax) && - (aod::track::dcaZ <= twotracksconfigs.confTrkDCAzMax) && - (aod::femtouniverseparticle::tpcNClsCrossedRows >= static_cast(twotracksconfigs.confTrkTPCcRowsMin)) && - (aod::femtouniverseparticle::tpcFractionSharedCls <= twotracksconfigs.confTrkTPCfracsClsMax) && - (aod::femtouniverseparticle::tpcNClsFound >= static_cast(twotracksconfigs.confTrkTPCnClsMin)) && - (aod::track::tpcNClsShared <= static_cast(twotracksconfigs.confTrkTPCsClsMax))); - - using FilteredFemtoFullParticles = soa::Filtered; - // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this optionconfIsCPRkT - using FemtoRecoParticles = soa::Join; - using FilteredFemtoRecoParticles = soa::Filtered; - - SliceCache cache; - Preslice perCol = aod::femtouniverseparticle::fdCollisionId; - - using FemtoTruthParticles = soa::Join; - Preslice perColMCTruth = aod::femtouniverseparticle::fdCollisionId; - - /// Particle 1 - struct : o2::framework::ConfigurableGroup { - Configurable confPDGCodePartOne{"confPDGCodePartOne", 211, "Particle 1 - PDG code"}; - Configurable confPIDPartOne{"confPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> - Configurable confPtLowPart1{"confPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; - Configurable confPtHighPart1{"confPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; - Configurable confChargePart1{"confChargePart1", 1, "Particle 1 sign"}; - } trackonefilter; - - /// Partition for particle 1 - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; - Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; - Partition partsOneMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); - - // - - /// Histogramming for particle 1 - FemtoUniverseParticleHisto trackHistoPartOne; - - /// Particle 2 - struct : o2::framework::ConfigurableGroup { - Configurable confPDGCodePartTwo{"confPDGCodePartTwo", 211, "Particle 2 - PDG code"}; - // Configurable confCutPartTwo{"confCutPartTwo", 5542474, "Particle 2 - Selection bit"}; - Configurable confPIDPartTwo{"confPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> - - Configurable confPtLowPart2{"confPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; - Configurable confPtHighPart2{"confPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; - Configurable confChargePart2{"confChargePart2", -1, "Particle 2 sign"}; - } tracktwofilter; - - /// Partition for particle 2 - Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; - Partition partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; - Partition partsTwoMCTruth = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack); - - /// Histogramming for particle 2 - FemtoUniverseParticleHisto trackHistoPartTwo; - - /// Histogramming for Event - FemtoUniverseEventHisto eventHisto; - - /// The Configurables need to be passed to an std::vector - int vPIDPartOne, vPIDPartTwo; - std::vector kNsigma; - - /// Event part - Configurable confV0MLow{"confV0MLow", 0.0, "Lower limit for V0M multiplicity"}; - Configurable confV0MHigh{"confV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; - Configurable confTPCOccupancyLow{"confTPCOccupancyLow", 0, "Lower limit for TPC occupancy"}; - Configurable confTPCOccupancyHigh{"confTPCOccupancyHigh", 500, "Higher limit for TPC occupancy"}; - Configurable confIntRateLow{"confIntRateLow", 0.0, "Lower limit for interaction rate"}; - Configurable confIntRateHigh{"confIntRateHigh", 10000.0, "Higher limit for interaction rate"}; - Configurable confIsCent{"confIsCent", true, "Condition to choose centrality of multiplicity for mixing"}; - - Filter collfilterFDtable = (o2::aod::femtouniversecollision::multV0M > confV0MLow) && (o2::aod::femtouniversecollision::multV0M < confV0MHigh); - Filter collfilterFDExttable = (o2::aod::femtouniversecollision::interactionRate > confIntRateLow) && (o2::aod::femtouniversecollision::interactionRate < confIntRateHigh) && - (o2::aod::femtouniversecollision::occupancy >= confTPCOccupancyLow) && (o2::aod::femtouniversecollision::occupancy < confTPCOccupancyHigh); - using FilteredFDCollisions = soa::Filtered>; - using FilteredFDCollision = FilteredFDCollisions::iterator; - // Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on Configurable - - /// Particle part - ConfigurableAxis confTempFitVarBins{"confTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; - - /// Correlation part - ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 12.5f, 15.0f, 17.5f, 20.0f, 22.5f, 25.0f, 27.5f, 30.0f, 32.5f, 35.0f, 37.5f, 40.0f, 42.5f, 45.0f, 47.5f, 50.0f, 52.5f, 55.0f, 57.5f, 60.0f, 62.5f, 65.0f, 67.5f, 70.5f, 75.0f, 80.0f, 90.0f, 100.0f, 99999.f}, "Mixing bins - centrality"}; - ConfigurableAxis confMultBinsMult{"confMultBinsMult", {VARIABLE_WIDTH, 0.0f, 400.0f, 800.0f, 1200.0f, 1600.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f, 10000.0f, 11000.0f, 12000.0f, 13000.0f, 14000.0f, 15000.0f, 16000.0f, 17000.0f, 18000.0f, 99999.f}, "Mixing bins - centrality"}; - ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; - ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; - ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - - ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; - ConfigurableAxis confmultBins3D{"confmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; - - ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBinsCent}, true}; - ColumnBinningPolicy colBinningNtr{{confVtxBins, confMultBinsMult}, true}; - - ConfigurableAxis confkstarBins{"confkstarBins", {60, 0.0, 0.3}, "binning kstar"}; - ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; - ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; - Configurable confIsLCMS{"confIsLCMS", true, "Choosing LCMS or PRF"}; - Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; - Configurable confLMax{"confLMax", 2, "Maximum value of l"}; - Configurable cfgProcessPM{"cfgProcessPM", false, "Process particles of the opposite charge"}; - Configurable cfgProcessPP{"cfgProcessPP", true, "Process particles of the same, positice charge"}; - Configurable cfgProcessMM{"cfgProcessMM", true, "Process particles of the same, positice charge"}; - Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; - Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; - Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; - - Configurable confRejectGammaPair{"confRejectGammaPair", false, "Additional check to reject e+e- pairs base on theta and minv"}; - Configurable confMaxEEMinv{"confMaxEEMinv", 0.002, "Max. minv of e-e+ pair for gamma pair rejection"}; - Configurable confMaxDTheta{"confMaxDTheta", 0.008, "Max. DeltaTheta of pair for gamma pair rejection"}; - - FemtoUniverseSHContainer sameEventCont; - FemtoUniverseSHContainer mixedEventCont; - - FemtoUniverseSHContainer sameEventContPP; - FemtoUniverseSHContainer mixedEventContPP; - - FemtoUniverseSHContainer sameEventContMM; - FemtoUniverseSHContainer mixedEventContMM; - - FemtoUniverseContainer sameEventCont1dpp; - FemtoUniverseContainer mixedEventCont1dpp; - FemtoUniverseContainer sameEventCont1dmm; - FemtoUniverseContainer mixedEventCont1dmm; - - FemtoUniversePairCleaner pairCleaner; - FemtoUniverseDetaDphiStar pairCloseRejection; - FemtoUniverseTrackSelection trackCuts; - - PairSHCentMultKt sameEventMultCont; - PairSHCentMultKt mixedEventMultCont; - - PairSHCentMultKt sameEventMultContPP; - PairSHCentMultKt mixedEventMultContPP; - - PairSHCentMultKt sameEventMultContMM; - PairSHCentMultKt mixedEventMultContMM; - - float mass1 = -1; - float mass2 = -1; - - /// Histogram output - HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry resultRegistry1D{"Correlations1D", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry resultRegistryPM{"CorrelationsPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry resultRegistryPP{"CorrelationsPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry resultRegistryMM{"CorrelationsMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; - - HistogramRegistry sameMultRegistryPM{"sameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mixedMultRegistryPM{"mixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - HistogramRegistry sameMultRegistryPP{"sameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mixedMultRegistryPP{"mixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - HistogramRegistry sameMultRegistryMM{"sameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry mixedMultRegistryMM{"mixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - TRandom2* randgen; - - // PID for protons - bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx - { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using Configurables: - // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed - // confNsigmaTPC -> TPC Sigma for momentum < 0.5 - // confNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 - - if (mom < twotracksconfigs.confTOFPtMin) { - if (std::abs(nsigmaTPCPr) < twotracksconfigs.confNsigmaTPC) { - return true; - } else { - return false; - } - } else { - if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.confNsigmaCombined) { - return true; - } else { - return false; - } - } - return false; - } - - bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) - { - if (mom < twotracksconfigs.confKaonPIDP1) { // 0.0-0.3 - if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma1) { - return true; - } else { - return false; - } - } else if (mom < twotracksconfigs.confKaonPIDP2) { // 0.30 - 0.45 - if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma2) { - return true; - } else { - return false; - } - } else if (mom < twotracksconfigs.confKaonPIDP3) { // 0.45-0.55 - if (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTPCNsigma3) { - return true; - } else { - return false; - } - } else if (mom < twotracksconfigs.confKaonPIDP4) { // 0.55-1.5 (now we use TPC and TOF) - if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma4) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma4)) { - { - return true; - } - } else { - return false; - } - } else if (mom > twotracksconfigs.confKaonPIDP4) { // 1.5 - - if ((std::abs(nsigmaTOFK) < twotracksconfigs.confKaonTPCNsigma5) && (std::abs(nsigmaTPCK) < twotracksconfigs.confKaonTOFNsigma5)) { - return true; - } else { - return false; - } - } else { - return false; - } - } - - bool isPionNSigma(float mom, float nsigmaITSPi, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCElReject) - { - //|nsigma_TPC| < 3 for p < 0.5 GeV/c - //|nsigma_combined| < 3 for p > 0.5 - - // using Configurables: - // confTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed - // confNsigmaTPC -> TPC Sigma for momentum < 0.5 - // confNsigmaCombined -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 - if (true) { - if (mom < twotracksconfigs.confTOFPtMin) { - if (twotracksconfigs.confIsElReject) { - if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC) && (nsigmaTPCElReject < twotracksconfigs.confNsigmaTPCElRejectMin || nsigmaTPCElReject > twotracksconfigs.confNsigmaTPCElRejectMax)) { - return true; - } else { - return false; - } - } else if (twotracksconfigs.confIsAddITSNsigma) { - if (std::hypot(nsigmaITSPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaITSTPCCombined) { - return true; - } else { - return false; - } - } else { - if ((std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC)) { - return true; - } else { - return false; - } - } - } else { - if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaCombined) { - return true; - } else { - return false; - } - } - } - return false; - } - - bool isParticleNSigma(ParticleNumber particle_number, float mom, float nsigmaITSPi, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCElReject) - { - if (particle_number == ParticleNumber::First) { - switch (trackonefilter.confPDGCodePartOne) { - case 2212: // Proton - case -2212: // Antiproton - return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); - break; - case 211: // Pion+ - case -211: // Pion- - return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); - break; - case 321: // Kaon+ - case -321: // Kaon- - return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); - break; - default: - return false; - } - return false; - } else if (particle_number == ParticleNumber::Second) { - switch (tracktwofilter.confPDGCodePartTwo) { - case 2212: // Proton - case -2212: // Antiproton - return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); - break; - case 211: // Pion+ - case -211: // Pion- - return isPionNSigma(mom, nsigmaITSPi, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCElReject); - break; - case 321: // Kaon+ - case -321: // Kaon- - return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); - break; - default: - return false; - } - return false; - } else { - LOGF(fatal, "Wrong number of particle chosen! It should be First or Second."); - } - return false; - } - - void init(InitContext&) - { - - colBinningCent = ColumnBinningPolicy{{confVtxBins, confMultBinsCent}, true}; - colBinningNtr = ColumnBinningPolicy{{confVtxBins, confMultBinsMult}, true}; - - eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); - - trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true, std::nullopt, twotracksconfigs.confIsAddITSNsigma); - - mixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - - mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); - mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); - - if (cfgProcessPM) { - if (!cfgProcessKtMt3DCF) { - sameEventCont.init(&resultRegistryPM, confkstarBins, confLMax); - mixedEventCont.init(&resultRegistryPM, confkstarBins, confLMax); - sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - } else { - sameEventMultCont.init(&sameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultCont.init(&mixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - } - } - - if (cfgProcessPP) { - if (!cfgProcessKtMt3DCF) { - sameEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); - mixedEventContPP.init(&resultRegistryPP, confkstarBins, confLMax); - sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - } else { - sameEventMultContPP.init(&sameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultContPP.init(&mixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - } - sameEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - sameEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventCont1dpp.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - mixedEventCont1dpp.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - } - - if (cfgProcessMM) { - if (!cfgProcessKtMt3DCF) { - sameEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); - mixedEventContMM.init(&resultRegistryMM, confkstarBins, confLMax); - sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - } else { - sameEventMultContMM.init(&sameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - mixedEventMultContMM.init(&mixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); - } - sameEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - sameEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - mixedEventCont1dmm.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); - mixedEventCont1dmm.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); - } - - pairCleaner.init(&qaRegistry); - if (twotracksconfigs.confIsCPR.value) { - pairCloseRejection.init(&resultRegistry, &qaRegistry, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMin.value, twotracksconfigs.confCPRdeltaPhiCutMax.value, twotracksconfigs.confCPRdeltaEtaCutMin.value, twotracksconfigs.confCPRdeltaEtaCutMax.value, twotracksconfigs.confCPRChosenRadii.value, twotracksconfigs.confCPRPlotPerRadii.value); - pairCloseRejection.init_kT(&resultRegistry, confKtKstarBins, twotracksconfigs.confDeltaEtaAxis, twotracksconfigs.confDeltaPhiStarAxis, twotracksconfigs.confCPRdeltaPhiCutMinVec.value, twotracksconfigs.confCPRdeltaPhiCutMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutMinVec.value, twotracksconfigs.confCPRdeltaEtaCutMaxVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMinVec.value, twotracksconfigs.confCPRdeltaPhiCutFractionMaxVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMinVec.value, twotracksconfigs.confCPRdeltaEtaCutFractionMaxVec.value, twotracksconfigs.confIsfilldEtadPhiTPCcls); - } - - vPIDPartOne = trackonefilter.confPIDPartOne.value; - vPIDPartTwo = tracktwofilter.confPIDPartTwo.value; - kNsigma = twotracksconfigs.confTrkPIDnSigmaMax.value; - } - - template - void fillCollision(CollisionType col, bool IsCent) - { - if (IsCent) { - mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningCent.getBin({col.posZ(), col.multV0M()})); - } else { - mixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinningNtr.getBin({col.posZ(), col.multNtr()})); - } - eventHisto.fillQA(col); - } - - /// This function processes the same event and takes care of all the histogramming - /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - /// @tparam PartitionType - /// @tparam PartType - /// @tparam isMC: enables Monte Carlo truth specific histograms - /// @param groupPartsOne partition for the first particle passed by the process function - /// @param groupPartsTwo partition for the second particle passed by the process function - /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) - /// @param magFieldTesla magnetic field of the collision - /// @param multCol multiplicity of the collision - template - void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, PairType contType, bool fillQA) - { - /// Histogramming same event - if ((contType == PairType::PlusMinus || contType == PairType::PlusPlus) && fillQA) { - for (const auto& part : groupPartsOne) { - if (!isParticleNSigma(ParticleNumber::First, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { - continue; - } - trackHistoPartOne.fillQA(part); - if (twotracksconfigs.confIsAddITSNsigma) { - trackHistoPartOne.fillQAITSPID<>(part); - } - trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); - } - } - - if ((contType == PairType::PlusMinus || contType == PairType::MinusMinus) && fillQA) { - for (const auto& part : groupPartsTwo) { - if (!isParticleNSigma(ParticleNumber::Second, part.p(), trackCuts.getNsigmaITS(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(part, o2::track::PID::Electron))) { - continue; - } - trackHistoPartTwo.fillQA(part); - if (twotracksconfigs.confIsAddITSNsigma) { - trackHistoPartTwo.fillQAITSPID<>(part); - } - } - } - - if (contType == PairType::PlusMinus) { - - /// Now build the combinations for non-identical particle pairs - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - if (!isParticleNSigma(ParticleNumber::First, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { - continue; - } - - if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { - continue; - } - - if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { - continue; - } - - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - float lastElement = confKtKstarBins.value.back(); - float firstRealElement = confKtKstarBins.value[1]; - - if (kT < firstRealElement || kT > lastElement) - continue; - float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); - if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { - continue; - } - - if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { - if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { - continue; - } - } else { - if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { - continue; - } - } else { - if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { - continue; - } - } - } - } - - // track cleaning - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - - sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } else { - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { - - if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { - continue; - } - - if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { - continue; - } - - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - float lastElement = confKtKstarBins.value.back(); - float firstRealElement = confKtKstarBins.value[1]; - - if (kT < firstRealElement || kT > lastElement) - continue; - - float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); - if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { - continue; - } - - double rand; - rand = randgen->Rndm(); - - auto part1 = p1; - auto part2 = p2; - - if (rand > twotracksconfigs.confRandValue) { - part1 = p2; - part2 = p1; - } - - if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { - if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::same)) { - continue; - } - } else { - if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { - continue; - } - if (twotracksconfigs.confIsCPRFraction) { - if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::same, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { - continue; - } - } - } else { - if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { - continue; - } - } - } - } - - // track cleaning - if (!pairCleaner.isCleanPair(part1, part2, parts)) { - continue; - } - - std::vector f3d; - double kv; - float outsideref = 0.0; - switch (contType) { - case PairType::PlusPlus: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - if (!twotracksconfigs.confUseCCImCut) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } else { - if (twotracksconfigs.confUse1stand3rd) { - if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } else if (twotracksconfigs.confUse2ndand4th) { - if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } - } - if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { - float weight = 1.0f; - sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } - if (twotracksconfigs.confIsFillAngqLCMS) { - kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); - pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); - } - break; - } - - case PairType::MinusMinus: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - if (!twotracksconfigs.confUseCCImCut) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } else { - if (twotracksconfigs.confUse1stand3rd) { - if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } else if (twotracksconfigs.confUse2ndand4th) { - if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } - } - if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { - float weight = 1.0f; - sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } - if (twotracksconfigs.confIsFillAngqLCMS) { - kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); - pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::same, kv); - } - break; - } - default: - break; - } - } - } - } - - /// process function for to call doSameEvent with Data - /// \param col subscribe to the collision table (Data) - /// \param parts subscribe to the femtoUniverseParticleTable - void processSameEvent(FilteredFDCollision const& col, - FilteredFemtoFullParticles const& parts) - { - fillCollision(col, confIsCent); - - auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - - bool fillQA = true; - randgen = new TRandom2(0); - - if (confIsCent) { - if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); - } - if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); - } - if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); - } - } else { - if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); - } - if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); - } - if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEvent, "Enable processing same event", true); - - /// process function for to call doSameEvent with Monte Carlo - /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) - /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth - /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table - void processSameEventMC(o2::aod::FdCollision const& col, - FilteredFemtoRecoParticles const& parts, - aod::FdMCParticles const&) - { - fillCollision(col, confIsCent); - - auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - bool fillQA = true; - randgen = new TRandom2(0); - - if (confIsCent) { - if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); - } - if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); - } - if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); - } - } else { - if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); - } - if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); - } - if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEventMC, "Enable processing same event for Monte Carlo", false); - - /// This function processes the same event and takes care of all the histogramming - /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - /// @tparam PartitionType - /// @tparam PartType - /// @tparam isMC: enables Monte Carlo truth specific histograms - /// @param groupPartsOne partition for the first particle passed by the process function - /// @param groupPartsTwo partition for the second particle passed by the process function - /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) - /// @param magFieldTesla magnetic field of the collision - /// @param multCol multiplicity of the collision - template - void doSameEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType, bool fillQA) - { - - randgen = new TRandom2(0); - /// Histogramming same event - if ((cfgProcessPM || cfgProcessPP) && fillQA) { - for (const auto& part : groupPartsOne) { - if (part.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) { - int pdgCode = static_cast(part.tempFitVar()); - const auto& pdgParticle = pdg->GetParticle(pdgCode); - if (pdgParticle) { - trackHistoPartOne.fillQA(part); - } - } - } - } - - if ((cfgProcessPM || cfgProcessMM) && fillQA) { - for (const auto& part : groupPartsTwo) { - if (part.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) { - int pdgCode = static_cast(part.tempFitVar()); - const auto& pdgParticle = pdg->GetParticle(pdgCode); - if (pdgParticle) { - trackHistoPartTwo.fillQA(part); - } - } - } - } - - if (cfgProcessPM) { - - /// Now build the combinations for non-identical particle pairs - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - int pdgCodePartOne = static_cast(p1.tempFitVar()); - const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); - int pdgCodePartTwo = static_cast(p2.tempFitVar()); - const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); - if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } - } else { - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { - - int pdgCodePartOne = static_cast(p1.tempFitVar()); - const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); - int pdgCodePartTwo = static_cast(p2.tempFitVar()); - const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); - - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - double rand; - rand = randgen->Rndm(); - std::vector f3d; - if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { - - auto part1 = p1; - auto part2 = p2; - - if (rand > twotracksconfigs.confRandValue) { - part1 = p2; - part2 = p1; - } - - switch (contType) { - case PairType::PlusPlus: { - if (twotracksconfigs.confIs1D) { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - float weight = f3d[5]; - sameEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } else { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - break; - } - - case PairType::MinusMinus: { - if (twotracksconfigs.confIs1D) { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - float weight = f3d[5]; - sameEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } else { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - break; - } - default: - break; - } - } - } - } - delete randgen; - } - - /// process function for to call doSameEvent with Monte Carlo - /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) - /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth - /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table - void processSameEventMCTruth(o2::aod::FdCollision const& col, - FemtoTruthParticles const&) - { - fillCollision(col, confIsCent); - - auto thegroupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - bool fillQA = true; - - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - if (confIsCent) { - if (cfgProcessPM) { - doSameEventMCTruth(thegroupPartsOne, thegroupPartsTwo, col.multV0M(), pairType, fillQA); - } - if (cfgProcessPP) { - doSameEventMCTruth(thegroupPartsOne, thegroupPartsOne, col.multV0M(), pairType, fillQA); - } - if (cfgProcessMM) { - doSameEventMCTruth(thegroupPartsTwo, thegroupPartsTwo, col.multV0M(), pairType, fillQA); - } - } else { - if (cfgProcessPM) { - doSameEventMCTruth(thegroupPartsOne, thegroupPartsTwo, col.multNtr(), pairType, fillQA); - } - if (cfgProcessPP) { - doSameEventMCTruth(thegroupPartsOne, thegroupPartsOne, col.multNtr(), pairType, fillQA); - } - if (cfgProcessMM) { - doSameEventMCTruth(thegroupPartsTwo, thegroupPartsTwo, col.multNtr(), pairType, fillQA); - } - } - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processSameEventMCTruth, "Enable processing same event for MC truth", false); - - /// This function processes the mixed event - /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - /// \tparam PartitionType - /// \tparam PartType - /// \tparam isMC: enables Monte Carlo truth specific histograms - /// \param groupPartsOne partition for the first particle passed by the process function - /// \param groupPartsTwo partition for the second particle passed by the process function - /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) - /// \param magFieldTesla magnetic field of the collision - /// \param multCol multiplicity of the collision - template - void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, PairType contType) - { - - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - if (!isParticleNSigma(ParticleNumber::Second, p1.p(), trackCuts.getNsigmaITS(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p1, o2::track::PID::Electron))) { - continue; - } - - if (!isParticleNSigma(ParticleNumber::Second, p2.p(), trackCuts.getNsigmaITS(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTPC(p2, o2::track::PID::Electron))) { - continue; - } - - if (confRejectGammaPair && pairCloseRejection.isGammaPair(p1, p2, confMaxEEMinv, confMaxDTheta)) { - continue; - } - - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - float lastElement = confKtKstarBins.value.back(); - float firstRealElement = confKtKstarBins.value[1]; - - if (kT < firstRealElement || kT > lastElement) - continue; - - float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); - if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { - continue; - } - - double rand; - rand = randgen->Rndm(); - auto part1 = p1; - auto part2 = p2; - - if (rand > twotracksconfigs.confRandValue) { - part1 = p2; - part2 = p1; - } - - if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { - if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed)) { - continue; - } - } else { - if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(part1, part2, femto_universe_container::EventType::mixed, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsfilldEtadPhiTPCcls, pairFractionTPCsCls)) { - continue; - } - if (twotracksconfigs.confIsCPRFraction) { - if (pairCloseRejection.isClosePairFractionkT(part1, part2, femto_universe_container::EventType::mixed, kT, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { - continue; - } - } - } else { - if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { - continue; - } - } - } - } - - std::vector f3d; - double kv; - float outsideref = 0.0; - - switch (contType) { - case PairType::PlusMinus: { - mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - break; - } - - case PairType::PlusPlus: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - if (!twotracksconfigs.confUseCCImCut) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } else { - if (twotracksconfigs.confUse1stand3rd) { - if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } else if (twotracksconfigs.confUse2ndand4th) { - if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } - } - if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { - float weight = 1.0f; - mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } - - if (twotracksconfigs.confIsFillAngqLCMS) { - kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); - pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); - } - break; - } - - case PairType::MinusMinus: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - if (!twotracksconfigs.confUseCCImCut) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } else { - if (twotracksconfigs.confUse1stand3rd) { - if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } else if (twotracksconfigs.confUse2ndand4th) { - if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - } - } - if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { - float weight = 1.0f; - mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } - if (twotracksconfigs.confIsFillAngqLCMS) { - kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); - pairCloseRejection.ClosePairqLCMS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, kv); - } - break; - } - - default: - break; - } - } - } - - /// process function for to call doMixedEvent with Data - /// @param cols subscribe to the collisions table (Data) - /// @param subscribe to the femtoUniverseParticleTable - void processMixedEventCent(FilteredFDCollisions const& cols, - FilteredFemtoFullParticles const&) - { - randgen = new TRandom2(0); - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multV0M(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); - - const auto& magFieldTesla1 = collision1.magField(); - const auto& magFieldTesla2 = collision2.magField(); - - if (magFieldTesla1 != magFieldTesla2) { - continue; - } - - if (cfgProcessPM) { - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventCent, "Enable processing mixed events for centrality", true); - - /// process function for to call doMixedEvent with Data - /// @param cols subscribe to the collisions table (Data) - /// @param parts subscribe to the femtoUniverseParticleTable - void processMixedEventNtr(FilteredFDCollisions const& cols, - FilteredFemtoFullParticles const&) - { - randgen = new TRandom2(0); - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multNtr(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); - - const auto& magFieldTesla1 = collision1.magField(); - const auto& magFieldTesla2 = collision2.magField(); - - if (magFieldTesla1 != magFieldTesla2) { - continue; - } - - if (cfgProcessPM) { - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventNtr, "Enable processing mixed events for centrality", false); - - /// brief process function for to call doMixedEvent with Monte Carlo - /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) - /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth - /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table - void processMixedEventMCCent(o2::aod::FdCollisions const& cols, - soa::Join const&, - o2::aod::FdMCParticles const&) - { - randgen = new TRandom2(0); - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multV0M(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); - - const auto& magFieldTesla1 = collision1.magField(); - const auto& magFieldTesla2 = collision2.magField(); - - if (magFieldTesla1 != magFieldTesla2) { - continue; - } - /// \todo before mixing we should check whether both collisions contain a pair of particles! - if (cfgProcessPM) { - auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventMCCent, "Enable processing mixed events MC", false); - - /// brief process function for to call doMixedEvent with Monte Carlo - /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) - /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth - /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table - void processMixedEventMCNtr(o2::aod::FdCollisions const& cols, - soa::Join const&, - o2::aod::FdMCParticles const&) - { - randgen = new TRandom2(0); - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multV0M(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); - - const auto& magFieldTesla1 = collision1.magField(); - const auto& magFieldTesla2 = collision2.magField(); - - if (magFieldTesla1 != magFieldTesla2) { - continue; - } - /// \todo before mixing we should check whether both collisions contain a pair of particles! - if (cfgProcessPM) { - auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); - } - } - delete randgen; - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventMCNtr, "Enable processing mixed events MC", false); - - /// This function processes the mixed event - /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - /// \tparam PartitionType - /// \tparam PartType - /// \tparam isMC: enables Monte Carlo truth specific histograms - /// \param groupPartsOne partition for the first particle passed by the process function - /// \param groupPartsTwo partition for the second particle passed by the process function - /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) - /// \param magFieldTesla magnetic field of the collision - /// \param multCol multiplicity of the collision - template - void doMixedEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType) - { - randgen = new TRandom2(0); - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - int pdgCodePartOne = static_cast(p1.tempFitVar()); - const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); - int pdgCodePartTwo = static_cast(p2.tempFitVar()); - const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); - - float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - double rand; - rand = randgen->Rndm(); - std::vector f3d; - - if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { - - auto part1 = p1; - auto part2 = p2; - - if (rand > twotracksconfigs.confRandValue) { - part1 = p2; - part2 = p1; - } - switch (contType) { - case PairType::PlusMinus: { - mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - break; - } - - case PairType::PlusPlus: { - if (twotracksconfigs.confIs1D) { - float weight = 1.0; - mixedEventCont1dpp.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } else { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - break; - } - - case PairType::MinusMinus: { - if (twotracksconfigs.confIs1D) { - float weight = 1.0; - mixedEventCont1dmm.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); - } else { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); - } - break; - } - default: - break; - } - } - } - delete randgen; - } - - /// process function for to call doMixedEvent with Data - /// @param cols subscribe to the collisions table (Data) - /// @param parts subscribe to the femtoUniverseParticleTable - void processMixedEventNtrMCTruth(o2::aod::FdCollisions const& cols, - FemtoTruthParticles const&) - { - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multNtr(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); - - if (cfgProcessPM) { - auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - } - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventNtrMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); - - /// process function for to call doMixedEvent with Data - /// @param cols subscribe to the collisions table (Data) - /// @param parts subscribe to the femtoUniverseParticleTable - void processMixedEventCentMCTruth(o2::aod::FdCollisions const& cols, - FemtoTruthParticles const&) - { - PairType pairType = PairType::PlusMinus; - if (cfgProcessPM) { - pairType = PairType::PlusMinus; - } else if (cfgProcessPP) { - pairType = PairType::PlusPlus; - } else if (cfgProcessMM) { - pairType = PairType::MinusMinus; - } - - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { - - const int multiplicityCol = collision1.multV0M(); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); - - if (cfgProcessPM) { - auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - if (cfgProcessPP) { - auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - if (cfgProcessMM) { - auto groupPartsOne = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); - } - } - } - PROCESS_SWITCH(FemtoUniversePairTaskTrackTrackSpherHarMultKtExtendedITSPID, processMixedEventCentMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), - }; - return workflow; -} \ No newline at end of file