diff --git a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h index f536077ce95..4d7f2e7aca5 100644 --- a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h +++ b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h @@ -9,9 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FEMTOWORLDDERIVED_H_ -#define FEMTOWORLDDERIVED_H_ +#ifndef PWGCF_FEMTOWORLD_DATAMODEL_FEMTOWORLDDERIVED_H_ +#define PWGCF_FEMTOWORLD_DATAMODEL_FEMTOWORLDDERIVED_H_ +#include #include "Framework/ASoA.h" #include "MathUtils/Utils.h" #include "Framework/DataTypes.h" @@ -20,7 +21,6 @@ #include "Framework/Expressions.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/PIDResponse.h" -#include namespace o2::aod { @@ -195,4 +195,4 @@ DECLARE_SOA_TABLE(FemtoHashes, "AOD", "HASH", femtohash::FemtoBin); using FemtoHash = FemtoHashes::iterator; } // namespace o2::aod -#endif /* FEMTOWORLDDERIVED_H_ */ +#endif // PWGCF_FEMTOWORLD_DATAMODEL_FEMTOWORLDDERIVED_H_ diff --git a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt index 30f7e2d471f..5e9016953f8 100644 --- a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt @@ -17,4 +17,14 @@ o2physics_add_dpl_workflow(femto-world-pair-track-track o2physics_add_dpl_workflow(femto-world-pair-track-phi SOURCES femtoWorldPairTaskTrackPhi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-world-pion-pair-track-track + SOURCES femtoWorldPionPairTaskTrackTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-world-pion-all-pair-track-track + SOURCES femtoWorldPionAllPairTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx new file mode 100644 index 00000000000..b290011a1c2 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx @@ -0,0 +1,452 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoWorldPionAllPair.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Deependra Sharma, IITB, deependra.sharma@cern.ch + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" + +#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldContainer.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoWorld; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace o2::aod +{ +// using FemtoWorldParticlesMerged = soa::Join; +using FemtoWorldParticlesMerged = aod::FemtoWorldParticles; +using FemtoWorldParticleMerged = FemtoWorldParticlesMerged::iterator; +} // namespace o2::aod + +// Particle Sign +enum SignofPair { + MinusSign = -1, + PlusSign = 1, + NSigns +}; + +struct FemtoWorldPionAllPair { + // for filling phi candidates table + // Produces outputCollision; + // Produces outputPhiCan; + // std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + + /// @brief read configurable and sets corresponding cuts + /// @tparam T type of configurable + /// @param cut local variable corresponding configurable to be set + template + void SetChargePair(T& cut1, T& cut2) + { + ChargePair.push_back(cut1); + ChargePair.push_back(cut2); + } + + Configurable cfgSignPartOne{"cfgSignPartOne", static_cast(PlusSign), "Sign of Firts particle"}; + Configurable cfgSignPartTwo{"cfgSignPartTwo", static_cast(PlusSign), "Sign of Second particle"}; + + std::vector ChargePair; + /// Particle selection part + + // Configurables for cuts + // First particle + Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable cfgPtHighPart1{"cfgPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable cfgEtaLowPart1{"cfgEtaLowPart1", -0.8, "Lower limit for Eta for the first particle"}; + Configurable cfgEtaHighPart1{"cfgEtaHighPart1", 0.8, "Higher limit for Eta for the first particle"}; + Configurable cfgDcaXYPart1{"cfgDcaXYPart1", 2.4, "Value for DCA_XY for the first particle"}; + Configurable cfgDcaZPart1{"cfgDcaZPart1", 3.2, "Value for DCA_Z for the first particle"}; + Configurable cfgTpcClPart1{"cfgTpcClPart1", 88, "Number of tpc clasters for the first particle"}; // min number of found TPC clusters + Configurable cfgTpcCrosRoPart1{"cfgTpcCrosRoPart1", 70, "Number of tpc crossed rows for the first particle"}; // min number of crossed rows + Configurable cfgChi2TpcPart1{"cfgChi2TpcPart1", 4.0, "Chi2 / cluster for the TPC track segment for the first particle"}; + Configurable cfgChi2ItsPart1{"cfgChi2ItsPart1", 36.0, "Chi2 / cluster for the ITS track segment for the first particle"}; + // Second particle + Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable cfgPtHighPart2{"cfgPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable cfgEtaLowPart2{"cfgEtaLowPart2", -0.8, "Lower limit for Eta for the second particle"}; + Configurable cfgEtaHighPart2{"cfgEtaHighPart2", 0.8, "Higher limit for Eta for the second particle"}; + Configurable cfgDcaXYPart2{"cfgDcaXYPart2", 2.4, "Value for DCA_XY for the second particle"}; + Configurable cfgDcaZPart2{"cfgDcaZPart2", 3.2, "Value for DCA_Z for the second particle"}; + Configurable cfgTpcClPart2{"cfgTpcClPart2", 88, "Number of tpc clasters for the second particle"}; // min number of found TPC clusters + Configurable cfgTpcCrosRoPart2{"cfgTpcCrosRoPart2", 70, "Number of tpc crossed rows for the second particle"}; // min number of crossed rows + Configurable cfgChi2TpcPart2{"cfgChi2TpcPart2", 4.0, "Chi2 / cluster for the TPC track segment for the second particle"}; + Configurable cfgChi2ItsPart2{"cfgChi2ItsPart2", 36.0, "Chi2 / cluster for the ITS track segment for the second particle"}; + + /// Particle 1 Pi+ + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; + Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from json file"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + + /// Partition for particle 1 + Partition partsOne = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) // particle type cut + && (aod::femtoworldparticle::pt < cfgPtHighPart1) && (aod::femtoworldparticle::pt > cfgPtLowPart1) // simple pT cuts + && (aod::femtoworldparticle::eta < cfgEtaHighPart1) && (aod::femtoworldparticle::eta > cfgEtaLowPart1) // Eta cuts + && (nabs(o2::aod::track::dcaXY) < cfgDcaXYPart1) && (nabs(o2::aod::track::dcaZ) < cfgDcaZPart1) // DCA cuts for XY and Z + && (aod::femtoworldparticle::tpcNClsFound > (uint8_t)cfgTpcClPart1) // Number of found TPC clusters + && (aod::femtoworldparticle::tpcNClsCrossedRows > (uint8_t)cfgTpcCrosRoPart1) // Crossed rows TPC + && (aod::femtoworldparticle::itsChi2NCl < cfgChi2ItsPart1) && (aod::femtoworldparticle::tpcChi2NCl < cfgChi2TpcPart1) //&& // chi2 cuts + && (aod::femtoworldparticle::sign == (int8_t)cfgSignPartOne); // todo: globaltrack cut + + Partition partsOneFailed = //~(aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) || // particle type cut + ((aod::femtoworldparticle::pt > cfgPtHighPart1) || (aod::femtoworldparticle::pt < cfgPtLowPart1)) || // pT cuts + ((aod::femtoworldparticle::eta > cfgEtaHighPart1) || (aod::femtoworldparticle::eta < cfgEtaLowPart1)) || // Eta cuts + (nabs(o2::aod::track::dcaXY) > cfgDcaXYPart1) || (nabs(o2::aod::track::dcaZ) > cfgDcaZPart1) || // DCA cuts for XY and Z + (aod::femtoworldparticle::tpcNClsFound < (uint8_t)cfgTpcClPart1) || // Number of found TPC clusters + (aod::femtoworldparticle::tpcNClsCrossedRows < (uint8_t)cfgTpcCrosRoPart1) || // Crossed rows TPC + (aod::femtoworldparticle::itsChi2NCl > cfgChi2ItsPart1) || (aod::femtoworldparticle::tpcChi2NCl > cfgChi2TpcPart1) || //&& // chi2 cuts + (aod::femtoworldparticle::sign != (int8_t)cfgSignPartOne); + /// Histogramming for particle 1 + FemtoWorldParticleHisto trackHistoPartOne; + FemtoWorldParticleHisto trackHistoPartOneFailed; + + /// Particle 2 Pi- + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; + Configurable> ConfPIDPartTwo{"ConfPIDPartTwo", std::vector{2}, "Particle 2 - Read from json file"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + /// Partition for particle 2 + Partition partsTwo = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) // particle type cut + && (aod::femtoworldparticle::pt < cfgPtHighPart2) && (aod::femtoworldparticle::pt > cfgPtLowPart2) // pT cuts + && (aod::femtoworldparticle::eta < cfgEtaHighPart2) && (aod::femtoworldparticle::eta > cfgEtaLowPart2) // Eta cuts + && (nabs(o2::aod::track::dcaXY) < cfgDcaXYPart2) && (nabs(o2::aod::track::dcaZ) < cfgDcaZPart2) // DCA cuts for XY and Z + && (aod::femtoworldparticle::tpcNClsFound > (uint8_t)cfgTpcClPart2) // Number of found TPC clusters + && (aod::femtoworldparticle::tpcNClsCrossedRows > (uint8_t)cfgTpcCrosRoPart2) // Crossed rows TPC + && (aod::femtoworldparticle::itsChi2NCl < cfgChi2ItsPart2) && (aod::femtoworldparticle::tpcChi2NCl < cfgChi2TpcPart2) // // chi2 cuts + && (aod::femtoworldparticle::sign == (int8_t)cfgSignPartTwo); + // todo: globaltrack cut + Partition partsTwoFailed = //(aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) || // particle type cut + ((aod::femtoworldparticle::pt > cfgPtHighPart2) || (aod::femtoworldparticle::pt < cfgPtLowPart2)) || // pT cuts + ((aod::femtoworldparticle::eta > cfgEtaHighPart2) || (aod::femtoworldparticle::eta < cfgEtaLowPart2)) || // Eta cuts + (nabs(o2::aod::track::dcaXY) > cfgDcaXYPart2) || (nabs(o2::aod::track::dcaZ) > cfgDcaZPart2) || // DCA cuts for XY and Z + (aod::femtoworldparticle::tpcNClsFound < (uint8_t)cfgTpcClPart2) || // Number of found TPC clusters + (aod::femtoworldparticle::tpcNClsCrossedRows < (uint8_t)cfgTpcCrosRoPart2) || // Crossed rows TPC + (aod::femtoworldparticle::itsChi2NCl > cfgChi2ItsPart2) || + (aod::femtoworldparticle::tpcChi2NCl > cfgChi2TpcPart2) || //&& // chi2 cuts + (aod::femtoworldparticle::sign != (int8_t)cfgSignPartTwo); + + /// Histogramming for particle 2 + FemtoWorldParticleHisto trackHistoPartTwo; + FemtoWorldParticleHisto trackHistoPartTwoFailed; + + /// Histogramming for Event + FemtoWorldEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + std::vector vPIDPartOne, vPIDPartTwo; + + /// Correlation part + // ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {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"}; + + ColumnBinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; + + ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis CfgmTBins{"CfgmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfPhiBins{"ConfPhiBins", 15, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 15, "Number of eta bins in deta dphi"}; + Configurable ConfMInvBins{"ConfMInvBins", 1000, "Number of bins in mInv distribution"}; + + FemtoWorldContainer sameEventCont; + FemtoWorldContainer mixedEventCont; + FemtoWorldPairCleaner pairCleaner; + FemtoWorldDetaDphiStar pairCloseRejection; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + // HistogramRegistry qaRegistryFail{"TrackQAFailed", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + SetChargePair(cfgSignPartOne, cfgSignPartTwo); + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry); + trackHistoPartOneFailed.init(&qaRegistry); + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry); + trackHistoPartTwoFailed.init(&qaRegistry); + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins, ConfPhiBins, ConfEtaBins, ConfMInvBins); + sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins, ConfPhiBins, ConfEtaBins, ConfMInvBins); + mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + if (ConfIsCPR) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, 0.01, 0.01, ConfCPRPlotPerRadii); /// \todo add config for Δη and ΔΦ cut values + } + + vPIDPartOne = ConfPIDPartOne; + vPIDPartTwo = ConfPIDPartTwo; + } + + // PID + // Need to be modified + // bool IsPionTPCdEdxNSigma(float mom, float nsigmap) + // { + // if(mom>=0.5 && TMath::Abs(nsigmap)<3.0) + // return true; + + // return false; + // } + + // bool IsPionTOFNSigma(float mom, float nsigmap) + // { + // if(mom>0.5 && TMath::Abs(nsigmap)<3.0) + // return true; + + // return false; + // } + + bool IsPionNSigma(float nsigmap) + { + if (TMath::Abs(nsigmap) < 3.0) + return true; + return 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, ... + void processSameEvent(o2::aod::FemtoWorldCollision& col, + o2::aod::FemtoWorldParticlesMerged& parts) + { + + // Partition Phiparts = (aod::femtoworldparticle::eta < cfgEtaHighPart2) && (aod::femtoworldparticle::eta > cfgEtaLowPart2) // Eta cuts + //; + // auto groupPhiParts = Phiparts->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsOneFailed = partsOneFailed->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsTwoFailed = partsTwoFailed->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + + const auto& magFieldTesla = col.magField(); + const int multCol = col.multV0M(); + eventHisto.fillQA(col); + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multV0M()})); + /// Histogramming same event + for (auto& part : groupPartsOne) { + if ((part.p() > 0.50)) { + + float NSigmaPion = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(part.tpcNSigmaPi()) + TMath::Sq(part.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + + } else if ((part.p() <= 0.50)) { + float NSigmaPion = part.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + } + trackHistoPartOne.fillQA(part); + } + for (auto& part : groupPartsOneFailed) { + + trackHistoPartOneFailed.fillQA(part); + } + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + if ((part.p() > 0.50)) { + + float NSigmaPion = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(part.tpcNSigmaPi()) + TMath::Sq(part.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + + } else if ((part.p() <= 0.50)) { + float NSigmaPion = part.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + } + trackHistoPartTwo.fillQA(part); + } + for (auto& part : groupPartsTwoFailed) { + + trackHistoPartTwoFailed.fillQA(part); + } + } + if ((ChargePair[0] == static_cast(PlusSign) && ChargePair[1] == static_cast(MinusSign)) || (ChargePair[0] == static_cast(MinusSign) && ChargePair[1] == static_cast(PlusSign))) { // Unlike Sign Condition + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if ((p1.p() > 0.50)) { + float NSigmaPion1 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p1.tpcNSigmaPi()) + TMath::Sq(p1.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + + } else if ((p1.p() <= 0.50)) { + float NSigmaPion1 = p1.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + } + if ((p2.p() > 0.50)) { + float NSigmaPion2 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p2.tpcNSigmaPi()) + TMath::Sq(p2.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + + } else if ((p2.p() <= 0.50)) { + float NSigmaPion2 = p2.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + } + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + sameEventCont.setPair(p1, p2, multCol); + } + } else if ((ChargePair[0] == static_cast(PlusSign) && ChargePair[1] == static_cast(PlusSign)) || (ChargePair[0] == static_cast(MinusSign) && ChargePair[1] == static_cast(MinusSign))) { // Like Sign Condition + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo))) { + // for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { + + if ((p1.p() > 0.50)) { + float NSigmaPion1 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p1.tpcNSigmaPi()) + TMath::Sq(p1.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + + } else if ((p1.p() <= 0.50)) { + float NSigmaPion1 = p1.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + } + if ((p2.p() > 0.50)) { + float NSigmaPion2 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p2.tpcNSigmaPi()) + TMath::Sq(p2.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + + } else if ((p2.p() <= 0.50)) { + float NSigmaPion2 = p2.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + } + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol); + } + } + } + + PROCESS_SWITCH(FemtoWorldPionAllPair, 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, ... + void processMixedEvent(o2::aod::FemtoWorldCollisions& cols, + o2::aod::FemtoWorldParticlesMerged& parts) + { + + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), collision1.multV0M()})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex()); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex()); + + 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 (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if ((p1.p() > 0.50)) { + float NSigmaPion1 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p1.tpcNSigmaPi()) + TMath::Sq(p1.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + + } else if ((p1.p() <= 0.50)) { + float NSigmaPion1 = p1.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + } + if ((p2.p() > 0.50)) { + float NSigmaPion2 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p2.tpcNSigmaPi()) + TMath::Sq(p2.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + + } else if ((p2.p() <= 0.50)) { + float NSigmaPion2 = p2.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + } + + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, collision1.multV0M()); + } + } + } + + PROCESS_SWITCH(FemtoWorldPionAllPair, processMixedEvent, "Enable processing mixed events", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPionPairTaskTrackTrack.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPionPairTaskTrackTrack.cxx new file mode 100644 index 00000000000..4959ce90fe0 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPionPairTaskTrackTrack.cxx @@ -0,0 +1,388 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoWorldPionPairTaskTrackTrack.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Deependra Sharma, IITB, deependra.sharma@cern.ch + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" + +#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldParticleHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldEventHisto.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldContainer.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoWorld; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace o2::aod +{ +// using FemtoWorldParticlesMerged = soa::Join; +using FemtoWorldParticlesMerged = aod::FemtoWorldParticles; +using FemtoWorldParticleMerged = FemtoWorldParticlesMerged::iterator; +} // namespace o2::aod + +struct femtoWorldPionPairTaskTrackTrack { + // for filling phi candidates table + // Produces outputCollision; + // Produces outputPhiCan; + // std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + /// Particle selection part + + // Configurables for cuts + // First particle + Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable cfgPtHighPart1{"cfgPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable cfgEtaLowPart1{"cfgEtaLowPart1", -0.8, "Lower limit for Eta for the first particle"}; + Configurable cfgEtaHighPart1{"cfgEtaHighPart1", 0.8, "Higher limit for Eta for the first particle"}; + Configurable cfgDcaXYPart1{"cfgDcaXYPart1", 2.4, "Value for DCA_XY for the first particle"}; + Configurable cfgDcaZPart1{"cfgDcaZPart1", 3.2, "Value for DCA_Z for the first particle"}; + Configurable cfgTpcClPart1{"cfgTpcClPart1", 88, "Number of tpc clasters for the first particle"}; // min number of found TPC clusters + Configurable cfgTpcCrosRoPart1{"cfgTpcCrosRoPart1", 70, "Number of tpc crossed rows for the first particle"}; // min number of crossed rows + Configurable cfgChi2TpcPart1{"cfgChi2TpcPart1", 4.0, "Chi2 / cluster for the TPC track segment for the first particle"}; + Configurable cfgChi2ItsPart1{"cfgChi2ItsPart1", 36.0, "Chi2 / cluster for the ITS track segment for the first particle"}; + // Second particle + Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable cfgPtHighPart2{"cfgPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable cfgEtaLowPart2{"cfgEtaLowPart2", -0.8, "Lower limit for Eta for the second particle"}; + Configurable cfgEtaHighPart2{"cfgEtaHighPart2", 0.8, "Higher limit for Eta for the second particle"}; + Configurable cfgDcaXYPart2{"cfgDcaXYPart2", 2.4, "Value for DCA_XY for the second particle"}; + Configurable cfgDcaZPart2{"cfgDcaZPart2", 3.2, "Value for DCA_Z for the second particle"}; + Configurable cfgTpcClPart2{"cfgTpcClPart2", 88, "Number of tpc clasters for the second particle"}; // min number of found TPC clusters + Configurable cfgTpcCrosRoPart2{"cfgTpcCrosRoPart2", 70, "Number of tpc crossed rows for the second particle"}; // min number of crossed rows + Configurable cfgChi2TpcPart2{"cfgChi2TpcPart2", 4.0, "Chi2 / cluster for the TPC track segment for the second particle"}; + Configurable cfgChi2ItsPart2{"cfgChi2ItsPart2", 36.0, "Chi2 / cluster for the ITS track segment for the second particle"}; + + /// Particle 1 Pi+ + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 - PDG code"}; + Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from json file"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + + /// Partition for particle 1 + Partition partsOne = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) // particle type cut + && (aod::femtoworldparticle::pt < cfgPtHighPart1) && (aod::femtoworldparticle::pt > cfgPtLowPart1) // simple pT cuts + && (aod::femtoworldparticle::eta < cfgEtaHighPart1) && (aod::femtoworldparticle::eta > cfgEtaLowPart1) // Eta cuts + && (o2::aod::track::dcaXY < cfgDcaXYPart1) && (o2::aod::track::dcaZ < cfgDcaZPart1) // DCA cuts for XY and Z + && (aod::femtoworldparticle::tpcNClsFound > (uint8_t)cfgTpcClPart1) // Number of found TPC clusters + && (aod::femtoworldparticle::tpcNClsCrossedRows > (uint8_t)cfgTpcCrosRoPart1) // Crossed rows TPC + && (aod::femtoworldparticle::itsChi2NCl < cfgChi2ItsPart1) && (aod::femtoworldparticle::tpcChi2NCl < cfgChi2TpcPart1) //&& // chi2 cuts + && (aod::femtoworldparticle::sign > int8_t(0)) // Sign (K+) + // todo: globaltrack cut + ; + + Partition partsOneFailed = //~(aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) || // particle type cut + ((aod::femtoworldparticle::pt > cfgPtHighPart1) || (aod::femtoworldparticle::pt < cfgPtLowPart1)) || // pT cuts + ((aod::femtoworldparticle::eta > cfgEtaHighPart1) || (aod::femtoworldparticle::eta < cfgEtaLowPart1)) || // Eta cuts + (o2::aod::track::dcaXY > cfgDcaXYPart1) || (o2::aod::track::dcaZ > cfgDcaZPart1) || // DCA cuts for XY and Z + (aod::femtoworldparticle::tpcNClsFound < (uint8_t)cfgTpcClPart1) || // Number of found TPC clusters + (aod::femtoworldparticle::tpcNClsCrossedRows < (uint8_t)cfgTpcCrosRoPart1) || // Crossed rows TPC + (aod::femtoworldparticle::itsChi2NCl > cfgChi2ItsPart1) || (aod::femtoworldparticle::tpcChi2NCl > cfgChi2TpcPart1) || //&& // chi2 cuts + (aod::femtoworldparticle::sign < int8_t(0)); + /// Histogramming for particle 1 + FemtoWorldParticleHisto trackHistoPartOne; + FemtoWorldParticleHisto trackHistoPartOneFailed; + + /// Particle 2 Pi- + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 211, "Particle 2 - PDG code"}; + Configurable> ConfPIDPartTwo{"ConfPIDPartTwo", std::vector{2}, "Particle 2 - Read from json file"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + /// Partition for particle 2 + Partition partsTwo = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) // particle type cut + && (aod::femtoworldparticle::pt < cfgPtHighPart2) && (aod::femtoworldparticle::pt > cfgPtLowPart2) // pT cuts + && (aod::femtoworldparticle::eta < cfgEtaHighPart2) && (aod::femtoworldparticle::eta > cfgEtaLowPart2) // Eta cuts + && (o2::aod::track::dcaXY < cfgDcaXYPart2) && (o2::aod::track::dcaZ < cfgDcaZPart2) // DCA cuts for XY and Z + && (aod::femtoworldparticle::tpcNClsFound > (uint8_t)cfgTpcClPart2) // Number of found TPC clusters + && (aod::femtoworldparticle::tpcNClsCrossedRows > (uint8_t)cfgTpcCrosRoPart2) // Crossed rows TPC + && (aod::femtoworldparticle::itsChi2NCl < cfgChi2ItsPart2) && (aod::femtoworldparticle::tpcChi2NCl < cfgChi2TpcPart2) // // chi2 cuts + && (aod::femtoworldparticle::sign < int8_t(0)) // Sign (K-) + // todo: globaltrack cut + ; + Partition partsTwoFailed = //(aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kTrack)) || // particle type cut + ((aod::femtoworldparticle::pt > cfgPtHighPart2) || (aod::femtoworldparticle::pt < cfgPtLowPart2)) || // pT cuts + ((aod::femtoworldparticle::eta > cfgEtaHighPart2) || (aod::femtoworldparticle::eta < cfgEtaLowPart2)) || // Eta cuts + (o2::aod::track::dcaXY > cfgDcaXYPart2) || (o2::aod::track::dcaZ > cfgDcaZPart2) || // DCA cuts for XY and Z + (aod::femtoworldparticle::tpcNClsFound < (uint8_t)cfgTpcClPart2) || // Number of found TPC clusters + (aod::femtoworldparticle::tpcNClsCrossedRows < (uint8_t)cfgTpcCrosRoPart2) || // Crossed rows TPC + (aod::femtoworldparticle::itsChi2NCl > cfgChi2ItsPart2) || (aod::femtoworldparticle::tpcChi2NCl > cfgChi2TpcPart2) //&& // chi2 cuts + ; + /// Histogramming for particle 2 + FemtoWorldParticleHisto trackHistoPartTwo; + FemtoWorldParticleHisto trackHistoPartTwoFailed; + + /// Histogramming for Event + FemtoWorldEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + std::vector vPIDPartOne, vPIDPartTwo; + + /// Correlation part + // ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {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"}; + + ColumnBinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; + + ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis CfgmTBins{"CfgmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfPhiBins{"ConfPhiBins", 15, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 15, "Number of eta bins in deta dphi"}; + Configurable ConfMInvBins{"ConfMInvBins", 1000, "Number of bins in mInv distribution"}; + + FemtoWorldContainer sameEventCont; + FemtoWorldContainer mixedEventCont; + FemtoWorldPairCleaner pairCleaner; + FemtoWorldDetaDphiStar pairCloseRejection; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + // HistogramRegistry qaRegistryFail{"TrackQAFailed", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry); + trackHistoPartOneFailed.init(&qaRegistry); + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry); + trackHistoPartTwoFailed.init(&qaRegistry); + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins, ConfPhiBins, ConfEtaBins, ConfMInvBins); + sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins, ConfPhiBins, ConfEtaBins, ConfMInvBins); + mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + if (ConfIsCPR) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, 0.01, 0.01, ConfCPRPlotPerRadii); /// \todo add config for Δη and ΔΦ cut values + } + + vPIDPartOne = ConfPIDPartOne; + vPIDPartTwo = ConfPIDPartTwo; + } + + // PID + // Need to be modified + // bool IsPionTPCdEdxNSigma(float mom, float nsigmap) + // { + // if(mom>=0.5 && TMath::Abs(nsigmap)<3.0) + // return true; + + // return false; + // } + + // bool IsPionTOFNSigma(float mom, float nsigmap) + // { + // if(mom>0.5 && TMath::Abs(nsigmap)<3.0) + // return true; + + // return false; + // } + + bool IsPionNSigma(float nsigmap) + { + if (TMath::Abs(nsigmap) < 3.0) + return true; + return 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, ... + void processSameEvent(o2::aod::FemtoWorldCollision& col, + o2::aod::FemtoWorldParticlesMerged& parts) + { + // Partition Phiparts = (aod::femtoworldparticle::eta < cfgEtaHighPart2) && (aod::femtoworldparticle::eta > cfgEtaLowPart2) // Eta cuts + //; + // auto groupPhiParts = Phiparts->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsOneFailed = partsOneFailed->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + auto groupPartsTwoFailed = partsTwoFailed->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex()); + + const auto& magFieldTesla = col.magField(); + const int multCol = col.multV0M(); + eventHisto.fillQA(col); + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multV0M()})); + /// Histogramming same event + for (auto& part : groupPartsOne) { + if ((part.p() > 0.50)) { + + float NSigmaPion = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(part.tpcNSigmaPi()) + TMath::Sq(part.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + + } else if ((part.p() <= 0.50)) { + float NSigmaPion = part.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + } + trackHistoPartOne.fillQA(part); + } + for (auto& part : groupPartsOneFailed) { + + trackHistoPartOneFailed.fillQA(part); + } + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + if ((part.p() > 0.50)) { + + float NSigmaPion = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(part.tpcNSigmaPi()) + TMath::Sq(part.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + + } else if ((part.p() <= 0.50)) { + float NSigmaPion = part.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion)) { + continue; + } + } + trackHistoPartTwo.fillQA(part); + } + for (auto& part : groupPartsTwoFailed) { + + trackHistoPartTwoFailed.fillQA(part); + } + } + /// Now build the combinations + for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { + + if ((p1.p() > 0.50)) { + float NSigmaPion1 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p1.tpcNSigmaPi()) + TMath::Sq(p1.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + + } else if ((p1.p() <= 0.50)) { + float NSigmaPion1 = p1.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + } + if ((p2.p() > 0.50)) { + float NSigmaPion2 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p2.tpcNSigmaPi()) + TMath::Sq(p2.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + + } else if ((p2.p() <= 0.50)) { + float NSigmaPion2 = p2.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + } + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol); + } + } + + PROCESS_SWITCH(femtoWorldPionPairTaskTrackTrack, 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, ... + void processMixedEvent(o2::aod::FemtoWorldCollisions& cols, + o2::aod::FemtoWorldParticlesMerged& parts) + { + + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), collision1.multV0M()})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex()); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex()); + + 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 (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if ((p1.p() > 0.50)) { + float NSigmaPion1 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p1.tpcNSigmaPi()) + TMath::Sq(p1.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + + } else if ((p1.p() <= 0.50)) { + float NSigmaPion1 = p1.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion1)) { + continue; + } + } + if ((p2.p() > 0.50)) { + float NSigmaPion2 = TMath::Sqrt(2.0) * TMath::Sqrt(TMath::Sq(p2.tpcNSigmaPi()) + TMath::Sq(p2.tofNSigmaPi())); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + + } else if ((p2.p() <= 0.50)) { + float NSigmaPion2 = p2.tpcNSigmaPi(); + if (!IsPionNSigma(NSigmaPion2)) { + continue; + } + } + + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, collision1.multV0M()); + } + } + } + + PROCESS_SWITCH(femtoWorldPionPairTaskTrackTrack, processMixedEvent, "Enable processing mixed events", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +}