diff --git a/PWGCF/DataModel/FemtoDerived.h b/PWGCF/DataModel/FemtoDerived.h index 3be2baadc37..af7f2ac6630 100644 --- a/PWGCF/DataModel/FemtoDerived.h +++ b/PWGCF/DataModel/FemtoDerived.h @@ -8,22 +8,24 @@ // 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. - #ifndef PWGCF_DATAMODEL_FEMTODERIVED_H_ #define PWGCF_DATAMODEL_FEMTODERIVED_H_ -#include -#include "Framework/ASoA.h" -#include "MathUtils/Utils.h" -#include "Framework/DataTypes.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" + #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/DataTypes.h" #include "Framework/Expressions.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" +#include "MathUtils/Utils.h" + +#include namespace o2::aod { @@ -88,17 +90,23 @@ DECLARE_SOA_TABLE_STAGED(FDMCCollLabels, "FDMCCollLabel", mcfdcolllabel::FDMCCol /// FemtoDreamTrack namespace femtodreamparticle { -/// Distinuishes the different particle types +/// Distinguishes the different particle types enum ParticleType { - kTrack, //! Track - kV0, //! V0 - kV0Child, //! Child track of a V0 - kCascade, //! Cascade + kTrack, //! Track + kV0, //! V0 + kReso, //! Resonances (phi) + kResoChild, // Child track of a Resonance + kV0Child, //! Child track of a V0 + kCascade, //! Cascade kCascadeV0, kCascadeV0Child, - kCascadeBachelor, //! Bachelor track of a cascade - kCharmHadron, //! Bachelor track of a cascade - kNParticleTypes //! Number of particle types + kCascadeBachelor, //! Bachelor track of a cascade + kCharmHadron, //! Bachelor track of a cascade + kPhiPosdaughTPC_NegdaughTPC, /// cases for Phi-daughters for TPC or TOF combinations + kPhiPosdaughTPC_NegdaughTOF, + kPhiPosdaughTOF_NegdaughTPC, + kPhiPosdaughTOF_NegdaughTOF, + kNParticleTypes //! Number of particle types }; enum MomentumType { @@ -107,8 +115,10 @@ enum MomentumType { kPtpc //! momentum at the inner wall of the TPC (useful for PID plots) }; -static constexpr std::string_view ParticleTypeName[kNParticleTypes] = {"Tracks", "V0", "V0Child", "Cascade", "CascadeV0", "CascadeV0Child", "CascadeBachelor", "CharmHadron"}; //! Naming of the different particle types -static constexpr std::string_view TempFitVarName[kNParticleTypes] = {"/hDCAxy", "/hCPA", "/hDCAxy", "/hCPA", "/hCPA", "/hDCAxy", "/hDCAxy", "/hCPA"}; +static constexpr std::string_view ParticleTypeName[kNParticleTypes] = {"Track", "V0", "Reso", "ResoChild", "V0Child", "PhiPosdaughTPC_NegdaughTPC", "PhiPosdaughTPC_NegdaughTOF", "PhiPosdaughTOF_NegdaughTPC", "PhiPosdaughTOF_NegdaughTOF", "Cascade", "CascadeV0", "CascadeV0Child", "CascadeBachelor", "CharmHadron"}; //! Naming of the different particle types +// static constexpr std::string_view TempFitVarName[kNParticleTypes] = {"/hDCAxy", "/hCPA", "/hDCAxy", "/hCPA", "/hCPA", "/hDCAxy", "/hDCAxy", "/hCPA"}; + +static constexpr std::string_view TempFitVarName[kNParticleTypes] = {"/hDCAxy", "/hCPA", "/hDCAxy", "/hDCAxy", "/hCPA", "/hDCAxy", "/hDCAxy", "/hDCAxy", "/hDCAxy", "/hCPA", "/hCPA", "/hDCAxy", "/hDCAxy", "/hCPA"}; // change later!! check for DCAXY for RESO!! using cutContainerType = uint32_t; //! Definition of the data type for the bit-wise container for the different selection criteria diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index 3d95fc08311..4f9cc467c69 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// Copyright 2019-2022 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. // @@ -19,19 +19,22 @@ #ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMCONTAINER_H_ #define PWGCF_FEMTODREAM_CORE_FEMTODREAMCONTAINER_H_ -#include -#include -#include - -#include "Framework/HistogramRegistry.h" +#include "PWGCF/DataModel/FemtoDerived.h" #include "PWGCF/FemtoDream/Core/femtoDreamMath.h" #include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" -#include "PWGCF/DataModel/FemtoDerived.h" + +#include "Framework/HistogramRegistry.h" #include "Math/Vector4D.h" #include "TMath.h" +#include + +#include +#include + using namespace o2::framework; +using namespace o2::aod; // maybe not needed namespace o2::analysis::femtoDream { @@ -99,6 +102,7 @@ class FemtoDreamContainer } if (extendedplots) { mHistogramRegistry->add((folderName + "/relPairkstarmTPtPart1PtPart2MultPercentile").c_str(), ("; :" + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2}); #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c}); Multiplicity Percentile (%)").c_str(), kTHnSparseF, {femtoObsAxis, mTAxis4D, pTAxis, pTAxis, multPercentileAxis4D}); + mHistogramRegistry->add((folderName + "/pT1pT2kstarinvMassPart1invMassPart2").c_str(), ("#it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c}), " + femtoObs + ";#it{m} (GeV/#it{c}^{2}); #it{m} (GeV/#it{c}^{2})").c_str(), kTHnSparseF, {pTAxis, pTAxis, femtoObsAxis, mP2Axis, mP2Axis}); } } @@ -230,6 +234,10 @@ class FemtoDreamContainer } if (extendedplots) { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTPtPart1PtPart2MultPercentile"), femtoObs, mT, part1.pt(), part2.pt(), multPercentile); + + if constexpr (requires { part1.mLambda(); part2.mLambda(); }) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/pT1pT2kstarinvMassPart1invMassPart2"), part1.pt(), part2.pt(), femtoObs, part1.mLambda(), part2.mLambda()); + } } } @@ -263,7 +271,7 @@ class FemtoDreamContainer /// \param part1 Particle one /// \param part2 Particle two /// \param mult Multiplicity of the event - template + template // depends on the part type i pass ?--> add bool or compile time flag void setPair(T1 const& part1, T2 const& part2, const int mult, const float multPercentile, bool use4dplots, bool extendedplots, bool smearingByOrigin = false) { float femtoObs, femtoObsMC; diff --git a/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h b/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h index 7dadb08df78..c37db44c116 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h +++ b/PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// Copyright 2019-2022 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. // @@ -154,6 +154,25 @@ class FemtoDreamDetaDphiStar } } } + if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kV0 && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kReso) { + + for (int i = 0; i < 4; i++) { + std::string dirName = static_cast(dirNames[4]); + histdetadpi[i][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][i]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][1] = mHistogramRegistry->add((dirName + static_cast(histNames[1][i]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][2] = mHistogramRegistry->add((dirName + "at_PV_" + std::to_string(i) + "_before" + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpi[i][3] = mHistogramRegistry->add((dirName + "at_PV_" + std::to_string(i) + "_after" + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + if (plotForEveryRadii) { + for (int j = 0; j < 9; j++) { + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(histNamesRadii[i][j]) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + } + } + if (fillQA) { + histdetadpi_eta[i] = mHistogramRegistry->add((dirName + "dEtadPhi_Eta_" + std::to_string(i) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}; #eta_{1}; #eta_{2}", kTHnSparseF, {{100, -0.15, 0.15}, {100, -0.15, 0.15}, {100, -0.8, 0.8}, {100, -0.8, 0.8}}); + histdetadpi_phi[i] = mHistogramRegistry->add((dirName + "dEtadPhi_Phi_" + std::to_string(i) + static_cast(histNameSEorME[meORse])).c_str(), "; #Delta #eta; #Delta #phi^{*}; #phi_{1}; #phi_{2}", kTHnSparseF, {{100, -0.15, 0.15}, {100, -0.15, 0.15}, {100, 0, 6.28}, {100, 0, 6.28}}); + } + } + } } /// Check if pair is close or not template @@ -236,6 +255,88 @@ class FemtoDreamDetaDphiStar return false; } + } else if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kV0 && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kReso) { + /// V0-Reso combination + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtodreamparticle::ParticleType::kV0 || (part2.partType() != o2::aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTOF && + part2.partType() != o2::aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTPC && + part2.partType() != o2::aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTOF && + part2.partType() != o2::aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTPC)) { + LOG(fatal) << "FemtoDreamDetaDphiStar: passed arguments don't agree with FemtoDreamDetaDphiStar instantiation! Please provide kV0, kPhiPosdaughTOF_NegdaughTOF, kPhiPosdaughTOF_NegdaughTPC, kPhiPosdaughTPC_NegdaughTOF, kPhiPosdaughTPC_NegdaughTPC candidates."; + return false; + } + + bool pass = false; + int nhist = 0; + for (int i = 0; i < 2; i++) { + int indexOfDaughterPart1, indexOfDaughterPart2; + for (int j = 0; j < 2; j++) { + if (isMixedEventLambda) { + indexOfDaughterPart1 = part1.globalIndex() - 2 + i; + indexOfDaughterPart2 = part2.globalIndex() - 2 + j; + } else { + indexOfDaughterPart1 = part1.index() - 2 + i; + indexOfDaughterPart2 = part2.index() - 2 + j; + } + + auto daughterPart1 = particles.begin() + indexOfDaughterPart1; + auto daughterPart2 = particles.begin() + indexOfDaughterPart2; + auto deta = daughterPart1.eta() - daughterPart2.eta(); + auto dphi_AT_PV = daughterPart1.phi() - daughterPart2.phi(); + auto dphi_AT_SpecificRadii = PhiAtSpecificRadiiTPC(daughterPart1, radiiTPC) - PhiAtSpecificRadiiTPC(daughterPart2, radiiTPC); + bool sameCharge = false; + auto dphiAvg = AveragePhiStar(*daughterPart1, *daughterPart2, nhist, &sameCharge); + if (Q3 == 999) { + histdetadpi[nhist][0]->Fill(deta, dphiAvg); + histdetadpi[nhist][2]->Fill(deta, dphi_AT_PV); + if (fillQA) { + histdetadpi_eta[nhist]->Fill(deta, dphiAvg, daughterPart1.eta(), daughterPart2.eta()); + histdetadpi_phi[nhist]->Fill(deta, dphiAvg, daughterPart1.phi(), daughterPart2.phi()); + } + } + if (sameCharge) { + if (atWhichRadiiToSelect == 1) { + if (pow(dphiAvg, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + pass = true; + } else { + if (Q3 == 999) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } else if (Q3 < upperQ3LimitForPlotting) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } + } + } else if (atWhichRadiiToSelect == 0) { + if (pow(dphi_AT_PV, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + pass = true; + } else { + if (Q3 == 999) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } else if (Q3 < upperQ3LimitForPlotting) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } + } + } else if (atWhichRadiiToSelect == 2) { + if (pow(dphi_AT_SpecificRadii, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + pass = true; + } else { + if (Q3 == 999) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } else if (Q3 < upperQ3LimitForPlotting) { + histdetadpi[nhist][1]->Fill(deta, dphiAvg); + histdetadpi[nhist][3]->Fill(deta, dphi_AT_PV); + } + } + } + } + nhist += 1; + } + } + return pass; } else if constexpr (mPartOneType == o2::aod::femtodreamparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtodreamparticle::ParticleType::kV0) { /// Track-V0 combination // check if provided particles are in agreement with the class instantiation @@ -583,7 +684,7 @@ class FemtoDreamDetaDphiStar private: HistogramRegistry* mHistogramRegistry = nullptr; ///< For main output HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output - static constexpr std::string_view dirNames[4] = {"kTrack_kTrack/", "kTrack_kV0/", "kTrack_kCharmHadron/", "kTrack_kCascade/"}; + static constexpr std::string_view dirNames[5] = {"kTrack_kTrack/", "kTrack_kV0/", "kTrack_kCharmHadron/", "kTrack_kCascade/", "kV0_kReso/"}; static constexpr std::string_view histNameSEorME[3] = {"_SEandME", "_SE", "_ME"}; diff --git a/PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h b/PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h index d01ce564f66..0c2155cae7c 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// Copyright 2019-2022 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. // @@ -16,15 +16,16 @@ #ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMOBJECTSELECTION_H_ #define PWGCF_FEMTODREAM_CORE_FEMTODREAMOBJECTSELECTION_H_ +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" + +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + #include #include #include -#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" -#include "ReconstructionDataFormats/PID.h" -#include "Framework/HistogramRegistry.h" -#include "PWGCF/DataModel/FemtoDerived.h" - using namespace o2; using namespace o2::framework; @@ -59,6 +60,14 @@ class FemtoDreamObjectSelection } } + /// assigns value from configurbale to protected class member + /// \param selVals o2 configurable containing the values employed for the selection + template + void assign(V& selVals) + { + assignedValue = static_cast(selVals); + } + /// Pass the Configurable of selection values in the analysis task to the selection class /// \tparam T Type of the configurable passed to the function /// \param selVals o2 configurable containing the values employed for the selection @@ -190,6 +199,7 @@ class FemtoDreamObjectSelection HistogramRegistry* mHistogramRegistry; ///< For Analysis QA output HistogramRegistry* mQAHistogramRegistry; ///< For QA output std::vector> mSelections; ///< Vector containing all selections + selValDataType assignedValue; }; } // namespace femtoDream diff --git a/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h b/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h index 4148e8b3efc..147c1675dc1 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h +++ b/PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// Copyright 2019-2022 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. // @@ -18,11 +18,14 @@ #ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMPARTICLEHISTO_H_ #define PWGCF_FEMTODREAM_CORE_FEMTODREAMPARTICLEHISTO_H_ -#include -#include #include "PWGCF/DataModel/FemtoDerived.h" -#include "Framework/HistogramRegistry.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/HistogramRegistry.h" + +#include + +#include using namespace o2::framework; @@ -72,6 +75,15 @@ class FemtoDreamParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassCascade").c_str(), "; M_{Cascade}; Entries", kTH1F, {InvMassAxis}); mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassCascade").c_str(), "; p_{T} (GeV/#it{c{}); M_{Cascade}", kTH2F, {pTAxis, InvMassAxis}); } + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kReso) { + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassPhi").c_str(), "; M_{#Phi}; Entries", kTH1F, {InvMassAxis}); // added for Phi !! + mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassPhi").c_str(), "; p_{T} (GeV/#it{c{}); M_{#Phi}", kTH2F, {pTAxis, InvMassAxis}); + } + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kResoChild) { + + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassPhi").c_str(), "; M_{#Phi}; Entries", kTH1F, {InvMassAxis}); // added for Phi !! + mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassPhi").c_str(), "; p_{T} (GeV/#it{c{}); M_{#Phi}", kTH2F, {pTAxis, InvMassAxis}); + } } // comment @@ -149,6 +161,30 @@ class FemtoDreamParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hCascDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassCompetingCascade").c_str(), "; M_{Competing Cascade}; Entries", kTH1F, {InvMassCompetingAxis}); mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassCompetingCascade").c_str(), "; p_{T} (GeV/#it{c{}); M_{Competing Cascade}", kTH2F, {pTAxis, InvMassCompetingAxis}); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kResoChild) { + mHistogramRegistry->add((folderName + folderSuffix + "/hCharge").c_str(), "; Charge; Entries", kTH1F, {{5, -2.5, 2.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfindable").c_str(), "; TPC findable clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfound").c_str(), "; TPC found clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCcrossedOverFindable").c_str(), "; TPC ratio findable over crossed; Entries", kTH1F, {{100, 0.5, 1.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCcrossedRows").c_str(), "; TPC crossed rows; Entries", kTH1F, {{163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCshared").c_str(), "; TPC shared clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCsharedOverFound").c_str(), "; TPC ratio shared over found; Entries", kTH1F, {{1000, 0, 1}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfindableVsCrossed").c_str(), ";TPC findable clusters ; TPC crossed rows;", kTH2F, {{163, -0.5, 162.5}, {163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfoundVsShared").c_str(), ";TPC found clusters ; TPC shared clusters;", kTH2F, {{163, -0.5, 162.5}, {163, -0.5, 162.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hITSclusters").c_str(), "; ITS clusters; Entries", kTH1F, {{10, -0.5, 9.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hITSclustersIB").c_str(), "; ITS clusters in IB; Entries", kTH1F, {{10, -0.5, 9.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAz").c_str(), "; #it{p} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {pTAxis, dcazAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCA").c_str(), "; #it{p} (GeV/#it{c}); DCA (cm)", kTH2F, {pTAxis, {300, 0., 1.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCdEdX").c_str(), "; #it{p} (GeV/#it{c}); TPC Signal", kTH2F, {{100, 0, 10}, {1000, 0, 1000}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "n#sigma_{TPC}^{#pi}", kTH2F, {pTAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "n#sigma_{TPC}^{K}", kTH2F, {pTAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "n#sigma_{TOF}^{#pi}", kTH2F, {pTAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "n#sigma_{TOF}^{K}", kTH2F, {pTAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "n#sigma_{comb}^{#pi}", kTH2F, {pTAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "n#sigma_{comb}^{K}", kTH2F, {pTAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/ITSSignal").c_str(), "x", kTH2F, {pTAxis, NsigmaITSAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaITS_pi").c_str(), "n#sigma_{ITS}^{#pi}", kTH2F, {pTAxis, NsigmaITSAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaITS_K").c_str(), "n#sigma_{ITS}^{K}", kTH2F, {pTAxis, NsigmaITSAxis}); } } @@ -256,6 +292,9 @@ class FemtoDreamParticleHisto if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack || mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascadeV0Child || mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascadeBachelor) { /// Track histograms tempFitVarAxisTitle = "DCA_{xy} (cm)"; + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kResoChild || mParticleType == o2::aod::femtodreamparticle::ParticleType::kReso) { // mParticleType == o2::aod::femtodreamparticle::ParticleType::kReso || Phi has no TempFitVar!! + /// Reso histograms added!! + tempFitVarAxisTitle = "DCA_{xy} (cm)"; } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0 || mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascadeV0) { /// V0 histograms tempFitVarAxisTitle = "cos#alpha"; @@ -323,6 +362,14 @@ class FemtoDreamParticleHisto // mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassCascade"), part.mLambda()); // mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassCascade"), part.pt(), part.mLambda()); } + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kReso) { + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassPhi"), part.mLambda()); // currently no MC for Phi!! + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassPhi"), part.pt(), part.mLambda()); // getter from FDPArticles now!! + } + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kResoChild) { + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassPhi"), part.mLambda()); // currently no MC for Phi!! + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassPhi"), part.pt(), part.mLambda()); // getter from FDPArticles now!! + } } template @@ -460,9 +507,32 @@ class FemtoDreamParticleHisto mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hCascDecayVtxZ"), part.cascDecayVtxZ()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassCompetingCascade"), part.mOmega()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassCompetingCascade"), part.pt(), part.mOmega()); + } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kResoChild) { + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hCharge"), part.sign()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCfindable"), part.tpcNClsFindable()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCfound"), part.tpcNClsFound()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCcrossedOverFindable"), part.tpcCrossedRowsOverFindableCls()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCcrossedRows"), part.tpcNClsCrossedRows()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCfindableVsCrossed"), part.tpcNClsFindable(), part.tpcNClsCrossedRows()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCshared"), part.tpcNClsShared()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCsharedOverFound"), static_cast(part.tpcNClsShared()) / static_cast(part.tpcNClsFound())); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCfoundVsShared"), part.tpcNClsFound(), part.tpcNClsShared()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hITSclusters"), part.itsNCls()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hITSclustersIB"), part.itsNClsInnerBarrel()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDCAz"), momentum, part.dcaZ()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDCA"), momentum, std::sqrt(std::pow(part.dcaXY(), 2.) + std::pow(part.dcaZ(), 2.))); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTPCdEdX"), momentum, part.tpcSignal()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_pi"), momentum, part.tpcNSigmaPi()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_K"), momentum, part.tpcNSigmaKa()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_pi"), momentum, part.tofNSigmaPi()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_K"), momentum, part.tofNSigmaKa()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_pi"), momentum, std::sqrt(part.tpcNSigmaPi() * part.tpcNSigmaPi() + part.tofNSigmaPi() * part.tofNSigmaPi())); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_K"), momentum, std::sqrt(part.tpcNSigmaKa() * part.tpcNSigmaKa() + part.tofNSigmaKa() * part.tofNSigmaKa())); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/ITSSignal"), momentum, part.itsSignal()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaITS_pi"), momentum, part.itsNSigmaPi()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaITS_K"), momentum, part.itsNSigmaKa()); } } - /// Filling specialized histograms for Monte Carlo truth /// internal function called by init only in case of Monte Carlo truth /// \tparam T Data type of the particle diff --git a/PWGCF/FemtoDream/Core/femtoDreamResoSelection.h b/PWGCF/FemtoDream/Core/femtoDreamResoSelection.h new file mode 100644 index 00000000000..fc3454c829e --- /dev/null +++ b/PWGCF/FemtoDream/Core/femtoDreamResoSelection.h @@ -0,0 +1,376 @@ +// 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 FemtoDreamResoSelection.h +/// \brief Definition of the FemtoDreamResoSelection +/// \author Valentina Mantovani Sarti, TU München valentina.mantovani-sarti@tum.de +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch + +#ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTION_H_ +#define PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTION_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + +#include "Math/Vector4D.h" +#include "TMath.h" + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +/// std::ofstream wtftest("logResoHeader.txt", std::ios::app); + +namespace o2::analysis::femtoDream +{ +namespace femtoDreamResoSelection +{ +enum ResoSel { + kResoSign +}; +/// If you add a new selection, adjust kNresoSelection + +enum Daughtertype { + kPosdaugh, + kNegdaugh +}; + +} // namespace femtoDreamResoSelection + +class FemtoDreamResoSelection + : public FemtoDreamObjectSelection +{ + + public: + FemtoDreamResoSelection() /// initialization currently kind of random change this!!! + : mDaughPTPCThr(99.f) + { + } + + virtual ~FemtoDreamResoSelection() = default; + + template + uint32_t getType(V const& track1, V const& track2); + + template + size_t numBitsUsed(V const& origvalue); + + template + void init(HistogramRegistry* QAregistry, HistogramRegistry* Registry); + + template + void fillQA(T const& track1, T const& track2); + + template + void setDaughterCuts(femtoDreamResoSelection::Daughtertype child, T selVal, + V selVar, femtoDreamSelection::SelectionType selType); + + template + void setDaughterPIDSpecies(T const& daugh, V& pids); + + template + bool DaughterSelection1(V const& track1, bool UseThreshold); + + template + bool DaughterSelection2(V const& track2, bool UseThreshold); + + template + std::array getCutContainer(V const& track1, V const& track2, float sign); + + void updateMembersMinimal() + { + mDaughPTPCThr = assignedValue; + }; + + void setDaughternSigmaPIDOffset(femtoDreamResoSelection::Daughtertype daugh, float offsetTPC, float offsetTOF) + { + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } else if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } + }; + + float getMass(o2::track::PID::ID pid) + { + switch (pid) { + case (o2::track::PID::Kaon): + return o2::constants::physics::MassKPlus; + case (o2::track::PID::Pion): + return o2::constants::physics::MassPiPlus; + default: + LOG(fatal) << "PID not implemented in femtoDreamResoSelection.getMass"; + return 0.; + } + } + + /// @brief checks if the reso-particle is either particle or antiparticle (dependent on isParticle) + /// @param PID vector of PIDs of daughter particles + /// @param isParticle true: function checks if Reso is particle, false: function checks if Reso is Antiparticle + template + bool isResoOfKind(T const& PosTrack, T const& NegTrack, std::vector const& PID, bool isParticle); + + /// The following functions might not be needed, as right now there is only one ResoSel (sign). + /// However all the other selections are implemented this way (also in the CutCulator). + /// So for now this is implemented analogous (migth also be beneficial if further ResoSels want to be implemented). + + /// Helper function to obtain the name of a given selection criterion for consistent naming of the configurables + /// \param iSel Reso selection variable to be examined + /// \param prefix Additional prefix for the name of the configurable + /// \param suffix Additional suffix for the name of the configurable + static std::string getSelectionName(femtoDreamResoSelection::ResoSel iSel, + std::string_view prefix = "", + std::string_view suffix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionNames[iSel]); + outString += suffix; + return outString; + } + + /// Helper function to obtain the index of a given selection variable for consistent naming of the configurables + /// \param obs Reso selection variable (together with prefix) got from file + /// \param prefix Additional prefix for the output of the configurable + static int findSelectionIndex(const std::string_view& obs, + std::string_view prefix = "") + { + for (int index = 0; index < kNresoSelection; index++) { + std::string comp = static_cast(prefix) + + static_cast(mSelectionNames[index]); + std::string_view cmp{comp}; + if (obs.compare(cmp) == 0) + return index; + } + LOGF(info, "Variable %s not found", obs); + return -1; + } + + /// Helper function to obtain the type of a given selection variable for consistent naming of the configurables + /// \param iSel Reso selection variable whose type is returned + static femtoDreamSelection::SelectionType + getSelectionType(femtoDreamResoSelection::ResoSel iSel) + { + return mSelectionTypes[iSel]; + } + + /// for consistent description of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the output of the configurable + static std::string getSelectionHelper(femtoDreamResoSelection::ResoSel iSel, + std::string_view prefix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionHelper[iSel]); + return outString; + } + + private: + float mDaughPTPCThr; + + FemtoDreamTrackSelection PosDaughTrack; + FemtoDreamTrackSelection NegDaughTrack; + + static constexpr int kNresoSelection = 1; + + static constexpr std::string_view mSelectionNames[kNresoSelection] = {"Sign"}; + + static constexpr femtoDreamSelection::SelectionType mSelectionTypes[kNresoSelection]{ + femtoDreamSelection::kEqual}; + + static constexpr std::string_view mSelectionHelper[kNresoSelection] = { + "+1 for Reso, -1 for AntiReso"}; + +}; // namespace femtoDream + +template +uint32_t FemtoDreamResoSelection::getType(V const& track1, V const& track2) +{ + if (track1.pt() <= mDaughPTPCThr && track2.pt() <= mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTPC_NegdaughTPC; + } + if (track1.pt() <= mDaughPTPCThr && track2.pt() > mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTPC_NegdaughTOF; + } + if (track1.pt() > mDaughPTPCThr && track2.pt() <= mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTOF_NegdaughTPC; + } + if (track1.pt() > mDaughPTPCThr && track2.pt() > mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTOF_NegdaughTOF; + } + return 255; // as error filler +} + +template +size_t FemtoDreamResoSelection::numBitsUsed(V const& origvalue) +{ + size_t bits = 0; + auto value = origvalue; + while (value != 0) { + ++bits; + value >>= 1; + } + return bits; +} + +template +void FemtoDreamResoSelection::init(HistogramRegistry* QAregistry, HistogramRegistry* Registry) +{ + if (QAregistry && Registry) { + this->mHistogramRegistry = Registry; + this->mQAHistogramRegistry = QAregistry; + + PosDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + + NegDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + } +} + +template +void FemtoDreamResoSelection::fillQA(T const& track1, T const& track2) +{ + PosDaughTrack.fillQA(track1); + NegDaughTrack.fillQA(track2); +} + +template +void FemtoDreamResoSelection::setDaughterCuts(femtoDreamResoSelection::Daughtertype daugh, T selVal, + V selVar, femtoDreamSelection::SelectionType selType) +{ + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setSelection(selVal, selVar, selType); + } + if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setSelection(selVal, selVar, selType); + } +} + +template +void FemtoDreamResoSelection::setDaughterPIDSpecies(T const& daugh, V& pids) +{ + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setPIDSpecies(pids); + } + if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setPIDSpecies(pids); + } +} + +template +bool FemtoDreamResoSelection::DaughterSelection1(V const& track1, bool UseThreshold) +{ + if (!PosDaughTrack.isSelectedMinimal(track1, UseThreshold)) { + return false; + } + return true; +} + +template +bool FemtoDreamResoSelection::DaughterSelection2(V const& track2, bool UseThreshold) +{ + if (!NegDaughTrack.isSelectedMinimal(track2, UseThreshold)) { + return false; + } + return true; +} + +template +bool FemtoDreamResoSelection::isResoOfKind(T const& PosTrack, T const& NegTrack, std::vector const& PID, bool isParticle) +{ + int part1 = PID[0]; + int part2 = PID[1]; + if (!isParticle) { + part1 = PID[1]; + part2 = PID[0]; + } + + bool resultPos = false; + float nSigPosTPC1 = o2::aod::pidutils::tpcNSigma(part1, PosTrack); + float nSigPosTOF1 = PosDaughTrack.getNsigmaTOF(PosTrack, part1); /// for TOF use function in TrackSelection, because it also checks hasTOF() + float nSigPosTPC2 = o2::aod::pidutils::tpcNSigma(part2, PosTrack); + float nSigPosTOF2 = PosDaughTrack.getNsigmaTOF(PosTrack, part2); + if (PosTrack.pt() < mDaughPTPCThr) { + resultPos = (std::abs(nSigPosTPC1) <= std::abs(nSigPosTPC2)); + } else { + resultPos = (std::sqrt(nSigPosTPC1 * nSigPosTPC1 + nSigPosTOF1 * nSigPosTOF1) <= std::sqrt(nSigPosTPC2 * nSigPosTPC2 + nSigPosTOF2 * nSigPosTOF2)); + } + + bool resultNeg = false; + float nSigNegTPC1 = o2::aod::pidutils::tpcNSigma(part1, NegTrack); + float nSigNegTOF1 = NegDaughTrack.getNsigmaTOF(NegTrack, part1); + float nSigNegTPC2 = o2::aod::pidutils::tpcNSigma(part2, NegTrack); + float nSigNegTOF2 = NegDaughTrack.getNsigmaTOF(NegTrack, part2); + if (NegTrack.pt() < mDaughPTPCThr) { + resultNeg = (std::abs(nSigNegTPC2) <= std::abs(nSigNegTPC1)); + } else { + resultNeg = (std::sqrt(nSigNegTPC2 * nSigNegTPC2 + nSigNegTOF2 * nSigNegTOF2) <= std::sqrt(nSigNegTPC1 * nSigNegTPC1 + nSigNegTOF1 * nSigNegTOF1)); + } + return (resultPos && resultNeg); +} + +//// new getCutContainer +template +std::array FemtoDreamResoSelection::getCutContainer(V const& track1, V const& track2, float sign) +{ + cutContainerType outputSign = 0; + cutContainerType outputPID = 0; + size_t counter = 0; + for (auto& sel : mSelections) { /// it should just be a 1D vector with sign + const auto selVariable = sel.getSelectionVariable(); + if (selVariable == femtoDreamResoSelection::kResoSign) { + sel.checkSelectionSetBit(sign, outputSign, counter, nullptr); + } + } + + const auto DCA1 = std::sqrt(track1.dcaXY() * track1.dcaXY() + track1.dcaZ() * track1.dcaZ()); + const auto DCA2 = std::sqrt(track2.dcaXY() * track2.dcaXY() + track2.dcaZ() * track2.dcaZ()); + + auto outputPosTrack = PosDaughTrack.getCutContainer(track1, track1.pt(), track1.eta(), DCA1); // false for useItsPid + auto outputNegTrack = NegDaughTrack.getCutContainer(track2, track2.pt(), track2.eta(), DCA2); + + const auto shiftvalue = numBitsUsed(outputSign); + outputPID = (outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID) << shiftvalue) | outputSign; + + std::array bitmask = {outputPID, + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID)}; + return bitmask; +} +} // namespace o2::analysis::femtoDream + +#endif // PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTION_H_ diff --git a/PWGCF/FemtoDream/Core/femtoDreamResoSelectionK0Short.h b/PWGCF/FemtoDream/Core/femtoDreamResoSelectionK0Short.h new file mode 100644 index 00000000000..a270d6f6795 --- /dev/null +++ b/PWGCF/FemtoDream/Core/femtoDreamResoSelectionK0Short.h @@ -0,0 +1,412 @@ +// 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 FemtoDreamResoSelectionK0Short.h +/// \brief Definition of the FemtoDreamResoSelection +/// \author Valentina Mantovani Sarti, TU München valentina.mantovani-sarti@tum.de +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch + +#ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTIONK0SHORT_H_ +#define PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTIONK0SHORT_H_ + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + +#include "Math/Vector4D.h" +#include "TMath.h" + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +namespace o2::analysis::femtoDream +{ +namespace femtoDreamResoSelection +{ +enum ResoSel { + kResoSign +}; +/// If you add a new selection, adjust kNresoSelection + +enum Daughtertype { + kPosdaugh, + kNegdaugh +}; + +enum ResoMothers { + kPhi, + kKStar +}; +} // namespace femtoDreamResoSelection + +class FemtoDreamResoSelection + : public FemtoDreamObjectSelection +{ + + public: + FemtoDreamResoSelection() /// initialization currently kind of random change this!!! + : mDaughPTPCThr(99.f), mPIDoffsetTPC(0.f), mPIDoffsetTOF(0.f) + { + } + + virtual ~FemtoDreamResoSelection() = default; + + template + uint32_t getType(V const& track1, V const& track2); + + template + size_t numBitsUsed(V const& origvalue); + + template + void init(HistogramRegistry* QAregistry, HistogramRegistry* Registry); + + template + void fillQA(T const& track1, T const& track2); + + template + void setDaughterCuts(femtoDreamResoSelection::Daughtertype child, T selVal, + V selVar, femtoDreamSelection::SelectionType selType); + + template + void setDaughterPIDSpecies(T const& daugh, V& pids); + + template + bool DaughterSelectionPos(V const& track1, bool UseThreshold); + + template + bool DaughterSelectionNeg(V const& track2, bool UseThreshold); + + template + std::array getCutContainer(V const& track1, V const& track2, float sign); + + template + std::pair checkCombination(T const& PosTrack, T const& NegTrack, femtoDreamResoSelection::ResoMothers mother); + + std::pair getPIDPairFromMother(femtoDreamResoSelection::ResoMothers mother); + + template + bool checkPID(T const& Track, float nSigTPC, float nSigTOF, float nSig2TPC, float nSig2TOF); + + void updateThreshold() + { + mDaughPTPCThr = assignedValue; + }; + + void setDaughternSigmaPIDOffset(femtoDreamResoSelection::Daughtertype daugh, float offsetTPC, float offsetTOF) + { + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } else if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } + mPIDoffsetTPC = offsetTPC; + mPIDoffsetTOF = offsetTOF; + }; + + float getMass(o2::track::PID::ID pid) + { + switch (pid) { + case (o2::track::PID::Kaon): + return o2::constants::physics::MassKPlus; + case (o2::track::PID::Pion): + return o2::constants::physics::MassPiPlus; + default: + LOG(warn) << "PID not implemented in femtoDreamResoSelection.getMass"; + return 0.; + } + } + + std::pair getMassDaughters(femtoDreamResoSelection::ResoMothers mother); + + /// The following functions might not be needed, as right now there is only one ResoSel (sign). + /// However all the other selections are implemented this way (also in the CutCulator). + /// So for now this is implemented analogous (migth also be beneficial if further ResoSels want to be implemented). + + /// Helper function to obtain the name of a given selection criterion for consistent naming of the configurables + /// \param iSel Reso selection variable to be examined + /// \param prefix Additional prefix for the name of the configurable + /// \param suffix Additional suffix for the name of the configurable + static std::string getSelectionName(femtoDreamResoSelection::ResoSel iSel, + std::string_view prefix = "", + std::string_view suffix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionNames[iSel]); + outString += suffix; + return outString; + } + + /// Helper function to obtain the index of a given selection variable for consistent naming of the configurables + /// \param obs Reso selection variable (together with prefix) got from file + /// \param prefix Additional prefix for the output of the configurable + static int findSelectionIndex(const std::string_view& obs, + std::string_view prefix = "") + { + for (int index = 0; index < kNresoSelection; index++) { + std::string comp = static_cast(prefix) + + static_cast(mSelectionNames[index]); + std::string_view cmp{comp}; + if (obs.compare(cmp) == 0) + return index; + } + LOGF(info, "Variable %s not found", obs); + return -1; + } + + /// Helper function to obtain the type of a given selection variable for consistent naming of the configurables + /// \param iSel Reso selection variable whose type is returned + static femtoDreamSelection::SelectionType + getSelectionType(femtoDreamResoSelection::ResoSel iSel) + { + return mSelectionTypes[iSel]; + } + + /// for consistent description of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the output of the configurable + static std::string getSelectionHelper(femtoDreamResoSelection::ResoSel iSel, + std::string_view prefix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionHelper[iSel]); + return outString; + } + + private: + float mDaughPTPCThr; + float mPIDoffsetTPC; + float mPIDoffsetTOF; + + FemtoDreamTrackSelection PosDaughTrack; + FemtoDreamTrackSelection NegDaughTrack; + + static constexpr int kNresoSelection = 1; + + static constexpr std::string_view mSelectionNames[kNresoSelection] = {"Sign"}; + + static constexpr femtoDreamSelection::SelectionType mSelectionTypes[kNresoSelection]{ + femtoDreamSelection::kEqual}; + + static constexpr std::string_view mSelectionHelper[kNresoSelection] = { + "+1 for Reso, -1 for AntiReso"}; + +}; // namespace femtoDream + +template +uint32_t FemtoDreamResoSelection::getType(V const& track1, V const& track2) +{ + if (track1.pt() <= mDaughPTPCThr && track2.pt() <= mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTPC_NegdaughTPC; + } + if (track1.pt() <= mDaughPTPCThr && track2.pt() > mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTPC_NegdaughTOF; + } + if (track1.pt() > mDaughPTPCThr && track2.pt() <= mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTOF_NegdaughTPC; + } + if (track1.pt() > mDaughPTPCThr && track2.pt() > mDaughPTPCThr) { + return aod::femtodreamparticle::kPhiPosdaughTOF_NegdaughTOF; + } + return 255; // as error filler +} + +template +size_t FemtoDreamResoSelection::numBitsUsed(V const& origvalue) +{ + size_t bits = 0; + auto value = origvalue; + while (value != 0) { + ++bits; + value >>= 1; + } + return bits; +} + +template +void FemtoDreamResoSelection::init(HistogramRegistry* QAregistry, HistogramRegistry* Registry) +{ + if (QAregistry && Registry) { + this->mHistogramRegistry = Registry; + this->mQAHistogramRegistry = QAregistry; + + PosDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + + NegDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + } +} + +template +void FemtoDreamResoSelection::fillQA(T const& track1, T const& track2) +{ + PosDaughTrack.fillQA(track1); + NegDaughTrack.fillQA(track2); +} + +template +void FemtoDreamResoSelection::setDaughterCuts(femtoDreamResoSelection::Daughtertype daugh, T selVal, + V selVar, femtoDreamSelection::SelectionType selType) +{ + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setSelection(selVal, selVar, selType); + }; + if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setSelection(selVal, selVar, selType); + } +} + +template +void FemtoDreamResoSelection::setDaughterPIDSpecies(T const& daugh, V& pids) +{ + if (daugh == femtoDreamResoSelection::kPosdaugh) { + PosDaughTrack.setPIDSpecies(pids); + } + if (daugh == femtoDreamResoSelection::kNegdaugh) { + NegDaughTrack.setPIDSpecies(pids); + } +} + +template +bool FemtoDreamResoSelection::DaughterSelectionPos(V const& track1, bool UseThreshold) +{ + return PosDaughTrack.isSelectedMinimal(track1, UseThreshold); +} + +template +bool FemtoDreamResoSelection::DaughterSelectionNeg(V const& track2, bool UseThreshold) +{ + return NegDaughTrack.isSelectedMinimal(track2, UseThreshold); +} + +template +std::pair FemtoDreamResoSelection::checkCombination(T const& PosTrack, T const& NegTrack, femtoDreamResoSelection::ResoMothers mother) +{ + /// first bool: normal or anti + /// second bool: is not a valid combination + + auto [part1, part2] = getPIDPairFromMother(mother); + + float nSigPosTPC1 = o2::aod::pidutils::tpcNSigma(part1, PosTrack) - mPIDoffsetTPC; + float nSigPosTOF1 = PosDaughTrack.getNsigmaTOF(PosTrack, part1) - mPIDoffsetTOF; /// for TOF use function in TrackSelection, because it also checks hasTOF() + float nSigPosTPC2 = o2::aod::pidutils::tpcNSigma(part2, PosTrack) - mPIDoffsetTPC; + float nSigPosTOF2 = PosDaughTrack.getNsigmaTOF(PosTrack, part2) - mPIDoffsetTOF; + float nSigNegTPC1 = o2::aod::pidutils::tpcNSigma(part1, NegTrack) - mPIDoffsetTPC; + float nSigNegTOF1 = NegDaughTrack.getNsigmaTOF(NegTrack, part1) - mPIDoffsetTOF; + float nSigNegTPC2 = o2::aod::pidutils::tpcNSigma(part2, NegTrack) - mPIDoffsetTPC; + float nSigNegTOF2 = NegDaughTrack.getNsigmaTOF(NegTrack, part2) - mPIDoffsetTOF; + + if (checkPID(PosTrack, nSigPosTPC1, nSigPosTOF1, nSigPosTPC2, nSigPosTOF2) && checkPID(NegTrack, nSigNegTPC2, nSigNegTOF2, nSigNegTPC1, nSigNegTOF1)) { + return {true, false}; + } else if (checkPID(PosTrack, nSigPosTPC2, nSigPosTOF2, nSigPosTPC1, nSigPosTOF1) && checkPID(NegTrack, nSigNegTPC1, nSigNegTOF1, nSigNegTPC2, nSigNegTOF2)) { + return {false, false}; + } else { + return {false, true}; + } +} + +template +bool FemtoDreamResoSelection::checkPID(T const& Track, float nSig1TPC, float nSig1TOF, float nSig2TPC, float nSig2TOF) +{ + if (Track.pt() < mDaughPTPCThr) { + return (std::abs(nSig1TPC) <= std::abs(nSig2TPC)); + } else { + return (std::sqrt(nSig1TPC * nSig1TPC + nSig1TOF * nSig1TOF) <= std::sqrt(nSig2TPC * nSig2TPC + nSig2TOF * nSig2TOF)); + } +} + +std::pair FemtoDreamResoSelection::getPIDPairFromMother(femtoDreamResoSelection::ResoMothers mother) +{ + /// return is structured this way: + /// The mother particle is assumed to be normal (not antiparticle). Then: + /// 1. return value is positive daughter + /// 2. return value is negative daughter + switch (mother) { + case (femtoDreamResoSelection::kPhi): + return {o2::track::PID::Kaon, o2::track::PID::Kaon}; + case (femtoDreamResoSelection::kKStar): + return {o2::track::PID::Kaon, o2::track::PID::Pion}; + default: + LOG(warn) << "MotherPID not implemented in femtoDreamResoSelection.getPIDPairFromMother"; + return {o2::track::PID::Kaon, o2::track::PID::Kaon}; + } +} + +std::pair FemtoDreamResoSelection::getMassDaughters(femtoDreamResoSelection::ResoMothers mother) +{ + switch (mother) { + case (femtoDreamResoSelection::kPhi): + return {o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}; + case (femtoDreamResoSelection::kKStar): + return {o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}; + default: + LOG(warn) << "MotherPID not implemented in femtoDreamResoSelection.getMassDauhters"; + return {o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}; + } +} + +//// new getCutContainer +template +std::array FemtoDreamResoSelection::getCutContainer(V const& track1, V const& track2, float sign) +{ + cutContainerType outputSign = 0; + cutContainerType outputPID = 0; + size_t counter = 0; + for (auto& sel : mSelections) { /// it should just be a 1D vector with sign + const auto selVariable = sel.getSelectionVariable(); + if (selVariable == femtoDreamResoSelection::kResoSign) { + sel.checkSelectionSetBit(sign, outputSign, counter, nullptr); + } + } + + const auto DCA1 = std::sqrt(track1.dcaXY() * track1.dcaXY() + track1.dcaZ() * track1.dcaZ()); + const auto DCA2 = std::sqrt(track2.dcaXY() * track2.dcaXY() + track2.dcaZ() * track2.dcaZ()); + + auto outputPosTrack = PosDaughTrack.getCutContainer(track1, track1.pt(), track1.eta(), DCA1); // false for useItsPid + auto outputNegTrack = NegDaughTrack.getCutContainer(track2, track2.pt(), track2.eta(), DCA2); + + const auto shiftvalue = numBitsUsed(outputSign); + outputPID = (outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID) << shiftvalue) | outputSign; + + std::array bitmask = {outputPID, + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID)}; + return bitmask; +} +} // namespace o2::analysis::femtoDream + +#endif // PWGCF_FEMTODREAM_CORE_FEMTODREAMRESOSELECTIONK0SHORT_H_ diff --git a/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h b/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h index 9cab0f9e78b..8d6302b3ca3 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// Copyright 2019-2022 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. // @@ -17,20 +17,22 @@ #ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMTRACKSELECTION_H_ #define PWGCF_FEMTODREAM_CORE_FEMTODREAMTRACKSELECTION_H_ -#include -#include -#include -#include - #include "PWGCF/DataModel/FemtoDerived.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h" -#include "ReconstructionDataFormats/PID.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + +#include +#include +#include +#include using namespace o2::framework; @@ -93,7 +95,8 @@ class FemtoDreamTrackSelection : public FemtoDreamObjectSelection - bool isSelectedMinimal(T const& track); + template + bool isSelectedMinimal(T const& track, bool UseThreshold = false); /// Obtain the bit-wise container for the selections /// Pt, eta and dca are not necessarily taken from the track table. For example, for V0 daughters they are recaluated and stored in the V0 table @@ -255,6 +258,7 @@ class FemtoDreamTrackSelection : public FemtoDreamObjectSelection mPIDspecies; ///< All the particle species for which the n_sigma values need to be stored static constexpr int kNtrackSelection = 14; static constexpr std::string_view mSelectionNames[kNtrackSelection] = {"Sign", @@ -381,6 +385,7 @@ void FemtoDreamTrackSelection::init(HistogramRegistry* QAregistry, HistogramRegi dcaZMax = getMinimalSelection(femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); dcaMin = getMinimalSelection(femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); nSigmaPIDMax = getMinimalSelection(femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + nPTPCThr = assignedValue; // inherited from femtoDreamObjectSelection } template @@ -422,7 +427,7 @@ auto FemtoDreamTrackSelection::getNsigmaITS(T const& track, o2::track::PID pid) } template -bool FemtoDreamTrackSelection::isSelectedMinimal(T const& track) +bool FemtoDreamTrackSelection::isSelectedMinimal(T const& track, bool UseThreshold) { const auto pT = track.pt(); const auto eta = track.eta(); @@ -494,6 +499,26 @@ bool FemtoDreamTrackSelection::isSelectedMinimal(T const& track) return isFulfilled; } } + + if (UseThreshold && nPIDnSigmaSel > 0) { + bool pass = false; + for (size_t i = 0; i < pidTPC.size(); ++i) { + + auto pidTPCVal = pidTPC.at(i); + if (pT < nPTPCThr) { + pass = std::fabs(pidTPCVal) < nSigmaPIDMax; + } else if (pT >= nPTPCThr) { + auto pidTOFVal = pidTOF.at(i); + pass = std::sqrt(pidTPCVal * pidTPCVal + pidTOFVal * pidTOFVal) < nSigmaPIDMax; + } + if (pass) + break; // early exit if any condition is satisfied + } + + if (!pass) { + return false; + } + } return true; } diff --git a/PWGCF/FemtoDream/Core/femtoDreamUtils.h b/PWGCF/FemtoDream/Core/femtoDreamUtils.h index f9bb60633f3..2cc8367bcc3 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamUtils.h +++ b/PWGCF/FemtoDream/Core/femtoDreamUtils.h @@ -16,11 +16,13 @@ #ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMUTILS_H_ #define PWGCF_FEMTODREAM_CORE_FEMTODREAMUTILS_H_ -#include -#include -#include "CommonConstants/PhysicsConstants.h" #include "PWGCF/DataModel/FemtoDerived.h" +#include "CommonConstants/PhysicsConstants.h" + +#include +#include + namespace o2::analysis::femtoDream { @@ -52,9 +54,6 @@ inline float getMass(int pdgCode) case o2::constants::physics::Pdg::kPhi: mass = o2::constants::physics::MassPhi; break; - case o2::constants::physics::Pdg::kDPlus: - mass = o2::constants::physics::MassDPlus; - break; case o2::constants::physics::Pdg::kLambdaCPlus: mass = o2::constants::physics::MassLambdaCPlus; break; @@ -67,6 +66,12 @@ inline float getMass(int pdgCode) case o2::constants::physics::Pdg::kHelium3: mass = o2::constants::physics::MassHelium3; break; + case o2::constants::physics::Pdg::kK0Star892: + mass = o2::constants::physics::MassK0Star892; + break; + case 310: /// K0Short is not implemented in o2::physics::constants::Pdg + mass = o2::constants::physics::MassK0Short; + break; default: LOG(fatal) << "PDG code is not suppored"; } diff --git a/PWGCF/FemtoDream/Core/femtoDreamV0SelectionK0Short.h b/PWGCF/FemtoDream/Core/femtoDreamV0SelectionK0Short.h new file mode 100644 index 00000000000..be69638690d --- /dev/null +++ b/PWGCF/FemtoDream/Core/femtoDreamV0SelectionK0Short.h @@ -0,0 +1,778 @@ +// 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 FemtoDreamV0Selection.h +/// \brief Definition of the FemtoDreamV0Selection +/// \author Valentina Mantovani Sarti, TU München valentina.mantovani-sarti@tum.de +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch + +#ifndef PWGCF_FEMTODREAM_CORE_FEMTODREAMV0SELECTION_H_ +#define PWGCF_FEMTODREAM_CORE_FEMTODREAMV0SELECTION_H_ + +#include "PWGCF/FemtoDream/Core/femtoDreamObjectSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + +#include +#include +#include + +using namespace o2::framework; + +namespace o2::analysis::femtoDream +{ + +namespace femtoDreamV0Selection +{ +/// The different selections this task is capable of doing +enum V0Sel { + kV0Sign, ///< +1 particle, -1 antiparticle + kV0pTMin, + kV0pTMax, + kV0etaMax, + kV0DCADaughMax, + kV0CPAMin, + kV0TranRadMin, + kV0TranRadMax, + kV0DecVtxMax, +}; + +enum ChildTrackType { kPosTrack, + kNegTrack }; + +enum V0ContainerPosition { + kV0, + kPosCuts, + kPosPID, + kNegCuts, + kNegPID, +}; /// Position in the full VO cut container + +} // namespace femtoDreamV0Selection + +/// \class FemtoDreamV0Selection +/// \brief Cut class to contain and execute all cuts applied to V0s +class FemtoDreamV0Selection + : public FemtoDreamObjectSelection +{ + public: + FemtoDreamV0Selection() + : nPtV0MinSel(0), nPtV0MaxSel(0), nEtaV0MaxSel(0), nDCAV0DaughMax(0), nCPAV0Min(0), nTranRadV0Min(0), nTranRadV0Max(0), nDecVtxMax(0), pTV0Min(9999999.), pTV0Max(-9999999.), etaV0Max(-9999999.), DCAV0DaughMax(-9999999.), CPAV0Min(9999999.), TranRadV0Min(9999999.), TranRadV0Max(-9999999.), DecVtxMax(-9999999.), fInvMassLowLimit(1.05), fInvMassUpLimit(1.3), fRejectKaon(false), fRejectLambda(false), fInvMassKaonLowLimit(0.48), fInvMassKaonUpLimit(0.515), nSigmaPIDOffsetTPC(0.), fMotherIsLambda(true) {} + /// Initializes histograms for the task + template + void init(HistogramRegistry* QAregistry, HistogramRegistry* Registry); + + template + bool isSelectedMinimal(C const& col, V const& v0, T const& posTrack, + T const& negTrack); + + template + void fillLambdaQA(C const& col, V const& v0, T const& posTrack, + T const& negTrack); + + /// \todo for the moment the PID of the tracks is factored out into a separate + /// field, hence 5 values in total \\ASK: what does it mean? + template + std::array getCutContainer(C const& col, V const& v0, + T const& posTrack, + T const& negTrack); + + template + void fillQA(C const& col, V const& v0, T const& posTrack, T const& negTrack); + + template + void setChildCuts(femtoDreamV0Selection::ChildTrackType child, T1 selVal, + T2 selVar, femtoDreamSelection::SelectionType selType) + { + if (child == femtoDreamV0Selection::kPosTrack) { + PosDaughTrack.setSelection(selVal, selVar, selType); + } else if (child == femtoDreamV0Selection::kNegTrack) { + NegDaughTrack.setSelection(selVal, selVar, selType); + } + } + template + void setChildPIDSpecies(femtoDreamV0Selection::ChildTrackType child, + T& pids) + { + if (child == femtoDreamV0Selection::kPosTrack) { + PosDaughTrack.setPIDSpecies(pids); + } else if (child == femtoDreamV0Selection::kNegTrack) { + NegDaughTrack.setPIDSpecies(pids); + } + } + + /// Helper function to obtain the name of a given selection criterion for consistent naming of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the name of the configurable + /// \param suffix Additional suffix for the name of the configurable + static std::string getSelectionName(femtoDreamV0Selection::V0Sel iSel, + std::string_view prefix = "", + std::string_view suffix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionNames[iSel]); + outString += suffix; + return outString; + } + + /// Helper function to obtain the index of a given selection variable for consistent naming of the configurables + /// \param obs V0 selection variable (together with prefix) got from file + /// \param prefix Additional prefix for the output of the configurable + static int findSelectionIndex(const std::string_view& obs, + std::string_view prefix = "") + { + for (int index = 0; index < kNv0Selection; index++) { + std::string comp = static_cast(prefix) + + static_cast(mSelectionNames[index]); + std::string_view cmp{comp}; + if (obs.compare(cmp) == 0) + return index; + } + LOGF(info, "Variable %s not found", obs); + return -1; + } + + /// Helper function to obtain the type of a given selection variable for consistent naming of the configurables + /// \param iSel V0 selection variable whose type is returned + static femtoDreamSelection::SelectionType + getSelectionType(femtoDreamV0Selection::V0Sel iSel) + { + return mSelectionTypes[iSel]; + } + + /// Helper function to obtain the helper string of a given selection criterion + /// for consistent description of the configurables + /// \param iSel Track selection variable to be examined + /// \param prefix Additional prefix for the output of the configurable + static std::string getSelectionHelper(femtoDreamV0Selection::V0Sel iSel, + std::string_view prefix = "") + { + std::string outString = static_cast(prefix); + outString += static_cast(mSelectionHelper[iSel]); + return outString; + } + + /// Set limit for the selection on the invariant mass + /// \param lowLimit Lower limit for the invariant mass distribution + /// \param upLimit Upper limit for the invariant mass distribution + void setInvMassLimits(float lowLimit, float upLimit) + { + fInvMassLowLimit = lowLimit; + fInvMassUpLimit = upLimit; + } + + /// Set limit for the kaon rejection on the invariant mass + /// \param lowLimit Lower limit for the invariant mass distribution + /// \param upLimit Upper limit for the invariant mass distribution + void setKaonInvMassLimits(float lowLimit, float upLimit) + { + fRejectKaon = true; + fInvMassKaonLowLimit = lowLimit; + fInvMassKaonUpLimit = upLimit; + } + + void setnSigmaPIDOffsetTPC(float offsetTPC) + { + nSigmaPIDOffsetTPC = offsetTPC; + } + + void setChildRejectNotPropagatedTracks(femtoDreamV0Selection::ChildTrackType child, bool reject) + { + if (child == femtoDreamV0Selection::kPosTrack) { + PosDaughTrack.setRejectNotPropagatedTracks(reject); + } else if (child == femtoDreamV0Selection::kNegTrack) { + NegDaughTrack.setRejectNotPropagatedTracks(reject); + } + } + + void setChildnSigmaPIDOffset(femtoDreamV0Selection::ChildTrackType child, float offsetTPC, float offsetTOF) + { + if (child == femtoDreamV0Selection::kPosTrack) { + PosDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } else if (child == femtoDreamV0Selection::kNegTrack) { + NegDaughTrack.setnSigmaPIDOffset(offsetTPC, offsetTOF); + } + } + + void setIsMother(bool IsMother) + { + fMotherIsLambda = IsMother; + } + + void setRejectLambda(bool reject) + { + fRejectLambda = reject; + } + + private: + int nPtV0MinSel; + int nPtV0MaxSel; + int nEtaV0MaxSel; + int nDCAV0DaughMax; + int nCPAV0Min; + int nTranRadV0Min; + int nTranRadV0Max; + int nDecVtxMax; + float pTV0Min; + float pTV0Max; + float etaV0Max; + float DCAV0DaughMax; + float CPAV0Min; + float TranRadV0Min; + float TranRadV0Max; + float DecVtxMax; + + float fInvMassLowLimit; + float fInvMassUpLimit; + + bool fRejectKaon; + bool fRejectLambda; + float fInvMassKaonLowLimit; + float fInvMassKaonUpLimit; + + float nSigmaPIDOffsetTPC; + + bool fMotherIsLambda; + + FemtoDreamTrackSelection PosDaughTrack; + FemtoDreamTrackSelection NegDaughTrack; + + static constexpr int kNv0Selection = 9; + + static constexpr std::string_view mSelectionNames[kNv0Selection] = { + "Sign", "PtMin", "PtMax", "EtaMax", "DCAdaughMax", "CPAMin", + "TranRadMin", "TranRadMax", "DecVecMax"}; ///< Name of the different + ///< selections + + static constexpr femtoDreamSelection::SelectionType + mSelectionTypes[kNv0Selection]{ + femtoDreamSelection::kEqual, + femtoDreamSelection::kLowerLimit, + femtoDreamSelection::kUpperLimit, + femtoDreamSelection::kUpperLimit, + femtoDreamSelection::kUpperLimit, + femtoDreamSelection::kLowerLimit, + femtoDreamSelection::kLowerLimit, + femtoDreamSelection::kUpperLimit, + femtoDreamSelection::kUpperLimit}; ///< Map to match a variable with + ///< its type + + static constexpr std::string_view mSelectionHelper[kNv0Selection] = { + "+1 for lambda, -1 for antilambda", + "Minimum pT (GeV/c)", + "Maximum pT (GeV/c)", + "Maximum |Eta|", + "Maximum DCA between daughters (cm)", + "Minimum Cosine of Pointing Angle", + "Minimum transverse radius (cm)", + "Maximum transverse radius (cm)", + "Maximum distance from primary vertex"}; ///< Helper information for the + ///< different selections + +}; // namespace femtoDream + +template +void FemtoDreamV0Selection::init(HistogramRegistry* QAregistry, HistogramRegistry* Registry) +{ + if (QAregistry && Registry) { + mHistogramRegistry = Registry; + mQAHistogramRegistry = QAregistry; + fillSelectionHistogram(); + fillSelectionHistogram(); + + AxisSpec massAxisLambda = {600, 0.0f, 3.0f, "m_{#Lambda} (GeV/#it{c}^{2})"}; /// paramters for K0Short + AxisSpec massAxisAntiLambda = {600, 0.0f, 3.0f, + "m_{#bar{#Lambda}} (GeV/#it{c}^{2})"}; + + /// \todo this should be an automatic check in the parent class, and the + /// return type should be templated + size_t nSelections = getNSelections(); + if (nSelections > 8 * sizeof(cutContainerType)) { + LOG(fatal) << "FemtoDreamV0Cuts: Number of selections to large for your " + "container - quitting!"; + } + + std::string folderName = static_cast( + o2::aod::femtodreamparticle::ParticleTypeName[part]); + /// \todo initialize histograms for children tracks of v0s + mQAHistogramRegistry->add((folderName + "/hPt").c_str(), + "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, + {{1000, 0, 10}}); + mQAHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", + kTH1F, {{1000, -1, 1}}); + mQAHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", + kTH1F, {{1000, 0, 2. * M_PI}}); + mQAHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), + "; DCA^{daugh} (cm); Entries", kTH1F, + {{1000, 0, 10}}); + mQAHistogramRegistry->add((folderName + "/hTransRadius").c_str(), + "; #it{r}_{xy} (cm); Entries", kTH1F, + {{1500, 0, 150}}); + mQAHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), + "; #it{Vtx}_{x} (cm); Entries", kTH1F, + {{2000, 0, 200}}); + mQAHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), + "; #it{Vtx}_{y} (cm)); Entries", kTH1F, + {{2000, 0, 200}}); + mQAHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), + "; #it{Vtx}_{z} (cm); Entries", kTH1F, + {{2000, 0, 200}}); + mQAHistogramRegistry->add((folderName + "/hCPA").c_str(), + "; #it{cos #theta_{p}}; Entries", kTH1F, + {{1000, 0.9, 1.}}); + mQAHistogramRegistry->add((folderName + "/hCPAvsPt").c_str(), + "; #it{p}_{T} (GeV/#it{c}); #it{cos #theta_{p}}", + kTH2F, {{8, 0.3, 4.3}, {1000, 0.9, 1.}}); + mQAHistogramRegistry->add((folderName + "/hInvMassLambda").c_str(), "", kTH1F, + {massAxisLambda}); + mQAHistogramRegistry->add((folderName + "/hInvMassAntiLambda").c_str(), "", + kTH1F, {massAxisAntiLambda}); + mQAHistogramRegistry->add((folderName + "/hInvMassLambdaAntiLambda").c_str(), + "", kTH2F, {massAxisLambda, massAxisAntiLambda}); + + PosDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + NegDaughTrack.init( + mQAHistogramRegistry, mHistogramRegistry); + + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaNoCuts", "No cuts", kTH1F, + {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaInvMassCut", + "Invariant mass cut", kTH1F, {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMin", "Minimum Pt cut", + kTH1F, {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMax", "Maximum Pt cut", + kTH1F, {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaEtaMax", "Maximum Eta cut", + kTH1F, {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaDCAV0Daugh", + "V0-daughters DCA cut", kTH1F, {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaCPA", "CPA cut", kTH1F, + {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMin", + "Minimum transverse radius cut", kTH1F, + {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMax", + "Maximum transverse radius cut", kTH1F, + {massAxisLambda}); + mQAHistogramRegistry->add("LambdaQA/hInvMassLambdaDecVtxMax", + "Maximum distance on decay vertex cut", kTH1F, + {massAxisLambda}); + } + + /// check whether the most open cuts are fulfilled - most of this should have + /// already be done by the filters + nPtV0MinSel = getNSelections(femtoDreamV0Selection::kV0pTMin); + nPtV0MaxSel = getNSelections(femtoDreamV0Selection::kV0pTMax); + nEtaV0MaxSel = getNSelections(femtoDreamV0Selection::kV0etaMax); + nDCAV0DaughMax = getNSelections(femtoDreamV0Selection::kV0DCADaughMax); + nCPAV0Min = getNSelections(femtoDreamV0Selection::kV0CPAMin); + nTranRadV0Min = getNSelections(femtoDreamV0Selection::kV0TranRadMin); + nTranRadV0Max = getNSelections(femtoDreamV0Selection::kV0TranRadMax); + nDecVtxMax = getNSelections(femtoDreamV0Selection::kV0DecVtxMax); + + pTV0Min = getMinimalSelection(femtoDreamV0Selection::kV0pTMin, + femtoDreamSelection::kLowerLimit); + pTV0Max = getMinimalSelection(femtoDreamV0Selection::kV0pTMax, + femtoDreamSelection::kUpperLimit); + etaV0Max = getMinimalSelection(femtoDreamV0Selection::kV0etaMax, + femtoDreamSelection::kAbsUpperLimit); + DCAV0DaughMax = getMinimalSelection(femtoDreamV0Selection::kV0DCADaughMax, + femtoDreamSelection::kUpperLimit); + CPAV0Min = getMinimalSelection(femtoDreamV0Selection::kV0CPAMin, + femtoDreamSelection::kLowerLimit); + TranRadV0Min = getMinimalSelection(femtoDreamV0Selection::kV0TranRadMin, + femtoDreamSelection::kLowerLimit); + TranRadV0Max = getMinimalSelection(femtoDreamV0Selection::kV0TranRadMax, + femtoDreamSelection::kUpperLimit); + DecVtxMax = getMinimalSelection(femtoDreamV0Selection::kV0DecVtxMax, + femtoDreamSelection::kAbsUpperLimit); +} + +template +bool FemtoDreamV0Selection::isSelectedMinimal(C const& /*col*/, V const& v0, + T const& posTrack, + T const& negTrack) +{ + const auto signPos = posTrack.sign(); + const auto signNeg = negTrack.sign(); + if (signPos < 0 || signNeg > 0) { + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for V0 daughters"; + } + // asfaf + const float pT = v0.pt(); + const float eta = v0.eta(); + const std::vector decVtx = {v0.x(), v0.y(), v0.z()}; + const float tranRad = v0.v0radius(); + const float dcaDaughv0 = v0.dcaV0daughters(); + const float cpav0 = v0.v0cosPA(); + + const float invMassLambda = v0.mLambda(); + const float invMassAntiLambda = v0.mAntiLambda(); + + const float invMassKaon = v0.mK0Short(); + + if (fMotherIsLambda) { /// Lambda + if ((invMassLambda < fInvMassLowLimit || invMassLambda > fInvMassUpLimit) && + (invMassAntiLambda < fInvMassLowLimit || + invMassAntiLambda > fInvMassUpLimit)) { + return false; + } + if (fRejectKaon) { + if (invMassKaon > fInvMassKaonLowLimit && + invMassKaon < fInvMassKaonUpLimit) { + return false; + } + } + } else { /// K0Short + if ((invMassKaon < fInvMassKaonLowLimit || invMassKaon > fInvMassKaonUpLimit)) { + return false; + } + if (fRejectLambda) { + if ((invMassLambda > fInvMassLowLimit && + invMassLambda < fInvMassUpLimit) || + (invMassAntiLambda > fInvMassLowLimit && + invMassAntiLambda < fInvMassUpLimit)) { + return false; + } + } + } + + if (nPtV0MinSel > 0 && pT < pTV0Min) { + return false; + } + if (nPtV0MaxSel > 0 && pT > pTV0Max) { + return false; + } + if (nEtaV0MaxSel > 0 && std::abs(eta) > etaV0Max) { + return false; + } + if (nDCAV0DaughMax > 0 && dcaDaughv0 > DCAV0DaughMax) { + return false; + } + if (nCPAV0Min > 0 && cpav0 < CPAV0Min) { + return false; + } + if (nTranRadV0Min > 0 && tranRad < TranRadV0Min) { + return false; + } + if (nTranRadV0Max > 0 && tranRad > TranRadV0Max) { + return false; + } + for (size_t i = 0; i < decVtx.size(); i++) { + if (nDecVtxMax > 0 && decVtx.at(i) > DecVtxMax) { + return false; + } + } + if (!PosDaughTrack.isSelectedMinimal(posTrack)) { + return false; + } + if (!NegDaughTrack.isSelectedMinimal(negTrack)) { + return false; + } + + // check that track combinations for V0 or antiV0 would be fulfilling PID + int nSigmaPIDMax = PosDaughTrack.getSigmaPIDMax(); + if (fMotherIsLambda) { /// Lambda + // antiV0 + auto nSigmaPrNeg = negTrack.tpcNSigmaPr(); + auto nSigmaPiPos = posTrack.tpcNSigmaPi(); + // v0 + auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); + auto nSigmaPrPos = posTrack.tpcNSigmaPr(); + if (!(std::abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + std::abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) && + !(std::abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + std::abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax)) { + return false; + } + } else { /// K0SHort + auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); + auto nSigmaPiPos = posTrack.tpcNSigmaPi(); + if (!(std::abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + std::abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax)) { + return false; + } + } + + return true; +} + +template +void FemtoDreamV0Selection::fillLambdaQA(C const& /*col*/, V const& v0, + T const& posTrack, T const& negTrack) +{ + const auto signPos = posTrack.sign(); + const auto signNeg = negTrack.sign(); + if (signPos < 0 || signNeg > 0) { + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for V0 daughters"; + } + const float pT = v0.pt(); + const float eta = v0.eta(); + const std::vector decVtx = {v0.x(), v0.y(), v0.z()}; + const float tranRad = v0.v0radius(); + const float dcaDaughv0 = v0.dcaV0daughters(); + const float cpav0 = v0.v0cosPA(); + + const float invMassLambda = v0.mLambda(); + const float invMassKaon = v0.mK0Short(); + + float fillMass = 0.; + if (fMotherIsLambda) { + fillMass = v0.mLambda(); + } else { + fillMass = v0.mK0Short(); + } + + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaNoCuts"), fillMass); + + if (fMotherIsLambda) { /// Lambda + if (invMassLambda > fInvMassLowLimit && invMassLambda < fInvMassUpLimit) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), + v0.mLambda()); + } + } else { /// K0Short + if (invMassKaon > fInvMassKaonLowLimit && invMassKaon < fInvMassKaonUpLimit) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), + v0.mK0Short()); + } + } + + if (pT > pTV0Min) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), + fillMass); + } + if (pT < pTV0Max) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), + fillMass); + } + if (std::abs(eta) < etaV0Max) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaEtaMax"), + fillMass); + } + if (dcaDaughv0 < DCAV0DaughMax) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAV0Daugh"), + fillMass); + } + if (cpav0 > CPAV0Min) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaCPA"), fillMass); + } + if (tranRad > TranRadV0Min) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), + fillMass); + } + if (tranRad < TranRadV0Max) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), + fillMass); + } + bool write = true; + for (size_t i = 0; i < decVtx.size(); i++) { + write = write && (decVtx.at(i) < DecVtxMax); + } + if (write) { + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), + fillMass); + } +} + +/// the CosPA of V0 needs as argument the posXYZ of collisions vertex so we need +/// to pass the collsion as well +template +std::array + FemtoDreamV0Selection::getCutContainer(C const& /*col*/, V const& v0, T const& posTrack, T const& negTrack) +{ + auto outputPosTrack = PosDaughTrack.getCutContainer(posTrack, v0.positivept(), v0.positiveeta(), v0.dcapostopv()); + auto outputNegTrack = NegDaughTrack.getCutContainer(negTrack, v0.negativept(), v0.negativeeta(), v0.dcanegtopv()); + cutContainerType output = 0; + size_t counter = 0; + + float sign = 0.; + /// Lambda + if (fMotherIsLambda) { + auto lambdaMassNominal = o2::constants::physics::MassLambda; + auto lambdaMassHypothesis = v0.mLambda(); + auto antiLambdaMassHypothesis = v0.mAntiLambda(); + auto diffLambda = std::abs(lambdaMassNominal - lambdaMassHypothesis); + auto diffAntiLambda = std::abs(antiLambdaMassHypothesis - lambdaMassHypothesis); + + int nSigmaPIDMax = PosDaughTrack.getSigmaPIDMax(); + auto nSigmaPrNeg = negTrack.tpcNSigmaPr(); + auto nSigmaPiPos = posTrack.tpcNSigmaPi(); + auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); + auto nSigmaPrPos = posTrack.tpcNSigmaPr(); + // check the mass and the PID of daughters + if (std::abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && std::abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda > diffLambda) { + sign = -1.; + } else if (std::abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && std::abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda < diffLambda) { + sign = 1.; + } else { + // if it happens that none of these are true, ignore the invariant mass + if (std::abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && std::abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { + sign = -1.; + } else if (std::abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && std::abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { + sign = 1.; + } + } + } else { + sign = 1.; // for the K0Short arbitrarily set the sign to 1 + } + + const auto pT = v0.pt(); + const auto eta = v0.eta(); + const auto tranRad = v0.v0radius(); + const auto dcaDaughv0 = v0.dcaV0daughters(); + const auto cpav0 = v0.v0cosPA(); + const std::vector decVtx = {v0.x(), v0.y(), v0.z()}; + + float observable = 0.; + for (auto& sel : mSelections) { + const auto selVariable = sel.getSelectionVariable(); + if (selVariable == femtoDreamV0Selection::kV0DecVtxMax) { + for (size_t i = 0; i < decVtx.size(); ++i) { + auto decVtxValue = decVtx.at(i); + sel.checkSelectionSetBit(decVtxValue, output, counter, nullptr); + } + } else { + switch (selVariable) { + case (femtoDreamV0Selection::kV0Sign): + observable = sign; + break; + case (femtoDreamV0Selection::kV0pTMin): + observable = pT; + break; + case (femtoDreamV0Selection::kV0pTMax): + observable = pT; + break; + case (femtoDreamV0Selection::kV0etaMax): + observable = eta; + break; + case (femtoDreamV0Selection::kV0DCADaughMax): + observable = dcaDaughv0; + break; + case (femtoDreamV0Selection::kV0CPAMin): + observable = cpav0; + break; + case (femtoDreamV0Selection::kV0TranRadMin): + observable = tranRad; + break; + case (femtoDreamV0Selection::kV0TranRadMax): + observable = tranRad; + break; + case (femtoDreamV0Selection::kV0DecVtxMax): + break; + } + sel.checkSelectionSetBit(observable, output, counter, nullptr); + } + } + return { + output, + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputPosTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + outputNegTrack.at(femtoDreamTrackSelection::TrackContainerPosition::kPID)}; +} + +template +void FemtoDreamV0Selection::fillQA(C const& /*col*/, V const& v0, T const& posTrack, + T const& negTrack) +{ + if (mQAHistogramRegistry) { + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hPt"), + v0.pt()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hEta"), + v0.eta()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hPhi"), + v0.phi()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hDaughDCA"), + v0.dcaV0daughters()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hTransRadius"), + v0.v0radius()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxX"), + v0.x()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxY"), + v0.y()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxZ"), + v0.z()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hCPA"), + v0.v0cosPA()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hCPAvsPt"), + v0.pt(), v0.v0cosPA()); + + if (fMotherIsLambda) { /// Lambda + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hInvMassLambda"), + v0.mLambda()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hInvMassAntiLambda"), + v0.mAntiLambda()); + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hInvMassLambdaAntiLambda"), + v0.mLambda(), v0.mAntiLambda()); + } else { /// K0Short + mQAHistogramRegistry->fill( + HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + + HIST("/hInvMassLambda"), + v0.mK0Short()); + } + } + + PosDaughTrack.fillQA(posTrack); + NegDaughTrack.fillQA(negTrack); +} + +} // namespace o2::analysis::femtoDream + +#endif // PWGCF_FEMTODREAM_CORE_FEMTODREAMV0SELECTION_H_ diff --git a/PWGCF/FemtoDream/TableProducer/CMakeLists.txt b/PWGCF/FemtoDream/TableProducer/CMakeLists.txt index 3af1c541683..5adbbb79643 100644 --- a/PWGCF/FemtoDream/TableProducer/CMakeLists.txt +++ b/PWGCF/FemtoDream/TableProducer/CMakeLists.txt @@ -14,6 +14,16 @@ o2physics_add_dpl_workflow(femtodream-producer PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-producer-reso + SOURCES femtoDreamProducerTaskReso.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtodream-producer-reso-kshort + SOURCES femtoDreamProducerTaskResoKshort.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-producer-reduced SOURCES femtoDreamProducerReducedTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskReso.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskReso.cxx new file mode 100644 index 00000000000..ff78067b774 --- /dev/null +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskReso.cxx @@ -0,0 +1,1010 @@ +// Copyright 2019-2022 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 femtoDreamProducerTask.cxx +/// \brief Tasks that produces the track tables used for the pairing +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamResoSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include "PWGCF/FemtoDream/Core/femtoDreamV0Selection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" + +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include + +#include "Math/Vector4D.h" +#include "TMath.h" + +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femtoDream; + +namespace o2::aod +{ +using FemtoFullCollision = soa::Join::iterator; +using FemtoFullCollision_noCent = soa::Join::iterator; +using FemtoFullCollision_CentPbPb = soa::Join::iterator; +using FemtoFullCollisionMC = soa::Join::iterator; +using FemtoFullCollision_noCent_MC = soa::Join::iterator; +using FemtoFullCollisionMC_CentPbPb = soa::Join::iterator; +using FemtoFullMCgenCollisions = soa::Join; +using FemtoFullMCgenCollision = FemtoFullMCgenCollisions::iterator; + +using FemtoFullTracks = + soa::Join; + +} // namespace o2::aod + +namespace softwareTriggers +{ +static const int nTriggers = 6; +static const std::vector triggerNames{"fPPP", "fPPL", "fPLL", "fLLL", "fPD", "fLD"}; +static const float triggerSwitches[1][nTriggers]{ + {0, 0, 0, 0, 0, 0}}; +} // namespace softwareTriggers + +template +int getRowDaughters(int daughID, T const& vecID) +{ + int rowInPrimaryTrackTableDaugh = -1; + for (size_t i = 0; i < vecID.size(); i++) { + if (vecID.at(i) == daughID) { + rowInPrimaryTrackTableDaugh = i; + break; + } + } + return rowInPrimaryTrackTableDaugh; +} + +struct femtoDreamProducerTaskReso { + + SliceCache cache; // o2::framework, included in ASoAHelpers.h + Preslice perCol = aod::track::collisionId; // o2::framework included in ASoAHelpers.h + Partition daughter1 = aod::track::signed1Pt > 0.f; // o2::framework included in AnalysisHelper.h + Partition daughter2 = aod::track::signed1Pt < 0.f; // o2::framework included in AnalysisHelper.h + + Zorro zorro; + + Produces outputCollision; + Produces outputMCCollision; + Produces outputCollsMCLabels; + Produces outputParts; + Produces outputPartsMC; + Produces outputDebugParts; + Produces outputPartsMCLabels; + Produces outputDebugPartsMC; + Produces outputPartsExtMCLabels; + + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable Debug tables"}; + Configurable ConfUseItsPid{"ConfUseItsPid", false, "Enable Debug tables"}; + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; // true? + Configurable ConfIsForceGRP{"ConfIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; + /// Event cuts + FemtoDreamCollisionSelection colCuts; + // Event cuts - Triggers + Configurable ConfEnableTriggerSelection{"ConfEnableTriggerSelection", false, "Should the trigger selection be enabled for collisions?"}; + Configurable> ConfTriggerSwitches{ + "ConfTriggerSwitches", + {softwareTriggers::triggerSwitches[0], 1, softwareTriggers::nTriggers, std::vector{"Switch"}, softwareTriggers::triggerNames}, + "Turn on which trigger should be checked for recorded events to pass selection"}; + Configurable ConfBaseCCDBPathForTriggers{"ConfBaseCCDBPathForTriggers", "Users/m/mpuccio/EventFiltering/OTS/Chunked/", "Provide ccdb path for trigger table; default - trigger coordination"}; + + // Event cuts - usual selection criteria + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", true, "Evt sel: check for trigger"}; + Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", kINT7, "Evt sel: trigger"}; + Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable ConfEvtAddOfflineCheck{"ConfEvtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; + Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtodream tables"}; + Configurable ConfIsActivateReso{"ConfIsActivateReso", true, "Activate filling of sl Resonances into femtodream tables"}; + Configurable ConfIsActivatePhi{"ConfIsActivatePhi", true, "Activates cuts on Phi's and fills tables"}; + + Configurable ConfTrkRejectNotPropagated{"ConfTrkRejectNotPropagated", false, "True: reject not propagated tracks"}; + // Configurable ConfRejectITSHitandTOFMissing{ "ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; + Configurable ConfTrkPDGCode{"ConfTrkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; + FemtoDreamTrackSelection trackCuts; + struct : ConfigurableGroup { + std::string prefix = std::string("Track"); + Configurable> ConfTrkCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "ConfTrk"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Track selection: ")}; + Configurable> ConfTrkPtmin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "ConfTrk"), std::vector{0.5f, 0.4f, 0.6f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Track selection: ")}; + Configurable> ConfTrkPtmax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "ConfTrk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Track selection: ")}; + Configurable> ConfTrkEta{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "ConfTrk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Track selection: ")}; + Configurable> ConfTrkTPCnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "ConfTrk"), std::vector{80.f, 70.f, 60.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCfCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "ConfTrk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "ConfTrk"), std::vector{70.f, 60.f, 80.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Track selection: ")}; + Configurable> ConfTrkTPCsCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCsClsMax, "ConfTrk"), std::vector{0.1f, 160.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCsClsMax, "Track selection: ")}; + Configurable> ConfTrkITSnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsMin, "ConfTrk"), std::vector{-1.f, 2.f, 4.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsMin, "Track selection: ")}; + Configurable> ConfTrkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "ConfTrk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; + Configurable> ConfTrkDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.1f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Track selection: ")}; + Configurable> ConfTrkDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Track selection: ")}; + Configurable> ConfTrkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "ConfTrk"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; + Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; // set to zero for run3 or so + Configurable ConfTrkPIDnSigmaOffsetTOF{"ConfTrkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; + Configurable> ConfTrkPIDspecies{"ConfTrkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + // missing DCA configurable?? because implemented in TrackSelection.h + } Track; + + FemtoDreamV0Selection v0Cuts; + Configurable> ConfV0Sign{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0Sign, "V0 selection: ")}; + Configurable> ConfV0PtMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0pTMin, "V0 selection: ")}; + Configurable> ConfV0PtMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0pTMax, "V0 selection: ")}; + Configurable> ConfV0EtaMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0etaMax, "ConfV0"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0etaMax, "V0 selection: ")}; + Configurable> ConfV0DCADaughMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0DCADaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0DCADaughMax, "V0 selection: ")}; + Configurable> ConfV0CPAMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0CPAMin, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0CPAMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0TranRadMin, "ConfV0"), std::vector{0.2f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0TranRadMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0TranRadMax, "ConfV0"), std::vector{100.f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0TranRadMax, "V0 selection: ")}; + Configurable> ConfV0DecVtxMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0DecVtxMax, "ConfV0"), std::vector{100.f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0DecVtxMax, "V0 selection: ")}; + + Configurable ConfV0InvMassLowLimit{"ConfV0InvV0MassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; + Configurable ConfV0InvMassUpLimit{"ConfV0InvV0MassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; + Configurable ConfV0RejectKaons{"ConfV0RejectKaons", false, "Switch to reject kaons"}; + + Configurable ConfV0InvKaonMassLowLimit{"ConfV0InvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; + Configurable ConfV0InvKaonMassUpLimit{"ConfV0InvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; + Configurable> ConfChildCharge{"ConfChildSign", std::vector{-1, 1}, "V0 Child sel: Charge"}; + Configurable> ConfChildEtaMax{"ConfChildEtaMax", std::vector{0.8f}, "V0 Child sel: max eta"}; + Configurable> ConfChildTPCnClsMin{"ConfChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "V0 Child sel: Min. nCls TPC"}; + Configurable> ConfChildDCAMin{"ConfChildDCAMin", std::vector{0.05f, 0.06f}, "V0 Child sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Child sel: Max. PID nSigma TPC"}; + Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; + + // Resonances + FemtoDreamResoSelection resoCuts; + struct : ConfigurableGroup { + std::string prefix = std::string("Resonance"); + Configurable ConfThreshold{"ConfThreshold", true, "Enable threshold selection between TPC/TPCTOF"}; + + Configurable ConfResoInvMassLowLimit{"ConfResoInvMassLowLimit", 0.9, "Lower limit of the Reso invariant mass"}; // 1.011461 + Configurable ConfResoInvMassUpLimit{"ConfResoInvMassUpLimit", 1.15, "Upper limit of the Reso invariant mass"}; // 1.027461 + Configurable> ConfResoSign{"ConfResoSign", std::vector{-1., 1.}, "Reso sign selection"}; + + Configurable> ConfDaughterCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "ConfDaughter"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Reso selection: ")}; + Configurable> ConfDaughterPtMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "ConfDaughter"), std::vector{0.1, 0.15, 0.2}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Reso selection: ")}; + Configurable> ConfDaughterPtMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "ConfDaughter"), std::vector{5.0, 4.0}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Reso selection: ")}; + Configurable> ConfDaughterEtaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "ConfDaughter"), std::vector{0.8, 0.85, 0.9}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Reso selection: ")}; + Configurable> ConfDaughterTPCnClsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "ConfDaughter"), std::vector{75, 85, 100}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Reso selection: ")}; + Configurable> ConfDaughterTPCfClsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "ConfDaughter"), std::vector{0.7, 0.8, 0.9}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Reso selection: ")}; + Configurable> ConfDaughterTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "ConfDaughter"), std::vector{75, 85, 100}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Reso selection: ")}; + Configurable> ConfDaughterDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "ConfDaughter"), std::vector{0.2, 0.15, 0.1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Reso selection: ")}; + Configurable> ConfDaughterDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "ConfDaughter"), std::vector{0.2, 0.15, 0.1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Reso selection: ")}; + Configurable> ConfDaughterPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "ConfDaughter"), std::vector{3.0, 2.5, 2.0}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Reso selection: ")}; + // Configurable ConfDaughterMassUp{"ConfDaughterMassUp", 0.52, "Upper limit for the mass selection of the daughters"}; + // Configurable ConfDaughterMassLow{"ConfDaughterMassLow", 0.48, "Lower limit for the mass selection of the daughters"}; + Configurable> ConfDaughterPIDspecies{"ConfDaughterPIDspecies", std::vector{o2::track::PID::Kaon}, "Reso sel: Particles species for PID"}; + Configurable ConfDaughterPTPCThr{"ConfDaughterPTPCThr", 0.4, "p_T (GeV/c)Threshold for case distinction between TPC/TPCTOF"}; + } Resonance; + + /// \todo should we add filter on min value pT/eta of V0 and daughters? + /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && + (nabs(aod::v0data::y) < V0DecVtxMax.value) && + (nabs(aod::v0data::z) < V0DecVtxMax.value);*/ + // (aod::v0data::v0radius > V0TranRadV0Min.value); to be added, not working + // for now do not know why + + /// General options + struct : o2::framework::ConfigurableGroup { + Configurable ConfTrkMinChi2PerClusterTPC{"ConfTrkMinChi2PerClusterTPC", 0.f, "Lower limit for chi2 of TPC; currently for testing only"}; + Configurable ConfTrkMaxChi2PerClusterTPC{"ConfTrkMaxChi2PerClusterTPC", 1000.f, "Upper limit for chi2 of TPC; currently for testing only"}; + Configurable ConfTrkMaxChi2PerClusterITS{"ConfTrkMaxChi2PerClusterITS", 1000.0f, "Minimal track selection: max allowed chi2 per ITS cluster"}; // 36.0 is default + Configurable ConfTrkTPCRefit{"ConfTrkTPCRefit", false, "True: require TPC refit"}; + Configurable ConfTrkITSRefit{"ConfTrkITSRefit", false, "True: require ITS refit"}; + + } OptionTrackSpecialSelections; + + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry V0Registry{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ResoRegistry{"Reso", {}, OutputObjHandlingPolicy::AnalysisObject}; + + int mRunNumber; + float mMagField; + std::string zorroTriggerNames = ""; + Service ccdb; /// Accessing the CCDB + + void init(InitContext&) + { + if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false) { + LOGF(fatal, "Neither processData nor processMC enabled. Please choose one."); + } + if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true)) { + LOGF(fatal, + "Cannot enable more than one process switch at the same time. " + "Please choose one."); + } + + int CutBits = 8 * sizeof(o2::aod::femtodreamparticle::cutContainerType); + TrackRegistry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + TrackRegistry.add("AnalysisQA/Chi2ITSTPCperCluster", "; ITS_Chi2; TPC_Chi2", kTH2F, {{100, 0, 50}, {100, 0, 20}}); + TrackRegistry.add("AnalysisQA/RefitITSTPC", "; ITS_Refit; TPC_Refit", kTH2F, {{2, 0, 2}, {2, 0, 2}}); + TrackRegistry.add("AnalysisQA/getGenStatusCode", "; Bit; Entries", kTH1F, {{200, 0, 200}}); + TrackRegistry.add("AnalysisQA/getProcess", "; Bit; Entries", kTH1F, {{200, 0, 200}}); + TrackRegistry.add("AnalysisQA/Mother", "; Bit; Entries", kTH1F, {{4000, -4000, 4000}}); + TrackRegistry.add("AnalysisQA/Particle", "; Bit; Entries", kTH1F, {{4000, -4000, 4000}}); + V0Registry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + + ResoRegistry.add("AnalysisQA/Reso/InvMass", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMass_phi_selected", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.8, 1.5}}); + + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Pt", "Transverse momentum of all tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Eta", "Pseudorapidity of all tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Phi", "Azimuthal angle of all tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/DcaXY", "dcaXY of all tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter1/DcaZ", "dcaZ of all tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Pt", "Transverse momentum of all tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Eta", "Pseudorapidity of all tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Phi", "Azimuthal angle of all tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/DcaXY", "dcaXY of all tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter2/DcaZ", "dcaZ of all tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + + ResoRegistry.add("AnalysisQA/Reso/Pt_posdaughter_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Eta_posdaughter_selected", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Phi_posdaughter_selected", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/DCAxy_posdaughter_selected", "dcaXY of all processed tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/DCAz_posdaughter_selected", "dcaZ of all processed tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Eta_negdaughter_selected", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Phi_negdaughter_selected", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Pt_negdaughter_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/DCAxy_negdaughter_selected", "dcaXY of all processed tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/DCAz_negdaughter_selected", "dcaZ of all processed tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + + if (ConfEnableTriggerSelection) { + for (const std::string& triggerName : softwareTriggers::triggerNames) { + if (ConfTriggerSwitches->get("Switch", triggerName.c_str())) { + zorroTriggerNames += triggerName + ","; + } + } + zorroTriggerNames.pop_back(); + } + + colCuts.setCuts(ConfEvtZvtx.value, ConfEvtTriggerCheck.value, ConfEvtTriggerSel.value, ConfEvtOfflineCheck.value, ConfEvtAddOfflineCheck.value, ConfIsRun3.value); + colCuts.init(&qaRegistry); + + trackCuts.setSelection(Track.ConfTrkCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + trackCuts.setSelection(Track.ConfTrkPtmin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkPtmax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + trackCuts.setSelection(Track.ConfTrkEta, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkTPCnclsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCfCls, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCsCls, femtoDreamTrackSelection::kTPCsClsMax, femtoDreamSelection::kUpperLimit); + trackCuts.setSelection(Track.ConfTrkITSnclsMin, femtoDreamTrackSelection::kITSnClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkITSnclsIbMin, femtoDreamTrackSelection::kITSnClsIbMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setPIDSpecies(Track.ConfTrkPIDspecies); + trackCuts.setnSigmaPIDOffset(Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + trackCuts.init(&qaRegistry, &TrackRegistry); + + /// \todo fix how to pass array to setSelection, getRow() passing a + /// different type! + // v0Cuts.setSelection(ConfV0Selection->getRow(0), + // femtoDreamV0Selection::kDecVtxMax, femtoDreamSelection::kAbsUpperLimit); + if (ConfIsActivateV0) { + v0Cuts.setSelection(ConfV0Sign, femtoDreamV0Selection::kV0Sign, femtoDreamSelection::kEqual); + v0Cuts.setSelection(ConfV0PtMin, femtoDreamV0Selection::kV0pTMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0PtMax, femtoDreamV0Selection::kV0pTMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0EtaMax, femtoDreamV0Selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setSelection(ConfV0DCADaughMax, femtoDreamV0Selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0CPAMin, femtoDreamV0Selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMin, femtoDreamV0Selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMax, femtoDreamV0Selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0DecVtxMax, femtoDreamV0Selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kPosTrack, ConfChildPIDspecies); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kNegTrack, ConfChildPIDspecies); + v0Cuts.init(&qaRegistry, &V0Registry); + v0Cuts.setInvMassLimits(ConfV0InvMassLowLimit, ConfV0InvMassUpLimit); + + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfTrkRejectNotPropagated); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kNegTrack, ConfTrkRejectNotPropagated); + + v0Cuts.setnSigmaPIDOffsetTPC(Track.ConfTrkPIDnSigmaOffsetTPC); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kPosTrack, Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kNegTrack, Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + + if (ConfV0RejectKaons) { + v0Cuts.setKaonInvMassLimits(ConfV0InvKaonMassLowLimit, ConfV0InvKaonMassUpLimit); + } + } + + if (ConfIsActivateReso.value) { + // resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh,Resonance.ConfDaughterCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPtMax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPtMin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCfClsMin, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + // resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh,Resonance.ConfDaughterCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPtMax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPtMin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCfClsMin, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + resoCuts.init(&qaRegistry, &V0Registry); + + resoCuts.assign(Resonance.ConfDaughterPTPCThr); // assigns configurable value to class member + resoCuts.setDaughterPIDSpecies(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPIDspecies); + resoCuts.setDaughterPIDSpecies(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPIDspecies); + resoCuts.setDaughternSigmaPIDOffset(femtoDreamResoSelection::kPosdaugh, 0.f, 0.f); + resoCuts.setDaughternSigmaPIDOffset(femtoDreamResoSelection::kNegdaugh, 0.f, 0.f); + + // resoCuts.init<>(); + } + + mRunNumber = 0; + mMagField = 0.0; + /// Initializing CCDB + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + } + + /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T + void initCCDB_Mag_Trig(aod::BCsWithTimestamps::iterator bc) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + // get magnetic field for run + if (mRunNumber == bc.runNumber()) + return; + auto timestamp = bc.timestamp(); + float output = -999; + + if (ConfIsRun3 && !ConfIsForceGRP) { + static o2::parameters::GRPMagField* grpo = nullptr; + grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return; + } + LOGF(info, "Retrieved GRP for timestamp %llu with L3 ", timestamp, grpo->getL3Current()); + // taken from GRP onject definition of getNominalL3Field; update later to something smarter (mNominalL3Field = std::lround(5.f * mL3Current / 30000.f);) + auto NominalL3Field = std::lround(5.f * grpo->getL3Current() / 30000.f); + output = 0.1 * (NominalL3Field); + + } else { + + static o2::parameters::GRPObject* grpo = nullptr; + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + output = 0.1 * (grpo->getNominalL3Field()); + } + mMagField = output; + mRunNumber = bc.runNumber(); + + // Init for zorro to get trigger flags + if (ConfEnableTriggerSelection) { + zorro.setCCDBpath(ConfBaseCCDBPathForTriggers); + zorro.initCCDB(ccdb.service, mRunNumber, timestamp, zorroTriggerNames); + } + } + + template + void fillDebugParticle(ParticleType const& particle) + { + if constexpr (isTrackOrV0) { + if constexpr (hasItsPid) { + outputDebugParts(particle.sign(), + (uint8_t)particle.tpcNClsFound(), + particle.tpcNClsFindable(), + (uint8_t)particle.tpcNClsCrossedRows(), + particle.tpcNClsShared(), + particle.tpcInnerParam(), + particle.itsNCls(), + particle.itsNClsInnerBarrel(), + particle.dcaXY(), + particle.dcaZ(), + particle.tpcSignal(), + particle.tpcNSigmaEl(), + particle.tpcNSigmaPi(), + particle.tpcNSigmaKa(), + particle.tpcNSigmaPr(), + particle.tpcNSigmaDe(), + particle.tpcNSigmaTr(), + particle.tpcNSigmaHe(), + particle.tofNSigmaEl(), + particle.tofNSigmaPi(), + particle.tofNSigmaKa(), + particle.tofNSigmaPr(), + particle.tofNSigmaDe(), + particle.tofNSigmaTr(), + particle.tofNSigmaHe(), + o2::analysis::femtoDream::itsSignal(particle), + particle.itsNSigmaEl(), + particle.itsNSigmaPi(), + particle.itsNSigmaKa(), + particle.itsNSigmaPr(), + particle.itsNSigmaDe(), + particle.itsNSigmaTr(), + particle.itsNSigmaHe(), + -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999.); + } else { + outputDebugParts(particle.sign(), + (uint8_t)particle.tpcNClsFound(), + particle.tpcNClsFindable(), + (uint8_t)particle.tpcNClsCrossedRows(), + particle.tpcNClsShared(), + particle.tpcInnerParam(), + particle.itsNCls(), + particle.itsNClsInnerBarrel(), + particle.dcaXY(), + particle.dcaZ(), + particle.tpcSignal(), + particle.tpcNSigmaEl(), + particle.tpcNSigmaPi(), + particle.tpcNSigmaKa(), + particle.tpcNSigmaPr(), + particle.tpcNSigmaDe(), + particle.tpcNSigmaTr(), + particle.tpcNSigmaHe(), + particle.tofNSigmaEl(), + particle.tofNSigmaPi(), + particle.tofNSigmaKa(), + particle.tofNSigmaPr(), + particle.tofNSigmaDe(), + particle.tofNSigmaTr(), + particle.tofNSigmaHe(), + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999.); + } + } else if constexpr (isReso) { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., -999., // for the moment + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999.); + + } else { + outputDebugParts(-999., // sign + -999., -999., -999., -999., -999., -999., -999., -999., -999., // track properties (DCA, NCls, crossed rows, etc.) + -999., -999., -999., -999., -999., -999., -999., -999., // TPC PID (TPC signal + particle hypothesis) + -999., -999., -999., -999., -999., -999., -999., // TOF PID + -999., -999., -999., -999., -999., -999., -999., -999., // ITS PID + particle.dcaV0daughters(), + particle.v0radius(), + particle.x(), + particle.y(), + particle.z(), + particle.mK0Short(), + -999., -999., -999., -999., -999., -999., -999.); // Cascade properties + } + } + + template + void fillMCParticle(CollisionType const& col, ParticleType const& particle, o2::aod::femtodreamparticle::ParticleType fdparttype) + { + if (particle.has_mcParticle()) { + // get corresponding MC particle and its info + auto particleMC = particle.mcParticle(); + auto pdgCode = particleMC.pdgCode(); + TrackRegistry.fill(HIST("AnalysisQA/Particle"), pdgCode); + int particleOrigin = 99; + int pdgCodeMother = -1; + // get list of mothers, but it could be empty (for example in case of injected light nuclei) + auto motherparticlesMC = particleMC.template mothers_as(); + // check pdg code + TrackRegistry.fill(HIST("AnalysisQA/getGenStatusCode"), particleMC.getGenStatusCode()); + TrackRegistry.fill(HIST("AnalysisQA/getProcess"), particleMC.getProcess()); + // if this fails, the particle is a fake + if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { + // check first if particle is from pile up + // check if the collision associated with the particle is the same as the analyzed collision by checking their Ids + if ((col.has_mcCollision() && (particleMC.mcCollisionId() != col.mcCollisionId())) || !col.has_mcCollision()) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kWrongCollision; + // check if particle is primary + } else if (particleMC.isPhysicalPrimary()) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; + // check if particle is secondary + // particle is from a decay -> getProcess() == 4 + // particle is generated during transport -> getGenStatusCode() == -1 + // list of mothers is not empty + } else if (particleMC.getProcess() == 4 && particleMC.getGenStatusCode() == -1 && !motherparticlesMC.empty()) { + // get direct mother + auto motherparticleMC = motherparticlesMC.front(); + pdgCodeMother = motherparticleMC.pdgCode(); + TrackRegistry.fill(HIST("AnalysisQA/Mother"), pdgCodeMother); + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); + // check if particle is material + // particle is from inelastic hadronic interaction -> getProcess() == 23 + // particle is generated during transport -> getGenStatusCode() == -1 + } else if (particleMC.getProcess() == 23 && particleMC.getGenStatusCode() == -1) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kMaterial; + // cross check to see if we missed a case + } else { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kElse; + } + // if pdg code is wrong, particle is fake + } else { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kFake; + } + + outputPartsMC(particleOrigin, pdgCode, particleMC.pt(), particleMC.eta(), particleMC.phi()); + outputPartsMCLabels(outputPartsMC.lastIndex()); + if (ConfIsDebug) { + outputPartsExtMCLabels(outputPartsMC.lastIndex()); + outputDebugPartsMC(pdgCodeMother); + } + } else { + outputPartsMCLabels(-1); + if (ConfIsDebug) { + outputPartsExtMCLabels(-1); + } + } + } + + template + void fillMCCollision(CollisionType const& col) + { + if (col.has_mcCollision()) { + auto genMCcol = col.template mcCollision_as(); + outputMCCollision(genMCcol.multMCNParticlesEta08()); + outputCollsMCLabels(outputMCCollision.lastIndex()); + } else { + outputCollsMCLabels(-1); + } + } + template + void fillCollisionsAndTracksAndV0(CollisionType const& col, TrackType const& tracks, TrackTypeWithItsPid const& tracksWithItsPid, V0Type const& fullV0s) + { + // If triggering is enabled, select only events which were triggered wit our triggers + if (ConfEnableTriggerSelection) { + bool zorroSelected = zorro.isSelected(col.template bc_as().globalBC()); /// check if event was selected by triggers of interest + if (!zorroSelected) { + return; + } + } + + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + float mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + if constexpr (useCentrality) { + if constexpr (analysePbPb) { + mult = col.centFT0C(); + } else { + mult = col.centFT0M(); + } + } else { + mult = 0; + } + multNtr = col.multNTracksPV(); + } else { + mult = 1; // multiplicity percentile is know in Run 2 + multNtr = col.multTracklets(); + } + + colCuts.fillQA(col, mult); + + // check whether the basic event selection criteria are fulfilled + // that included checking if there is at least on usable track or V0 + if (!colCuts.isSelectedCollision(col)) { + return; + } + if (ConfIsActivateV0.value) { + if (colCuts.isEmptyCollision(col, tracks, trackCuts) && colCuts.isEmptyCollision(col, fullV0s, v0Cuts, tracks)) { + return; + } + } else { + if (colCuts.isEmptyCollision(col, tracks, trackCuts)) { + return; + } + } + + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + if constexpr (isMC) { + fillMCCollision(col); + } + + std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + + for (auto& track : tracksWithItsPid) { + + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track + trackCuts.fillQA(track); + + if (track.tpcChi2NCl() < OptionTrackSpecialSelections.ConfTrkMinChi2PerClusterTPC || track.tpcChi2NCl() > OptionTrackSpecialSelections.ConfTrkMaxChi2PerClusterTPC) { + continue; + } + if (track.itsChi2NCl() > OptionTrackSpecialSelections.ConfTrkMaxChi2PerClusterITS) { + continue; + } + if ((OptionTrackSpecialSelections.ConfTrkTPCRefit && !track.hasTPC()) || (OptionTrackSpecialSelections.ConfTrkITSRefit && !track.hasITS())) { + continue; + } + + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + + TrackRegistry.fill(HIST("AnalysisQA/Chi2ITSTPCperCluster"), track.itsChi2NCl(), track.tpcChi2NCl()); + TrackRegistry.fill(HIST("AnalysisQA/RefitITSTPC"), track.hasITS(), track.hasTPC()); + + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + std::array cutContainer; + cutContainer = trackCuts.getCutContainer(track, track.pt(), track.eta(), sqrtf(powf(track.dcaXY(), 2.f) + powf(track.dcaZ(), 2.f))); + + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtodreamparticle::ParticleType::kTrack, + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); + tmpIDtrack.push_back(track.globalIndex()); + if (ConfIsDebug.value) { + fillDebugParticle(track); + } + + if constexpr (isMC) { + fillMCParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); + } + } + + if (ConfIsActivateV0.value) { + + for (auto& v0 : fullV0s) { + + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + ///\tocheck funnily enough if we apply the filter the + /// sign of Pos and Neg track is always negative + // const auto dcaXYpos = postrack.dcaXY(); + // const auto dcaZpos = postrack.dcaZ(); + // const auto dcapos = std::sqrt(pow(dcaXYpos, 2.) + pow(dcaZpos, 2.)); + v0Cuts.fillLambdaQA(col, v0, postrack, negtrack); + + if (!v0Cuts.isSelectedMinimal(col, v0, postrack, negtrack)) { + continue; + } + + // if (ConfRejectITSHitandTOFMissing) { + // Uncomment only when TOF timing is solved + // bool itsHit = o2PhysicsTrackSelection->IsSelected(postrack, + // TrackSelection::TrackCuts::kITSHits); bool itsHit = + // o2PhysicsTrackSelection->IsSelected(negtrack, + // TrackSelection::TrackCuts::kITSHits); + // } + + v0Cuts.fillQA(col, v0, postrack, negtrack); ///\todo fill QA also for daughters + auto cutContainerV0 = v0Cuts.getCutContainer(col, v0, postrack, negtrack); + + int postrackID = v0.posTrackId(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + v0.positivept(), v0.positiveeta(), v0.positivephi(), + aod::femtodreamparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kPosPID), + postrack.dcaXY(), + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(col, postrack, o2::aod::femtodreamparticle::ParticleType::kV0Child); + } + int negtrackID = v0.negTrackId(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + v0.negativept(), + v0.negativeeta(), + v0.negativephi(), + aod::femtodreamparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kNegPID), + negtrack.dcaXY(), + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(col, negtrack, o2::aod::femtodreamparticle::ParticleType::kV0Child); + } + std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), + v0.pt(), + v0.eta(), + v0.phi(), + aod::femtodreamparticle::ParticleType::kV0, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kV0), + 0, + v0.v0cosPA(), + indexChildID, + v0.mLambda(), + v0.mAntiLambda()); + if (ConfIsDebug.value) { + fillDebugParticle(postrack); // QA for positive daughter + fillDebugParticle(negtrack); // QA for negative daughter + fillDebugParticle(v0); // QA for v0 + } + if constexpr (isMC) { + fillMCParticle(col, v0, o2::aod::femtodreamparticle::ParticleType::kV0); + } + } + } + + if (ConfIsActivatePhi.value) { + resoCuts.updateMembersMinimal(); + + auto SlicePosdaugh = daughter1.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); // o2::framework defined in AnalysisHelper.h + auto SliceNegdaugh = daughter2.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + + for (auto& track1 : SlicePosdaugh) { + + if (!resoCuts.DaughterSelection1(track1, Resonance.ConfThreshold.value)) + continue; + + for (auto& track2 : SliceNegdaugh) { + if (!resoCuts.DaughterSelection2(track2, Resonance.ConfThreshold.value)) + continue; + + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Pt"), track1.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Pt"), track2.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Eta"), track1.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Eta"), track2.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/DcaXY"), track1.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/DcaXY"), track2.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/DcaZ"), track1.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/DcaZ"), track2.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Phi"), track1.phi()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Phi"), track2.phi()); + + ROOT::Math::PtEtaPhiMVector tempD1(track1.pt(), track1.eta(), track1.phi(), o2::constants::physics::MassKPlus); + ROOT::Math::PtEtaPhiMVector tempD2(track2.pt(), track2.eta(), track2.phi(), o2::constants::physics::MassKMinus); + + ROOT::Math::PtEtaPhiMVector tempPhi = tempD1 + tempD2; + + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass"), tempPhi.M()); + + if (!(tempPhi.M() > Resonance.ConfResoInvMassLowLimit.value && tempPhi.M() < Resonance.ConfResoInvMassUpLimit.value)) { + continue; // if selection is not fullfilled jump the pair + } + + resoCuts.fillQA(track1, track2); + + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass_phi_selected"), tempPhi.M()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Pt_posdaughter_selected"), track1.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Pt_negdaughter_selected"), track2.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Eta_posdaughter_selected"), track1.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Eta_negdaughter_selected"), track2.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAxy_posdaughter_selected"), track1.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAxy_negdaughter_selected"), track2.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAz_posdaughter_selected"), track1.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAz_negdaughter_selected"), track2.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Phi_posdaughter_selected"), track1.phi()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Phi_negdaughter_selected"), track2.phi()); + + auto Type = resoCuts.getType(track1, track2); // kPhiPosdaughTPC_NegdaughTPC + // kPhiPosdaughTPC_NegdaughTOF + // kPhiPosdaughTOF_NegdaughTPC + // kPhiPosdaughTOF_NegdaughTOF as possible output + + auto Bitmask = resoCuts.getCutContainer(track1, track2, 1.0f); + + // fill FDParticles + int postrkId = track1.globalIndex(); + int RowOfPosTrack = -1; + RowOfPosTrack = getRowDaughters(postrkId, tmpIDtrack); + + childIDs[0] = RowOfPosTrack; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), track1.pt(), track1.eta(), track1.phi(), aod::femtodreamparticle::ParticleType::kResoChild, Bitmask[1], Bitmask[2], track1.dcaXY(), childIDs, tempD1.M(), tempD2.M()); + const int rowPosTrk = outputParts.lastIndex(); + + int negtrkId = track2.globalIndex(); + int RowOfNegTrack = -1; + RowOfNegTrack = getRowDaughters(negtrkId, tmpIDtrack); + + childIDs[0] = 0; + childIDs[1] = RowOfNegTrack; + outputParts(outputCollision.lastIndex(), track2.pt(), track2.eta(), track2.phi(), aod::femtodreamparticle::ParticleType::kResoChild, Bitmask[3], Bitmask[4], track2.dcaXY(), childIDs, tempD2.M(), tempD1.M()); + const int rowNegTrk = outputParts.lastIndex(); + + // Phi + std::vector IndexChildIds = {rowPosTrk, rowNegTrk}; + outputParts(outputCollision.lastIndex(), tempPhi.pt(), tempPhi.eta(), tempPhi.phi(), Type, Bitmask[0], Bitmask[2], -999.f, IndexChildIds, tempPhi.M(), tempPhi.M()); + + if (ConfIsDebug.value) { + fillDebugParticle(track1); // QA for positive daughter + fillDebugParticle(track2); + fillDebugParticle(tempPhi); + } + } + } + } + } + + void + processData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processData, + "Provide experimental data", true); + + void + processData_noCentrality(aod::FemtoFullCollision_noCent const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processData_noCentrality, + "Provide experimental data without centrality information", false); + + void processData_CentPbPb(aod::FemtoFullCollision_CentPbPb const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processData_CentPbPb, + "Provide experimental data with centrality information for PbPb collisions", false); + + void processMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processMC, "Provide MC data", false); + + void processMC_noCentrality(aod::FemtoFullCollision_noCent_MC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processMC_noCentrality, "Provide MC data without requiring a centrality calibration", false); + + void processMC_CentPbPb(aod::FemtoFullCollisionMC_CentPbPb const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskReso, processMC_CentPbPb, "Provide MC data with centrality information for PbPb collisions", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskResoKshort.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskResoKshort.cxx new file mode 100644 index 00000000000..f093a8c3fe9 --- /dev/null +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskResoKshort.cxx @@ -0,0 +1,1111 @@ +// Copyright 2019-2022 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 femtoDreamProducerTaskReso.cxx +/// \brief Tasks that produces the track tables used for the pairing +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#include "FairLogger.h" // delete after debugging + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamResoSelectionK0Short.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include "PWGCF/FemtoDream/Core/femtoDreamV0SelectionK0Short.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" + +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include // delete after debugging + +#include "Math/Vector4D.h" +#include "TMath.h" + +#include + +#include // delete after debugging +#include // delete in the end +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; +using namespace o2::analysis::femtoDream; + +namespace o2::aod +{ +using FemtoFullCollision = soa::Join::iterator; +using FemtoFullCollision_noCent = soa::Join::iterator; +using FemtoFullCollision_CentPbPb = soa::Join::iterator; +using FemtoFullCollisionMC = soa::Join::iterator; +using FemtoFullCollision_noCent_MC = soa::Join::iterator; +using FemtoFullCollisionMC_CentPbPb = soa::Join::iterator; +using FemtoFullMCgenCollisions = soa::Join; +using FemtoFullMCgenCollision = FemtoFullMCgenCollisions::iterator; + +using FemtoFullTracks = + soa::Join; + +} // namespace o2::aod + +namespace softwareTriggers +{ +static const int nTriggers = 6; +static const std::vector triggerNames{"fPPP", "fPPL", "fPLL", "fLLL", "fPD", "fLD"}; +static const float triggerSwitches[1][nTriggers]{ + {0, 0, 0, 0, 0, 0}}; +} // namespace softwareTriggers + +template +int getRowDaughters(int daughID, T const& vecID) +{ + int rowInPrimaryTrackTableDaugh = -1; + for (size_t i = 0; i < vecID.size(); i++) { + if (vecID.at(i) == daughID) { + rowInPrimaryTrackTableDaugh = i; + break; + } + } + return rowInPrimaryTrackTableDaugh; +} + +struct femtoDreamProducerTaskResoKshort { + + SliceCache cache; // o2::framework, included in ASoAHelpers.h + Preslice perCol = aod::track::collisionId; // o2::framework included in ASoAHelpers.h + Partition daughter1 = aod::track::signed1Pt > 0.f; // o2::framework included in AnalysisHelper.h + Partition daughter2 = aod::track::signed1Pt < 0.f; // o2::framework included in AnalysisHelper.h + + Zorro zorro; + + Produces outputCollision; + Produces outputMCCollision; + Produces outputCollsMCLabels; + Produces outputParts; + Produces outputPartsMC; + Produces outputDebugParts; + Produces outputPartsMCLabels; + Produces outputDebugPartsMC; + Produces outputPartsExtMCLabels; + + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable Debug tables"}; + Configurable ConfUseItsPid{"ConfUseItsPid", false, "Enable Debug tables"}; + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; // true? + Configurable ConfIsForceGRP{"ConfIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; + /// Event cuts + FemtoDreamCollisionSelection colCuts; + // Event cuts - Triggers + Configurable ConfEnableTriggerSelection{"ConfEnableTriggerSelection", false, "Should the trigger selection be enabled for collisions?"}; + Configurable> ConfTriggerSwitches{ + "ConfTriggerSwitches", + {softwareTriggers::triggerSwitches[0], 1, softwareTriggers::nTriggers, std::vector{"Switch"}, softwareTriggers::triggerNames}, + "Turn on which trigger should be checked for recorded events to pass selection"}; + Configurable ConfBaseCCDBPathForTriggers{"ConfBaseCCDBPathForTriggers", "Users/m/mpuccio/EventFiltering/OTS/Chunked/", "Provide ccdb path for trigger table; default - trigger coordination"}; + + // Event cuts - usual selection criteria + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", true, "Evt sel: check for trigger"}; + Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", kINT7, "Evt sel: trigger"}; + Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable ConfEvtAddOfflineCheck{"ConfEvtAddOfflineCheck", false, "Evt sel: additional checks for offline selection (not part of sel8 yet)"}; + Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtodream tables"}; + Configurable ConfIsActivateReso{"ConfIsActivateReso", true, "Activate filling of sl Resonances into femtodream tables"}; + Configurable ConfIsActivatePhi{"ConfIsActivatePhi", true, "Activates cuts on Phi's and fills tables"}; + + Configurable ConfTrkRejectNotPropagated{"ConfTrkRejectNotPropagated", false, "True: reject not propagated tracks"}; + // Configurable ConfRejectITSHitandTOFMissing{ "ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; + Configurable ConfTrkPDGCode{"ConfTrkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; + FemtoDreamTrackSelection trackCuts; + struct : ConfigurableGroup { + std::string prefix = std::string("Track"); + Configurable> ConfTrkCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "ConfTrk"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Track selection: ")}; + Configurable> ConfTrkPtmin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "ConfTrk"), std::vector{0.1f, 0.15f, 0.2f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Track selection: ")}; + Configurable> ConfTrkPtmax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "ConfTrk"), std::vector{4.4f, 4.6f, 4.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Track selection: ")}; + Configurable> ConfTrkEta{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "ConfTrk"), std::vector{0.8f, 0.85f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Track selection: ")}; + Configurable> ConfTrkTPCnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "ConfTrk"), std::vector{80.f, 90.f, 100.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCfCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "ConfTrk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "ConfTrk"), std::vector{70.f, 60.f, 80.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Track selection: ")}; + Configurable> ConfTrkTPCsCls{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCsClsMax, "ConfTrk"), std::vector{0.1f, 160.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCsClsMax, "Track selection: ")}; + Configurable> ConfTrkITSnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsMin, "ConfTrk"), std::vector{-1.f, 2.f, 4.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsMin, "Track selection: ")}; + Configurable> ConfTrkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "ConfTrk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; + Configurable> ConfTrkDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.2f, 0.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Track selection: ")}; + Configurable> ConfTrkDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f, 0.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Track selection: ")}; + Configurable> ConfTrkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "ConfTrk"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; + Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; // set to zero for run3 or so + Configurable ConfTrkPIDnSigmaOffsetTOF{"ConfTrkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; + Configurable> ConfTrkPIDspecies{"ConfTrkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + // missing DCA configurable?? because implemented in TrackSelection.h + } Track; + + FemtoDreamV0Selection v0Cuts; + Configurable> ConfV0Sign{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0Sign, "V0 selection: ")}; + Configurable> ConfV0PtMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0pTMin, "V0 selection: ")}; + Configurable> ConfV0PtMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0pTMax, "V0 selection: ")}; + Configurable> ConfV0EtaMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0etaMax, "ConfV0"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0etaMax, "V0 selection: ")}; + Configurable> ConfV0DCADaughMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0DCADaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0DCADaughMax, "V0 selection: ")}; + Configurable> ConfV0CPAMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0CPAMin, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0CPAMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMin{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0TranRadMin, "ConfV0"), std::vector{0.2f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0TranRadMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0TranRadMax, "ConfV0"), std::vector{100.f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0TranRadMax, "V0 selection: ")}; + Configurable> ConfV0DecVtxMax{FemtoDreamV0Selection::getSelectionName(femtoDreamV0Selection::kV0DecVtxMax, "ConfV0"), std::vector{100.f}, FemtoDreamV0Selection::getSelectionHelper(femtoDreamV0Selection::kV0DecVtxMax, "V0 selection: ")}; + + Configurable ConfV0InvMassLowLimit{"ConfV0InvV0MassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; + Configurable ConfV0InvMassUpLimit{"ConfV0InvV0MassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; + Configurable ConfV0RejectKaons{"ConfV0RejectKaons", false, "Switch to reject kaons"}; + Configurable ConfV0RejectLambdas{"ConfV0RejectLambdas", false, "Switch to reject lambdas (if mother is kaon)"}; + Configurable ConfV0InvKaonMassLowLimit{"ConfV0InvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; + Configurable ConfV0InvKaonMassUpLimit{"ConfV0InvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; + Configurable ConfV0MotherIsLambda{"ConfV0MotherIsLambda", true, "True: Lambda, False: K0Short"}; + + Configurable> ConfChildCharge{"ConfChildSign", std::vector{-1, 1}, "V0 Child sel: Charge"}; + Configurable> ConfChildEtaMax{"ConfChildEtaMax", std::vector{0.8f}, "V0 Child sel: max eta"}; + Configurable> ConfChildTPCnClsMin{"ConfChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "V0 Child sel: Min. nCls TPC"}; + Configurable> ConfChildDCAMin{"ConfChildDCAMin", std::vector{0.05f, 0.06f}, "V0 Child sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Child sel: Max. PID nSigma TPC"}; + Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; + + // Resonances + FemtoDreamResoSelection resoCuts; + struct : ConfigurableGroup { + std::string prefix = std::string("Resonance"); + Configurable ConfThreshold{"ConfThreshold", true, "Enable threshold selection between TPC/TPCTOF"}; + + Configurable ConfResoInvMassLowLimit{"ConfResoInvMassLowLimit", 0.9, "Lower limit of the Reso invariant mass"}; // 1.011461 + Configurable ConfResoInvMassUpLimit{"ConfResoInvMassUpLimit", 1.15, "Upper limit of the Reso invariant mass"}; // 1.027461 + Configurable> ConfResoSign{"ConfResoSign", std::vector{-1., 1.}, "Reso Sign selection"}; + Configurable ConfResoMotherID{"ConfResoMotherID", static_cast(femtoDreamResoSelection::kPhi), "ResoID of Mother [0: Phi, 1: KStar]"}; + + Configurable> ConfDaughterCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "ConfDaughter"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Reso selection: ")}; + Configurable> ConfDaughterPtMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMin, "ConfDaughter"), std::vector{0.1, 0.15, 0.2}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "Reso selection: ")}; + Configurable> ConfDaughterPtMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kpTMax, "ConfDaughter"), std::vector{5.0, 4.0}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMax, "Reso selection: ")}; + Configurable> ConfDaughterEtaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "ConfDaughter"), std::vector{0.8, 0.85, 0.9}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Reso selection: ")}; + Configurable> ConfDaughterTPCnClsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCnClsMin, "ConfDaughter"), std::vector{75, 85, 100}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCnClsMin, "Reso selection: ")}; + Configurable> ConfDaughterTPCfClsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCfClsMin, "ConfDaughter"), std::vector{0.7, 0.8, 0.9}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCfClsMin, "Reso selection: ")}; + Configurable> ConfDaughterTPCcRowsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kTPCcRowsMin, "ConfDaughter"), std::vector{75, 85, 100}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kTPCcRowsMin, "Reso selection: ")}; + Configurable> ConfDaughterDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "ConfDaughter"), std::vector{0.2, 0.15, 0.1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Reso selection: ")}; + Configurable> ConfDaughterDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "ConfDaughter"), std::vector{0.2, 0.15, 0.1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Reso selection: ")}; + Configurable> ConfDaughterPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "ConfDaughter"), std::vector{3.0, 2.5, 2.0}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Reso selection: ")}; + // Configurable ConfResoMassUp{"ConfResoMassUp", 0.52, "Upper limit for the mass selection of the daughters"}; + // Configurable ConfResoMassLow{"ConfResoMassLow", 0.48, "Lower limit for the mass selection of the daughters"}; + Configurable> ConfDaughterPIDspecies{"ConfDaughterPIDspecies", std::vector{o2::track::PID::Kaon}, "Reso Daughter sel: Particles species for PID"}; + Configurable ConfDaughterPTPCThr{"ConfResoPTPCThr", 0.5, "p_T (GeV/c)Threshold for case distinction between TPC/TPCTOF"}; + } Resonance; + + /// \todo should we add filter on min value pT/eta of V0 and daughters? + /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && + (nabs(aod::v0data::y) < V0DecVtxMax.value) && + (nabs(aod::v0data::z) < V0DecVtxMax.value);*/ + // (aod::v0data::v0radius > V0TranRadV0Min.value); to be added, not working + // for now do not know why + + /// General options + struct : o2::framework::ConfigurableGroup { + Configurable ConfTrkMinChi2PerClusterTPC{"ConfTrkMinChi2PerClusterTPC", 0.f, "Lower limit for chi2 of TPC; currently for testing only"}; + Configurable ConfTrkMaxChi2PerClusterTPC{"ConfTrkMaxChi2PerClusterTPC", 1000.f, "Upper limit for chi2 of TPC; currently for testing only"}; + Configurable ConfTrkMaxChi2PerClusterITS{"ConfTrkMaxChi2PerClusterITS", 1000.0f, "Minimal track selection: max allowed chi2 per ITS cluster"}; // 36.0 is default + Configurable ConfTrkTPCRefit{"ConfTrkTPCRefit", false, "True: require TPC refit"}; + Configurable ConfTrkITSRefit{"ConfTrkITSRefit", false, "True: require ITS refit"}; + + } OptionTrackSpecialSelections; + + struct : o2::framework::ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } rctCut; + + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry V0Registry{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ResoRegistry{"Reso", {}, OutputObjHandlingPolicy::AnalysisObject}; + + int mRunNumber; + float mMagField; + std::string zorroTriggerNames = ""; + Service ccdb; /// Accessing the CCDB + RCTFlagsChecker rctChecker; + + void init(InitContext&) + { + if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false) { + LOGF(fatal, "Neither processData nor processMC enabled. Please choose one."); + } + if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true)) { + LOGF(fatal, + "Cannot enable more than one process switch at the same time. " + "Please choose one."); + } + + int CutBits = 8 * sizeof(o2::aod::femtodreamparticle::cutContainerType); + TrackRegistry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + TrackRegistry.add("AnalysisQA/Chi2ITSTPCperCluster", "; ITS_Chi2; TPC_Chi2", kTH2F, {{100, 0, 50}, {100, 0, 20}}); + TrackRegistry.add("AnalysisQA/RefitITSTPC", "; ITS_Refit; TPC_Refit", kTH2F, {{2, 0, 2}, {2, 0, 2}}); + TrackRegistry.add("AnalysisQA/getGenStatusCode", "; Bit; Entries", kTH1F, {{200, 0, 200}}); + TrackRegistry.add("AnalysisQA/getProcess", "; Bit; Entries", kTH1F, {{200, 0, 200}}); + TrackRegistry.add("AnalysisQA/Mother", "; Bit; Entries", kTH1F, {{4000, -4000, 4000}}); + TrackRegistry.add("AnalysisQA/Particle", "; Bit; Entries", kTH1F, {{4000, -4000, 4000}}); + V0Registry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + + ResoRegistry.add("AnalysisQA/Reso/InvMass", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.65, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMassAnti", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.65, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMass_phi_selected", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.65, 1.5}}); + ResoRegistry.add("AnalysisQA/Reso/InvMassAnti_phi_selected", "Invariant mass V0s;M_{KK};Entries", HistType::kTH1F, {{7000, 0.65, 1.5}}); + + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Pt", "Transverse momentum of all tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Eta", "Pseudorapidity of all tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/Phi", "Azimuthal angle of all tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter1/DcaXY", "dcaXY of all tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter1/DcaZ", "dcaZ of all tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Pt", "Transverse momentum of all tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Eta", "Pseudorapidity of all tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/Phi", "Azimuthal angle of all tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Daughter2/DcaXY", "dcaXY of all tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Daughter2/DcaZ", "dcaZ of all tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + + ResoRegistry.add("AnalysisQA/Reso/Pt_posdaughter_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/Eta_posdaughter_selected", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Phi_posdaughter_selected", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/DCAxy_posdaughter_selected", "dcaXY of all processed tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/DCAz_posdaughter_selected", "dcaZ of all processed tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/Eta_negdaughter_selected", "Pseudorapidity of all processed tracks;#eta;Entries", HistType::kTH1F, {{1000, -2, 2}}); + ResoRegistry.add("AnalysisQA/Reso/Phi_negdaughter_selected", "Azimuthal angle of all processed tracks;#phi;Entries", HistType::kTH1F, {{720, 0, TMath::TwoPi()}}); + ResoRegistry.add("AnalysisQA/Reso/Pt_negdaughter_selected", "Transverse momentum of all processed tracks;p_{T} (GeV/c);Entries", HistType::kTH1F, {{1000, 0, 10}}); + ResoRegistry.add("AnalysisQA/Reso/DCAxy_negdaughter_selected", "dcaXY of all processed tracks;d_{XY} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + ResoRegistry.add("AnalysisQA/Reso/DCAz_negdaughter_selected", "dcaZ of all processed tracks;d_{Z} (cm);Entries", HistType::kTH1F, {{1000, 0, 1}}); // check if cm is correct here + + if (ConfEnableTriggerSelection) { + for (const std::string& triggerName : softwareTriggers::triggerNames) { + if (ConfTriggerSwitches->get("Switch", triggerName.c_str())) { + zorroTriggerNames += triggerName + ","; + } + } + zorroTriggerNames.pop_back(); + } + + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, false, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + colCuts.setCuts(ConfEvtZvtx.value, ConfEvtTriggerCheck.value, ConfEvtTriggerSel.value, ConfEvtOfflineCheck.value, ConfEvtAddOfflineCheck.value, ConfIsRun3.value); + colCuts.init(&qaRegistry); + + trackCuts.setSelection(Track.ConfTrkCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + trackCuts.setSelection(Track.ConfTrkPtmin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkPtmax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + trackCuts.setSelection(Track.ConfTrkEta, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkTPCnclsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCfCls, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkTPCsCls, femtoDreamTrackSelection::kTPCsClsMax, femtoDreamSelection::kUpperLimit); + trackCuts.setSelection(Track.ConfTrkITSnclsMin, femtoDreamTrackSelection::kITSnClsMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkITSnclsIbMin, femtoDreamTrackSelection::kITSnClsIbMin, femtoDreamSelection::kLowerLimit); + trackCuts.setSelection(Track.ConfTrkDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setSelection(Track.ConfTrkPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + trackCuts.setPIDSpecies(Track.ConfTrkPIDspecies); + trackCuts.setnSigmaPIDOffset(Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + trackCuts.init(&qaRegistry, &TrackRegistry); + + /// \todo fix how to pass array to setSelection, getRow() passing a + /// different type! + // v0Cuts.setSelection(ConfV0Selection->getRow(0), + // femtoDreamV0Selection::kDecVtxMax, femtoDreamSelection::kAbsUpperLimit); + if (ConfIsActivateV0) { + v0Cuts.setSelection(ConfV0Sign, femtoDreamV0Selection::kV0Sign, femtoDreamSelection::kEqual); + v0Cuts.setSelection(ConfV0PtMin, femtoDreamV0Selection::kV0pTMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0PtMax, femtoDreamV0Selection::kV0pTMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0EtaMax, femtoDreamV0Selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setSelection(ConfV0DCADaughMax, femtoDreamV0Selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0CPAMin, femtoDreamV0Selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMin, femtoDreamV0Selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMax, femtoDreamV0Selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0DecVtxMax, femtoDreamV0Selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kPosTrack, ConfChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoDreamV0Selection::kNegTrack, ConfChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kPosTrack, ConfChildPIDspecies); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kNegTrack, ConfChildPIDspecies); + v0Cuts.init(&qaRegistry, &V0Registry); + v0Cuts.setInvMassLimits(ConfV0InvMassLowLimit, ConfV0InvMassUpLimit); + v0Cuts.setIsMother(ConfV0MotherIsLambda); + + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfTrkRejectNotPropagated); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kNegTrack, ConfTrkRejectNotPropagated); + + v0Cuts.setnSigmaPIDOffsetTPC(Track.ConfTrkPIDnSigmaOffsetTPC); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kPosTrack, Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kNegTrack, Track.ConfTrkPIDnSigmaOffsetTPC, Track.ConfTrkPIDnSigmaOffsetTOF); + + if (ConfV0RejectKaons) { + v0Cuts.setKaonInvMassLimits(ConfV0InvKaonMassLowLimit, ConfV0InvKaonMassUpLimit); + } + v0Cuts.setRejectLambda(ConfV0RejectLambdas); + } + + if (ConfIsActivateReso.value) { + // resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh,Resonance.ConfDaughterCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPtMax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPtMin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCfClsMin, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + // resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh,Resonance.ConfDaughterCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPtMax, femtoDreamTrackSelection::kpTMax, femtoDreamSelection::kUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPtMin, femtoDreamTrackSelection::kpTMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCfClsMin, femtoDreamTrackSelection::kTPCfClsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterTPCcRowsMin, femtoDreamTrackSelection::kTPCcRowsMin, femtoDreamSelection::kLowerLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); + resoCuts.setDaughterCuts(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + resoCuts.init(&qaRegistry, &V0Registry); + + resoCuts.assign(Resonance.ConfDaughterPTPCThr); // assigns configurable value to class member + resoCuts.setDaughterPIDSpecies(femtoDreamResoSelection::kPosdaugh, Resonance.ConfDaughterPIDspecies); + resoCuts.setDaughterPIDSpecies(femtoDreamResoSelection::kNegdaugh, Resonance.ConfDaughterPIDspecies); + resoCuts.setDaughternSigmaPIDOffset(femtoDreamResoSelection::kPosdaugh, 0.f, 0.f); + resoCuts.setDaughternSigmaPIDOffset(femtoDreamResoSelection::kNegdaugh, 0.f, 0.f); + + resoCuts.setSelection(Resonance.ConfResoSign, femtoDreamResoSelection::kResoSign, femtoDreamSelection::kEqual); + + // resoCuts.init<>(); + } + + mRunNumber = 0; + mMagField = 0.0; + /// Initializing CCDB + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + } + + /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T + void initCCDB_Mag_Trig(aod::BCsWithTimestamps::iterator bc) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + // get magnetic field for run + if (mRunNumber == bc.runNumber()) + return; + auto timestamp = bc.timestamp(); + float output = -999; + + if (ConfIsRun3 && !ConfIsForceGRP) { + static o2::parameters::GRPMagField* grpo = nullptr; + grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return; + } + LOGF(info, "Retrieved GRP for timestamp %llu with L3 ", timestamp, grpo->getL3Current()); + // taken from GRP onject definition of getNominalL3Field; update later to something smarter (mNominalL3Field = std::lround(5.f * mL3Current / 30000.f);) + auto NominalL3Field = std::lround(5.f * grpo->getL3Current() / 30000.f); + output = 0.1 * (NominalL3Field); + + } else { + + static o2::parameters::GRPObject* grpo = nullptr; + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + output = 0.1 * (grpo->getNominalL3Field()); + } + mMagField = output; + mRunNumber = bc.runNumber(); + + // Init for zorro to get trigger flags + if (ConfEnableTriggerSelection) { + zorro.setCCDBpath(ConfBaseCCDBPathForTriggers); + zorro.initCCDB(ccdb.service, mRunNumber, timestamp, zorroTriggerNames); + } + } + + template + void fillDebugParticle(ParticleType const& particle) + { + if constexpr (isTrackOrV0) { + if constexpr (hasItsPid) { + outputDebugParts(particle.sign(), + (uint8_t)particle.tpcNClsFound(), + particle.tpcNClsFindable(), + (uint8_t)particle.tpcNClsCrossedRows(), + particle.tpcNClsShared(), + particle.tpcInnerParam(), + particle.itsNCls(), + particle.itsNClsInnerBarrel(), + particle.dcaXY(), + particle.dcaZ(), + particle.tpcSignal(), + particle.tpcNSigmaEl(), + particle.tpcNSigmaPi(), + particle.tpcNSigmaKa(), + particle.tpcNSigmaPr(), + particle.tpcNSigmaDe(), + particle.tpcNSigmaTr(), + particle.tpcNSigmaHe(), + particle.tofNSigmaEl(), + particle.tofNSigmaPi(), + particle.tofNSigmaKa(), + particle.tofNSigmaPr(), + particle.tofNSigmaDe(), + particle.tofNSigmaTr(), + particle.tofNSigmaHe(), + o2::analysis::femtoDream::itsSignal(particle), + particle.itsNSigmaEl(), + particle.itsNSigmaPi(), + particle.itsNSigmaKa(), + particle.itsNSigmaPr(), + particle.itsNSigmaDe(), + particle.itsNSigmaTr(), + particle.itsNSigmaHe(), + -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999.); + } else { + outputDebugParts(particle.sign(), + (uint8_t)particle.tpcNClsFound(), + particle.tpcNClsFindable(), + (uint8_t)particle.tpcNClsCrossedRows(), + particle.tpcNClsShared(), + particle.tpcInnerParam(), + particle.itsNCls(), + particle.itsNClsInnerBarrel(), + particle.dcaXY(), + particle.dcaZ(), + particle.tpcSignal(), + particle.tpcNSigmaEl(), + particle.tpcNSigmaPi(), + particle.tpcNSigmaKa(), + particle.tpcNSigmaPr(), + particle.tpcNSigmaDe(), + particle.tpcNSigmaTr(), + particle.tpcNSigmaHe(), + particle.tofNSigmaEl(), + particle.tofNSigmaPi(), + particle.tofNSigmaKa(), + particle.tofNSigmaPr(), + particle.tofNSigmaDe(), + particle.tofNSigmaTr(), + particle.tofNSigmaHe(), + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999.); + } + } else if constexpr (isReso) { + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., -999., // for the moment + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999.); + } else { + outputDebugParts(-999., // sign + -999., -999., -999., -999., -999., -999., -999., -999., -999., // track properties (DCA, NCls, crossed rows, etc.) + -999., -999., -999., -999., -999., -999., -999., -999., // TPC PID (TPC signal + particle hypothesis) + -999., -999., -999., -999., -999., -999., -999., // TOF PID + -999., -999., -999., -999., -999., -999., -999., -999., // ITS PID + particle.dcaV0daughters(), + particle.v0radius(), + particle.x(), + particle.y(), + particle.z(), + particle.mK0Short(), + -999., -999., -999., -999., -999., -999., -999.); // Cascade properties + } + } + + template + void fillMCParticle(CollisionType const& col, ParticleType const& particle, o2::aod::femtodreamparticle::ParticleType fdparttype) + { + if (particle.has_mcParticle()) { + // get corresponding MC particle and its info + auto particleMC = particle.mcParticle(); + auto pdgCode = particleMC.pdgCode(); + TrackRegistry.fill(HIST("AnalysisQA/Particle"), pdgCode); + int particleOrigin = 99; + int pdgCodeMother = -1; + // get list of mothers, but it could be empty (for example in case of injected light nuclei) + auto motherparticlesMC = particleMC.template mothers_as(); + // check pdg code + TrackRegistry.fill(HIST("AnalysisQA/getGenStatusCode"), particleMC.getGenStatusCode()); + TrackRegistry.fill(HIST("AnalysisQA/getProcess"), particleMC.getProcess()); + // if this fails, the particle is a fake + if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { + // check first if particle is from pile up + // check if the collision associated with the particle is the same as the analyzed collision by checking their Ids + if ((col.has_mcCollision() && (particleMC.mcCollisionId() != col.mcCollisionId())) || !col.has_mcCollision()) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kWrongCollision; + // check if particle is primary + } else if (particleMC.isPhysicalPrimary()) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; + // check if particle is secondary + // particle is from a decay -> getProcess() == 4 + // particle is generated during transport -> getGenStatusCode() == -1 + // list of mothers is not empty + } else if (particleMC.getProcess() == 4 && particleMC.getGenStatusCode() == -1 && !motherparticlesMC.empty()) { + // get direct mother + auto motherparticleMC = motherparticlesMC.front(); + pdgCodeMother = motherparticleMC.pdgCode(); + TrackRegistry.fill(HIST("AnalysisQA/Mother"), pdgCodeMother); + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); + // check if particle is material + // particle is from inelastic hadronic interaction -> getProcess() == 23 + // particle is generated during transport -> getGenStatusCode() == -1 + } else if (particleMC.getProcess() == 23 && particleMC.getGenStatusCode() == -1) { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kMaterial; + // cross check to see if we missed a case + } else { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kElse; + } + // if pdg code is wrong, particle is fake + } else { + particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kFake; + } + + outputPartsMC(particleOrigin, pdgCode, particleMC.pt(), particleMC.eta(), particleMC.phi()); + outputPartsMCLabels(outputPartsMC.lastIndex()); + if (ConfIsDebug) { + outputPartsExtMCLabels(outputPartsMC.lastIndex()); + outputDebugPartsMC(pdgCodeMother); + } + } else { + outputPartsMCLabels(-1); + if (ConfIsDebug) { + outputPartsExtMCLabels(-1); + } + } + } + + template + void fillMCCollision(CollisionType const& col) + { + if (col.has_mcCollision()) { + auto genMCcol = col.template mcCollision_as(); + outputMCCollision(genMCcol.multMCNParticlesEta08()); + outputCollsMCLabels(outputMCCollision.lastIndex()); + } else { + outputCollsMCLabels(-1); + } + } + template + void fillCollisionsAndTracksAndV0(CollisionType const& col, TrackType const& tracks, TrackTypeWithItsPid const& tracksWithItsPid, V0Type const& fullV0s) + { + // If triggering is enabled, select only events which were triggered wit our triggers + if (ConfEnableTriggerSelection) { + bool zorroSelected = zorro.isSelected(col.template bc_as().globalBC()); /// check if event was selected by triggers of interest + if (!zorroSelected) { + return; + } + } + + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + float mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + if constexpr (useCentrality) { + if constexpr (analysePbPb) { + mult = col.centFT0C(); + } else { + mult = col.centFT0M(); + } + } else { + mult = 0; + } + multNtr = col.multNTracksPV(); + } else { + mult = 1; // multiplicity percentile is know in Run 2 + multNtr = col.multTracklets(); + } + + colCuts.fillQA(col, mult); + + // check whether the basic event selection criteria are fulfilled + // that included checking if there is at least on usable track or V0 + if (!colCuts.isSelectedCollision(col)) { + return; + } + + if (ConfIsActivateV0.value) { + if (colCuts.isEmptyCollision(col, tracks, trackCuts) && colCuts.isEmptyCollision(col, fullV0s, v0Cuts, tracks)) { + return; + } + } else { + if (colCuts.isEmptyCollision(col, tracks, trackCuts)) { + return; + } + } + + if (rctCut.requireRCTFlagChecker && !rctChecker(col)) { + return; + } + + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + if constexpr (isMC) { + fillMCCollision(col); + } + + std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + std::vector tmpIDtrack; // this vector keeps track of the matching of the primary track table row <-> aod::track table global index + + for (auto& track : tracksWithItsPid) { + + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track + trackCuts.fillQA(track); + + if (track.tpcChi2NCl() < OptionTrackSpecialSelections.ConfTrkMinChi2PerClusterTPC || track.tpcChi2NCl() > OptionTrackSpecialSelections.ConfTrkMaxChi2PerClusterTPC) { + continue; + } + if (track.itsChi2NCl() > OptionTrackSpecialSelections.ConfTrkMaxChi2PerClusterITS) { + continue; + } + if ((OptionTrackSpecialSelections.ConfTrkTPCRefit && !track.hasTPC()) || (OptionTrackSpecialSelections.ConfTrkITSRefit && !track.hasITS())) { + continue; + } + + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + + TrackRegistry.fill(HIST("AnalysisQA/Chi2ITSTPCperCluster"), track.itsChi2NCl(), track.tpcChi2NCl()); + TrackRegistry.fill(HIST("AnalysisQA/RefitITSTPC"), track.hasITS(), track.hasTPC()); + + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + std::array cutContainer; + cutContainer = trackCuts.getCutContainer(track, track.pt(), track.eta(), sqrtf(powf(track.dcaXY(), 2.f) + powf(track.dcaZ(), 2.f))); + + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtodreamparticle::ParticleType::kTrack, + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); + tmpIDtrack.push_back(track.globalIndex()); + if (ConfIsDebug.value) { + fillDebugParticle(track); + } + + if constexpr (isMC) { + fillMCParticle(col, track, o2::aod::femtodreamparticle::ParticleType::kTrack); + } + } + + if (ConfIsActivateV0.value) { + for (auto& v0 : fullV0s) { + + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + ///\tocheck funnily enough if we apply the filter the + /// sign of Pos and Neg track is always negative + // const auto dcaXYpos = postrack.dcaXY(); + // const auto dcaZpos = postrack.dcaZ(); + // const auto dcapos = std::sqrt(pow(dcaXYpos, 2.) + pow(dcaZpos, 2.)); + v0Cuts.fillLambdaQA(col, v0, postrack, negtrack); + + if (!v0Cuts.isSelectedMinimal(col, v0, postrack, negtrack)) { + continue; + } + + // if (ConfRejectITSHitandTOFMissing) { + // Uncomment only when TOF timing is solved + // bool itsHit = o2PhysicsTrackSelection->IsSelected(postrack, + // TrackSelection::TrackCuts::kITSHits); bool itsHit = + // o2PhysicsTrackSelection->IsSelected(negtrack, + // TrackSelection::TrackCuts::kITSHits); + // } + + v0Cuts.fillQA(col, v0, postrack, negtrack); ///\todo fill QA also for daughters + auto cutContainerV0 = v0Cuts.getCutContainer(col, v0, postrack, negtrack); + + int postrackID = v0.posTrackId(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + v0.positivept(), v0.positiveeta(), v0.positivephi(), + aod::femtodreamparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kPosPID), + postrack.dcaXY(), + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(col, postrack, o2::aod::femtodreamparticle::ParticleType::kV0Child); + } + int negtrackID = v0.negTrackId(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + v0.negativept(), + v0.negativeeta(), + v0.negativephi(), + aod::femtodreamparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kNegPID), + negtrack.dcaXY(), + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(col, negtrack, o2::aod::femtodreamparticle::ParticleType::kV0Child); + } + std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; + float FillMass = 0.; + float FillMassAnti = 0.; + if (ConfV0MotherIsLambda) { + FillMass = v0.mLambda(); + FillMassAnti = v0.mAntiLambda(); + } else { + FillMass = v0.mK0Short(); + FillMassAnti = FillMass; + } + outputParts(outputCollision.lastIndex(), + v0.pt(), + v0.eta(), + v0.phi(), + aod::femtodreamparticle::ParticleType::kV0, + cutContainerV0.at(femtoDreamV0Selection::V0ContainerPosition::kV0), + 0, + v0.v0cosPA(), + indexChildID, + FillMass, + FillMassAnti); + if (ConfIsDebug.value) { + fillDebugParticle(postrack); // QA for positive daughter + fillDebugParticle(negtrack); // QA for negative daughter + fillDebugParticle(v0); // QA for v0 + } + if constexpr (isMC) { + fillMCParticle(col, v0, o2::aod::femtodreamparticle::ParticleType::kV0); + } + } + } + + if (ConfIsActivatePhi.value) { + resoCuts.updateThreshold(); + + auto SlicePosdaugh = daughter1.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); // o2::framework defined in AnalysisHelper.h + auto SliceNegdaugh = daughter2.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + + for (auto& track1 : SlicePosdaugh) { + if (!resoCuts.DaughterSelectionPos(track1, Resonance.ConfThreshold.value)) + continue; /// loosest cuts for track1 + for (auto& track2 : SliceNegdaugh) { + if (!resoCuts.DaughterSelectionNeg(track2, Resonance.ConfThreshold.value)) + continue; /// loosest cuts for track2 + + bool ResoIsNotAnti = true; /// bool for differentianting between particle/antiparticle + float ResoSign = 1.; + if ((Resonance.ConfDaughterPIDspecies->size() > 1) && (Resonance.ConfDaughterPIDspecies.value[0] != Resonance.ConfDaughterPIDspecies.value[1])) { + auto [isNormal, WrongCombination] = resoCuts.checkCombination(track1, track2, static_cast(Resonance.ConfResoMotherID.value)); + if (WrongCombination) { + continue; + } + if (!isNormal) { + ResoSign = -1.; + } + ResoIsNotAnti = isNormal; + } + /// Resos, where both daughters have the same PID are defaulted to sign 1. and ResoIsNotAnti = true + + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Pt"), track1.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Pt"), track2.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Eta"), track1.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Eta"), track2.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/DcaXY"), track1.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/DcaXY"), track2.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/DcaZ"), track1.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/DcaZ"), track2.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter1/Phi"), track1.phi()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Daughter2/Phi"), track2.phi()); + + /// Get masses for calculating invariant Mass + /// This only works for the case where the mass of opposite charged particles are the same (for example K+/K- have same mass) + auto [MassPart1, MassPart2] = resoCuts.getMassDaughters(static_cast(Resonance.ConfResoMotherID.value)); + + /// Resonance + ROOT::Math::PtEtaPhiMVector tempD1(track1.pt(), track1.eta(), track1.phi(), MassPart1); + ROOT::Math::PtEtaPhiMVector tempD2(track2.pt(), track2.eta(), track2.phi(), MassPart2); + ROOT::Math::PtEtaPhiMVector tempReso = tempD1 + tempD2; + /// Anti-resonance + ROOT::Math::PtEtaPhiMVector tempDA1(track1.pt(), track1.eta(), track1.phi(), MassPart2); + ROOT::Math::PtEtaPhiMVector tempDA2(track2.pt(), track2.eta(), track2.phi(), MassPart1); + ROOT::Math::PtEtaPhiMVector tempAntiReso = tempDA1 + tempDA2; + + if (ResoIsNotAnti) { + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass"), tempReso.M()); + if (!(tempReso.M() > Resonance.ConfResoInvMassLowLimit.value && tempReso.M() < Resonance.ConfResoInvMassUpLimit.value)) + continue; /// MassCut + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMass_phi_selected"), tempReso.M()); + } else { + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMassAnti"), tempAntiReso.M()); + if (!(tempAntiReso.M() > Resonance.ConfResoInvMassLowLimit.value && tempAntiReso.M() < Resonance.ConfResoInvMassUpLimit.value)) + continue; /// MassCut + ResoRegistry.fill(HIST("AnalysisQA/Reso/InvMassAnti_phi_selected"), tempAntiReso.M()); + } + + resoCuts.fillQA(track1, track2); + + ResoRegistry.fill(HIST("AnalysisQA/Reso/Pt_posdaughter_selected"), track1.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Pt_negdaughter_selected"), track2.pt()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Eta_posdaughter_selected"), track1.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Eta_negdaughter_selected"), track2.eta()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAxy_posdaughter_selected"), track1.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAxy_negdaughter_selected"), track2.dcaXY()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAz_posdaughter_selected"), track1.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/DCAz_negdaughter_selected"), track2.dcaZ()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Phi_posdaughter_selected"), track1.phi()); + ResoRegistry.fill(HIST("AnalysisQA/Reso/Phi_negdaughter_selected"), track2.phi()); + + auto Type = resoCuts.getType(track1, track2); // kPhiPosdaughTPC_NegdaughTPC + // kPhiPosdaughTPC_NegdaughTOF + // kPhiPosdaughTPC_NegdaughTPC + // kPhiPosdaughTOF_NegdaughTOF as possible output + + auto Bitmask = resoCuts.getCutContainer(track1, track2, ResoSign); + + /// Get Variables for Output + auto outputReso = tempReso; + auto outputDaugh1 = tempD1; + auto outputDaugh2 = tempD2; + if (!ResoIsNotAnti) { + outputReso = tempAntiReso; + outputDaugh1 = tempDA1; + outputDaugh2 = tempDA2; + } + + // fill FDParticles + int postrkId = track1.globalIndex(); + int RowOfPosTrack = -1; + RowOfPosTrack = getRowDaughters(postrkId, tmpIDtrack); + + childIDs[0] = RowOfPosTrack; // should give me the row + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + track1.pt(), + track1.eta(), + track1.phi(), + aod::femtodreamparticle::ParticleType::kResoChild, + Bitmask[1], + Bitmask[2], + track1.dcaXY(), + childIDs, + outputDaugh1.M(), + outputDaugh2.M()); // fill tempFitVar with dcaXY? + const int rowPosTrk = outputParts.lastIndex(); + + int negtrkId = track2.globalIndex(); + int RowOfNegTrack = -1; + RowOfNegTrack = getRowDaughters(negtrkId, tmpIDtrack); + + childIDs[0] = 0; + childIDs[1] = RowOfNegTrack; + outputParts(outputCollision.lastIndex(), + track2.pt(), + track2.eta(), + track2.phi(), + aod::femtodreamparticle::ParticleType::kResoChild, + Bitmask[3], + Bitmask[4], + track2.dcaXY(), + childIDs, + outputDaugh2.M(), + outputDaugh1.M()); // maybe CPA instead of dcaXY()? as tempFitVar? + const int rowNegTrk = outputParts.lastIndex(); + + // Reso + std::vector IndexChildIds = {rowPosTrk, rowNegTrk}; + outputParts(outputCollision.lastIndex(), + outputReso.pt(), + outputReso.eta(), + outputReso.phi(), + Type, + Bitmask[0], // PIDBit of neg_daugh merged with sign cutBit + Bitmask[2], // PIDBit of pos_daugh + -999.f, + IndexChildIds, + tempReso.M(), + tempAntiReso.M()); // no TempFitVar !! + // needed? + if (ConfIsDebug.value) { + fillDebugParticle(track1); // QA for positive daughter + fillDebugParticle(track2); // QA for negative daughter + fillDebugParticle(outputReso); + } + } + } + } + } + + void + processData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processData, + "Provide experimental data", true); + + void + processData_noCentrality(aod::FemtoFullCollision_noCent const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processData_noCentrality, + "Provide experimental data without centrality information", false); + + void processData_CentPbPb(aod::FemtoFullCollision_CentPbPb const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + auto tracksWithItsPid = soa::Attach(tracks); + + if (ConfUseItsPid.value) { + fillCollisionsAndTracksAndV0(col, tracks, tracksWithItsPid, fullV0s); + } else { + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processData_CentPbPb, + "Provide experimental data with centrality information for PbPb collisions", false); + + void processMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processMC, "Provide MC data", false); + + void processMC_noCentrality(aod::FemtoFullCollision_noCent_MC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processMC_noCentrality, "Provide MC data without requiring a centrality calibration", false); + + void processMC_CentPbPb(aod::FemtoFullCollisionMC_CentPbPb const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0(col, tracks, tracks, fullV0s); + } + PROCESS_SWITCH(femtoDreamProducerTaskResoKshort, processMC_CentPbPb, "Provide MC data with centrality information for PbPb collisions", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoDream/Tasks/CMakeLists.txt b/PWGCF/FemtoDream/Tasks/CMakeLists.txt index 933d50035a9..d3aedd5f125 100644 --- a/PWGCF/FemtoDream/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoDream/Tasks/CMakeLists.txt @@ -24,6 +24,11 @@ o2physics_add_dpl_workflow(femtodream-pair-track-v0 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-pair-v0-reso + SOURCES femtoDreamPairTaskV0Reso.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-pair-track-cascade SOURCES femtoDreamPairTaskTrackCascade.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -44,6 +49,12 @@ o2physics_add_dpl_workflow(femtodream-debug-v0 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-debug-reso + SOURCES femtoDreamDebugReso.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(femtodream-debug-cascade SOURCES femtoDreamDebugCascade.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamDebugReso.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamDebugReso.cxx new file mode 100644 index 00000000000..0643df208f8 --- /dev/null +++ b/PWGCF/FemtoDream/Tasks/femtoDreamDebugReso.cxx @@ -0,0 +1,153 @@ +// Copyright 2019-2022 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 femtoDreamDebugV0.cxx +/// \brief Tasks that reads the particle tables and fills QA histograms for V0s +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" + +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" + +#include "TVector3.h" + +#include "fairlogger/Logger.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis::femtoDream; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoDreamDebugReso { + SliceCache cache; + + struct : ConfigurableGroup { + std::string prefix = std::string("resonance"); + + Configurable ConfReso_PDGCode{"ConfReso_PDGCode", 333, "Reso - PDG code"}; + Configurable ConfReso_ChildPos_PDGCode{"ConfReso_PosChild_PDGCode", 321, "Positive Child - PDG code"}; + Configurable ConfReso_ChildNeg_PDGCode{"ConfReso_NegChild_PDGCode", 321, "Negative Child- PDG code"}; + + ConfigurableAxis ConfResoTempFitVarBins{"ConfResoTempFitVarBins", {300, 0.95, 1.}, "Reso: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfResoTempFitVarMomentumBins{"ConfResoTempFitVarMomentumBins", {20, 0.5, 4.05}, "Reso: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfBinmult{"ConfBinmult", {1, 0, 1}, "multiplicity Binning"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis for inv mass"}; + + Configurable ConfResoTempFitVarMomentum{"ConfResoTempFitVarMomentum", 0, "Momentum used for binning: 0 -> pt; 1 -> preco; 2 -> ptpc"}; + ConfigurableAxis ConfResoInvMassBins{"ConfResoInvMassBins", {200, 1, 1.2}, "Reso: InvMass binning"}; + + ConfigurableAxis ConfResoChildTempFitVarMomentumBins{"ConfResoChildTempFitVarMomentumBins", {600, 0, 6}, "p binning for the p vs Nsigma TPC/TOF plot"}; + ConfigurableAxis ConfResoChildNsigmaTPCBins{"ConfResoChildNsigmaTPCBins", {1600, -8, 8}, "binning of Nsigma TPC plot"}; // TPC and TOf seperate doen't make sense really right?? + ConfigurableAxis ConfResoChildNsigmaTOFBins{"ConfResoChildNsigmaTOFBins", {3000, -15, 15}, "binning of the Nsigma TOF plot"}; + ConfigurableAxis ConfResoChildNsigmaTPCTOFBins{"ConfResoChildNsigmaTPCTOFBins", {1000, 0, 10}, "binning of the Nsigma TPC+TOF plot"}; + ConfigurableAxis ConfResoChildNsigmaITSBins{"ConfResoChildNsigmaITSBins", {600, -3, 3}, "binning of the Nsigma ITS plot"}; + + Configurable ConfReso_ChildPos_CutBit{"ConfReso_ChildPos_CutBit", 4860458, "Positive Child of Reso - Selection bit from cutCulator"}; + Configurable ConfReso_ChildPos_TPCBit{"ConfReso_ChildPos_TPCBit", 16, "Positive Child of Reso - PID bit from cutCulator"}; + Configurable ConfReso_ChildPos_TPCTOFBit{"ConfReso_ChildPos_TPCTOFBit", 8, "Positive Child of Reso - PID bit from cutCulator"}; + Configurable ConfReso_ChildNeg_CutBit{"ConfReso_ChildNeg_CutBit", 4860457, "Negative Child of Reso - PID bit from cutCulator"}; + Configurable ConfReso_ChildNegMerged_TPCBit{"ConfReso_ChildNegMerged_TPCBit", 64, "Negative Child of Reso - PID bit from cutCulator"}; // change + Configurable ConfReso_ChildNegMerged_TPCTOFBit{"ConfReso_ChildNegMerged_TPCTOFBit", 32, "Negative Child of Reso - PID bit from cutCulator"}; // change + ConfigurableAxis ConfChildTempFitVarBins{"ConfChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfChildTempFitVarpTBins{"ConfChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + } resonance; + + using FemtoFullParticles = soa::Join; + + Partition partsTwo = (ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTPC), ncheckbit(aod::femtodreamparticle::pidcut, resonance.ConfReso_ChildPos_TPCBit) && ncheckbit(aod::femtodreamparticle::cut, resonance.ConfReso_ChildNegMerged_TPCBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTOF), ncheckbit(aod::femtodreamparticle::pidcut, resonance.ConfReso_ChildPos_TPCTOFBit) && ncheckbit(aod::femtodreamparticle::cut, resonance.ConfReso_ChildNegMerged_TPCTOFBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTPC), ncheckbit(aod::femtodreamparticle::pidcut, resonance.ConfReso_ChildPos_TPCTOFBit) && ncheckbit(aod::femtodreamparticle::cut, resonance.ConfReso_ChildNegMerged_TPCBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTOF), ncheckbit(aod::femtodreamparticle::pidcut, resonance.ConfReso_ChildPos_TPCBit) && ncheckbit(aod::femtodreamparticle::cut, resonance.ConfReso_ChildNegMerged_TPCTOFBit), false)); + + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + + /// Histogramming + FemtoDreamEventHisto eventHisto; + FemtoDreamParticleHisto posResoChildHistos; + FemtoDreamParticleHisto negResoChildHistos; + FemtoDreamParticleHisto ResoHistos; + + /// Histogram output + HistogramRegistry EventRegistry{"Event", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ResoRegistry{"FullResoQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + posResoChildHistos.init(&ResoRegistry, resonance.ConfBinmult, resonance.ConfDummy, resonance.ConfResoChildTempFitVarMomentumBins, resonance.ConfDummy, resonance.ConfDummy, resonance.ConfChildTempFitVarBins, resonance.ConfResoChildNsigmaTPCBins, resonance.ConfResoChildNsigmaTOFBins, resonance.ConfResoChildNsigmaTPCTOFBins, resonance.ConfResoChildNsigmaITSBins, resonance.ConfResoInvMassBins, resonance.ConfDummy, false, resonance.ConfReso_ChildPos_PDGCode.value, true); // isDebug == TRUE + negResoChildHistos.init(&ResoRegistry, resonance.ConfBinmult, resonance.ConfDummy, resonance.ConfResoChildTempFitVarMomentumBins, resonance.ConfDummy, resonance.ConfDummy, resonance.ConfChildTempFitVarBins, resonance.ConfResoChildNsigmaTPCBins, resonance.ConfResoChildNsigmaTOFBins, resonance.ConfResoChildNsigmaTPCTOFBins, resonance.ConfResoChildNsigmaITSBins, resonance.ConfResoInvMassBins, resonance.ConfDummy, false, resonance.ConfReso_ChildNeg_PDGCode, true); // isDebug == TRUE + ResoHistos.init(&ResoRegistry, resonance.ConfBinmult, resonance.ConfDummy, resonance.ConfResoTempFitVarMomentumBins, resonance.ConfDummy, resonance.ConfDummy, resonance.ConfResoTempFitVarBins, resonance.ConfResoChildNsigmaTPCBins, resonance.ConfResoChildNsigmaTOFBins, resonance.ConfResoChildNsigmaTPCTOFBins, resonance.ConfResoChildNsigmaITSBins, resonance.ConfResoInvMassBins, resonance.ConfDummy, false, resonance.ConfReso_PDGCode.value, true); // isDebug == TRUE, isMc ==FALSE for all + ResoRegistry.add("hArmenterosPodolanski/hArmenterosPodolanskiPlot", "; #alpha; p_{T} (MeV/#it{c})", kTH2F, {{100, -1, 1}, {500, -0.3, 2}}); + } + + /// Porduce QA plots for V0 & Reso selection in FemtoDream framework + void process(o2::aod::FDCollision const& col, FemtoFullParticles const& parts) + { + + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); // maybe . instead of -> ?? + for (auto& part : groupPartsTwo) { + if (!part.has_children()) { + LOG(warn) << " Reso has no children"; + continue; + } + + const auto& posresoChild = parts.iteratorAt(part.index() - 2); + const auto& negresoChild = parts.iteratorAt(part.index() - 1); + if (posresoChild.globalIndex() != part.childrenIds()[0] || negresoChild.globalIndex() != part.childrenIds()[1]) { + continue; + } + if (posresoChild.partType() == uint8_t(aod::femtodreamparticle::ParticleType::kResoChild) && + (posresoChild.cut() & resonance.ConfReso_ChildPos_CutBit) == resonance.ConfReso_ChildPos_CutBit && + negresoChild.partType() == uint8_t(aod::femtodreamparticle::ParticleType::kResoChild) && + (negresoChild.cut() & resonance.ConfReso_ChildNeg_CutBit) == resonance.ConfReso_ChildNeg_CutBit) { + + TVector3 p_parent(part.px(), part.py(), part.pz()); // Parent momentum (px, py, pz) + TVector3 p_plus(posresoChild.px(), posresoChild.py(), posresoChild.pz()); // Daughter 1 momentum (px, py, pz) + TVector3 p_minus(negresoChild.px(), negresoChild.py(), negresoChild.pz()); // Daughter 2 momentum (px, py, pz) + + double pL_plus = p_plus.Dot(p_parent) / p_parent.Mag(); + double pL_minus = p_minus.Dot(p_parent) / p_parent.Mag(); + float alpha = (pL_plus - pL_minus) / (pL_plus + pL_minus); + + TVector3 p_perp = p_plus - (p_parent * (pL_plus / p_parent.Mag())); + double qtarm = p_perp.Mag(); + + ResoRegistry.fill(HIST("hArmenterosPodolanski/hArmenterosPodolanskiPlot"), alpha, qtarm); + + ResoHistos.fillQA(part, static_cast(resonance.ConfResoTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + posResoChildHistos.fillQA(posresoChild, static_cast(resonance.ConfResoTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + negResoChildHistos.fillQA(negresoChild, static_cast(resonance.ConfResoTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + } + } + } +}; + +WorkflowSpec + defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskV0Reso.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskV0Reso.cxx new file mode 100644 index 00000000000..2d026deb70e --- /dev/null +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskV0Reso.cxx @@ -0,0 +1,410 @@ +// 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 femtoDreamPairTaskV0Reso.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Christopher Klumm, TU München, christopher.klumm@cern.ch +/// \author Anton Riedel, TU München, anton.riedel@cern.ch +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@cern.ch + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainer.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" + +#include "TRandom3.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femtoDream; + +struct femtoDreamPairTaskV0Reso { + SliceCache cache; + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; // are my cases included check & add! + + FemtoDreamContainer sameEventCont; + FemtoDreamContainer mixedEventCont; + // FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejectionSE; + FemtoDreamDetaDphiStar pairCloseRejectionME; + + /// General options + struct : ConfigurableGroup { + std::string prefix = std::string("Option"); + Configurable IsMC{"IsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable Use4D{"Use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; + Configurable ExtendedPlots{"ExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable HighkstarCut{"HighkstarCut", -1., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; + Configurable CPROn{"CPROn", true, "Close Pair Rejection"}; + Configurable CPROld{"CPROld", false, "Set to FALSE to use fixed version of CPR (for testing now, will be default soon)"}; + Configurable CPRPlotPerRadii{"CPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable CPRdeltaPhiMax{"CPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable CPRdeltaEtaMax{"CPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable DCACutPtDep{"DCACutPtDep", false, "Use pt dependent dca cut"}; + Configurable MixEventWithPairs{"MixEventWithPairs", true, "Only use events that contain particle 1 and partile 2 for the event mixing"}; + Configurable smearingByOrigin{"smearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; + ConfigurableAxis Dummy{"Dummy", {1, 0, 1}, "Dummy axis"}; + } Option; + + /// Event selection + struct : ConfigurableGroup { + std::string prefix = std::string("EventSel"); + Configurable MultMin{"MultMin", 0, "Minimum Multiplicity (MultNtr)"}; + Configurable MultMax{"MultMax", 99999, "Maximum Multiplicity (MultNtr)"}; + Configurable MultPercentileMin{"MultPercentileMin", 0, "Minimum Multiplicity Percentile"}; + Configurable MultPercentileMax{"MultPercentileMax", 100, "Maximum Multiplicity Percentile"}; + } EventSel; + + /// Binning configurables + struct : ConfigurableGroup { + std::string prefix = std::string("Binning"); + ConfigurableAxis TempFitVarReso{"TempFitVarReso", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis TempFitVarV0{"TempFitVarV0", {300, 0.9, 1}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Reso))"}; + ConfigurableAxis TempFitVarV0Child{"TempFitVarV0Child", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (V0 child)"}; + ConfigurableAxis TempFitVarResoChild{"TempFitVarResoChild", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Reso child)"}; + ConfigurableAxis InvMass{"InvMass", {1500, 0.9, 1.13}, "InvMass binning"}; + ConfigurableAxis pTTrack{"pTTrack", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis pTV0{"pTV0", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0)"}; + ConfigurableAxis pTReso{"pTReso", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (Reso)"}; + ConfigurableAxis pTV0Child{"pTV0Child", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (V0 Child)"}; + ConfigurableAxis pTResoChild{"pTResoChild", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot (Reso Child)"}; + ConfigurableAxis pT{"pT", {20, 0.5, 4.05}, "pT binning"}; + ConfigurableAxis kstar{"kstar", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis kT{"kT", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis mT{"mT", {225, 0., 7.5}, "binning mT"}; + ConfigurableAxis multTempFit{"multTempFit", {1, 0, 1}, "multiplicity for the TempFitVar plot"}; + } Binning; + + struct : ConfigurableGroup { + std::string prefix = std::string("Binning4D"); + ConfigurableAxis kstar{"kstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis mT{"mT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis Mult{"mult", {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}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis multPercentile{"multPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + } Binning4D; + + // Mixing configurables + struct : ConfigurableGroup { + std::string prefix = std::string("Mixing"); + ConfigurableAxis BinMult{"BinMult", {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}, "bins - multiplicity"}; + ConfigurableAxis BinMultPercentile{"BinMultPercentile", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f}, "bins - multiplicity percentile"}; + ConfigurableAxis BinVztx{"BinVztx", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "bins - z-vertex"}; + Configurable Depth{"Depth", 5, "Number of events for mixing"}; + Configurable Policy{"BinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; + } Mixing; + + /// particle 1 (V01), Λ + struct : ConfigurableGroup { + std::string prefix = std::string("V01"); + Configurable PDGCode{"PDGCode", 3122, "PDG code of particle 1 (V0)"}; + Configurable CutBit{"CutBit", 7518, "Selection bit for particle 1 (V0)"}; + Configurable ChildPos_CutBit{"ChildPos_CutBit", 210, "Selection bit for positive child of V01"}; + Configurable ChildPos_TPCBit{"ChildPos_TPCBit", 64, "PID TPC bit for positive child of V01"}; + Configurable ChildNeg_CutBit{"ChildNeg_CutBit", 209, "Selection bit for negative child of V01"}; + Configurable ChildNeg_TPCBit{"ChildNeg_TPCBit", 256, "PID TPC bit for negative child of V01"}; + + Configurable InvMassMin{"InvMassMin", 1.08, "Minimum invariant mass of Partricle 1 (particle) (V0)"}; + Configurable InvMassMax{"InvMassMax", 1.15, "Maximum invariant mass of Partricle 1 (particle) (V0)"}; + Configurable InvMassAntiMin{"InvMassAntiMin", 0., "Minimum invariant mass of Partricle 1 (antiparticle) (V0)"}; // should be the same as for Lambda... + Configurable InvMassAntiMax{"InvMassAntiMax", 999., "Maximum invariant mass of Partricle 1 (antiparticle) (V0)"}; + + Configurable PtMin{"PtMin", 0., "Minimum pT of Partricle 1 (V0)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of Partricle 1 (V0)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of Partricle 1 (V0)"}; + Configurable EtaMax{"EtaMax", 10., "Maximum eta of Partricle 1 (V0)"}; + } V01; // hier evtl noch weiter Configurables einfügen... + + /// particle 2, (Resonance) (needs implementation phi in cut bit ) + struct : ConfigurableGroup { + std::string prefix = std::string("Reso2"); + Configurable PDGCode{"PDGCode", 333, "PDG code of particle 2 (V0)"}; + + Configurable InvMassMin{"InvMassMin", 1.017, "Minimum invariant mass of Partricle 2 (particle) (V0)"}; // phi values for inv mass + Configurable InvMassMax{"InvMassMax", 1.027, "Maximum invariant mass of Partricle 2 (particle) (V0)"}; + Configurable PtMin{"PtMin", 0., "Minimum pT of Partricle 2 (V0)"}; + Configurable PtMax{"PtMax", 999., "Maximum pT of Partricle 2 (V0)"}; + Configurable EtaMin{"EtaMin", -10., "Minimum eta of Partricle 2 (V0)"}; // change values + Configurable EtaMax{"EtaMax", 10., "Maximum eta of Partricle 2 (V0)"}; // change values + + Configurable DaughPos_CutBit{"DaughPos_CutBit", 4860458, "Selection bit for positive child of V02"}; // K+ + Configurable DaughPos_TPCBit{"DaughPos_TPCBit", 64, "PID TPC bit for positive child of V02"}; // NSigma_TPC = 2.5 + Configurable DaughPos_TPCTOFBit{"DaughPos_TOFBit", 32, "PID TOF bit for positive child of V02"}; // NSigma_TOF = 2.5 + Configurable DaughNeg_CutBit{"DaughNeg_CutBit", 4860457, "Selection bit for negative child of V02"}; // K- + Configurable DaughNegMerged_TPCBit{"DaughNegMerged_TPCBit", 64, "PID TPC bit for negative child of V02"}; // NSigma_TPC = 2.5 + Configurable DaughNegMerged_TPCTOFBit{"DaughNegMerged_TPCTOFBit", 32, "PID TOF bit for negative child of V02"}; // NSigma_TOF = 2.5 + } Reso2; + + /// Partition for particle 1 + Partition PartitionV01 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && + ((aod::femtodreamparticle::cut & V01.CutBit) == V01.CutBit) && + (aod::femtodreamparticle::pt > V01.PtMin) && + (aod::femtodreamparticle::pt < V01.PtMax) && + (aod::femtodreamparticle::eta > V01.EtaMin) && + (aod::femtodreamparticle::eta < V01.EtaMax) && + (aod::femtodreamparticle::mLambda > V01.InvMassMin) && + (aod::femtodreamparticle::mLambda < V01.InvMassMax) && + (aod::femtodreamparticle::mAntiLambda > V01.InvMassAntiMin) && + (aod::femtodreamparticle::mAntiLambda < V01.InvMassAntiMax); + + /// Partition for particle 2 + Partition PartitionReso2 = (ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTPC), ncheckbit(aod::femtodreamparticle::pidcut, Reso2.DaughPos_TPCBit) && ncheckbit(aod::femtodreamparticle::cut, Reso2.DaughNegMerged_TPCBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTOF), ncheckbit(aod::femtodreamparticle::pidcut, Reso2.DaughPos_TPCTOFBit) && ncheckbit(aod::femtodreamparticle::cut, Reso2.DaughNegMerged_TPCTOFBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTOF_NegdaughTPC), ncheckbit(aod::femtodreamparticle::pidcut, Reso2.DaughPos_TPCTOFBit) && ncheckbit(aod::femtodreamparticle::cut, Reso2.DaughNegMerged_TPCBit), false) || + ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kPhiPosdaughTPC_NegdaughTOF), ncheckbit(aod::femtodreamparticle::pidcut, Reso2.DaughPos_TPCBit) && ncheckbit(aod::femtodreamparticle::cut, Reso2.DaughNegMerged_TPCTOFBit), false)) && + (aod::femtodreamparticle::pt < Reso2.PtMax) && + (aod::femtodreamparticle::eta > Reso2.EtaMin) && + (aod::femtodreamparticle::eta < Reso2.EtaMax) && + (aod::femtodreamparticle::mLambda > Reso2.InvMassMin) && + (aod::femtodreamparticle::mLambda < Reso2.InvMassMax); + + ColumnBinningPolicy colBinningMult{{Mixing.BinVztx, Mixing.BinMult}, true}; + ColumnBinningPolicy colBinningMultPercentile{{Mixing.BinVztx, Mixing.BinMultPercentile}, true}; + ColumnBinningPolicy colBinningMultMultPercentile{{Mixing.BinVztx, Mixing.BinMult, Mixing.BinMultPercentile}, true}; + + Filter EventMultiplicity = aod::femtodreamcollision::multNtr >= EventSel.MultMin && aod::femtodreamcollision::multNtr <= EventSel.MultMax; + Filter EventMultiplicityPercentile = aod::femtodreamcollision::multV0M >= EventSel.MultPercentileMin && aod::femtodreamcollision::multV0M <= EventSel.MultPercentileMax; + + using FilteredCollisions = soa::Filtered; + using FilteredCollision = FilteredCollisions::iterator; + // no masked yet + + /// Histogramming for particle 1 + FemtoDreamParticleHisto V0HistoPartOne; + FemtoDreamParticleHisto posChildHistos; + FemtoDreamParticleHisto negChildHistos; + + /// Histogramming for particle 2 + /// prob need to add cases in fillQA, fillDebug in femtoDreamParticleHisto + FemtoDreamParticleHisto ResoHistoPartTwo; + FemtoDreamParticleHisto ResoposChildHistos; + FemtoDreamParticleHisto ResonegChildHistos; + + /// Histogram output + HistogramRegistry Registry{"Output", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) // InitContext& context + { + + // setup binnnig policy for mixing + colBinningMult = {{Mixing.BinVztx, Mixing.BinMult}, true}; + colBinningMultPercentile = {{Mixing.BinVztx, Mixing.BinMultPercentile}, true}; + colBinningMultMultPercentile = {{Mixing.BinVztx, Mixing.BinMult, Mixing.BinMultPercentile}, true}; + + eventHisto.init(&Registry, Option.IsMC); + // change them !! + V0HistoPartOne.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTTrack, Option.Dummy, Option.Dummy, Binning.TempFitVarV0, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.IsMC, V01.PDGCode); + posChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + negChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTV0Child, Option.Dummy, Option.Dummy, Binning.TempFitVarV0Child, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + + ResoHistoPartTwo.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTReso, Option.Dummy, Option.Dummy, Binning.TempFitVarReso, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Binning.InvMass, Option.Dummy, Option.IsMC, Reso2.PDGCode); + ResoposChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTResoChild, Option.Dummy, Option.Dummy, Binning.TempFitVarResoChild, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + ResonegChildHistos.init(&Registry, Binning.multTempFit, Option.Dummy, Binning.pTResoChild, Option.Dummy, Option.Dummy, Binning.TempFitVarResoChild, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, Option.Dummy, false, 0); + + sameEventCont.init(&Registry, + Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.BinMult, Mixing.BinMultPercentile, + Binning4D.kstar, Binning4D.mT, Binning4D.Mult, Binning4D.multPercentile, + Option.IsMC, Option.Use4D, Option.ExtendedPlots, + Option.HighkstarCut, + Option.smearingByOrigin, Binning.InvMass); + + sameEventCont.setPDGCodes(V01.PDGCode, Reso2.PDGCode); + mixedEventCont.init(&Registry, + Binning.kstar, Binning.pT, Binning.kT, Binning.mT, Mixing.BinMult, Mixing.BinMultPercentile, + Binning4D.kstar, Binning4D.mT, Binning4D.Mult, Binning4D.multPercentile, + Option.IsMC, Option.Use4D, Option.ExtendedPlots, + Option.HighkstarCut, + Option.smearingByOrigin, Binning.InvMass); + + mixedEventCont.setPDGCodes(V01.PDGCode, Reso2.PDGCode); + // pairCleaner.init(&Registry); + if (Option.CPROn.value) { + pairCloseRejectionSE.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 1, Option.CPROld.value); + pairCloseRejectionME.init(&Registry, &Registry, Option.CPRdeltaPhiMax.value, Option.CPRdeltaEtaMax.value, Option.CPRPlotPerRadii.value, 2, Option.CPROld.value, 99, true); + } + } + + template + void doSameEvent(PartitionType& SliceV01, PartitionType& SliceReso2, TableTracks const& parts, Collision const& col) + { + /// Histogramming for same event missing + + for (auto& v0 : SliceV01) { + const auto& posChild = parts.iteratorAt(v0.index() - 2); + const auto& negChild = parts.iteratorAt(v0.index() - 1); + + if (((posChild.cut() & V01.ChildPos_CutBit) == V01.ChildPos_CutBit) && + ((posChild.pidcut() & V01.ChildPos_TPCBit) == V01.ChildPos_TPCBit) && + ((negChild.cut() & V01.ChildNeg_CutBit) == V01.ChildNeg_CutBit) && + ((negChild.pidcut() & V01.ChildNeg_TPCBit) == V01.ChildNeg_TPCBit)) { + V0HistoPartOne.fillQA(v0, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); // fillQA, here IsDebug == true, false?? + posChildHistos.fillQA(posChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + negChildHistos.fillQA(negChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + } + + for (auto& reso : SliceReso2) { + const auto& posresoChild = parts.iteratorAt(reso.index() - 2); + const auto& negresoChild = parts.iteratorAt(reso.index() - 1); + + if (ncheckbit(posresoChild.cut(), Reso2.DaughPos_CutBit)) { + ResoposChildHistos.fillQA(negresoChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + + if (ncheckbit(negresoChild.cut(), Reso2.DaughNeg_CutBit)) { + ResonegChildHistos.fillQA(posresoChild, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + + if (((posresoChild.cut() & Reso2.DaughPos_CutBit) == Reso2.DaughPos_CutBit) && + ((negresoChild.cut() & Reso2.DaughNeg_CutBit) == Reso2.DaughNeg_CutBit)) { + ResoHistoPartTwo.fillQA(reso, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); // improve + } + } + + /// build particle combinations + for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceV01, SliceReso2))) { + + const auto& posChild = parts.iteratorAt(p1.index() - 2); + const auto& negChild = parts.iteratorAt(p1.index() - 1); + + const auto& posresoChild = parts.iteratorAt(p2.index() - 2); + const auto& negresoChild = parts.iteratorAt(p2.index() - 1); + + if (((posChild.cut() & V01.ChildPos_CutBit) == V01.ChildPos_CutBit) && + ((posChild.pidcut() & V01.ChildPos_TPCBit) == V01.ChildPos_TPCBit) && + ((negChild.cut() & V01.ChildNeg_CutBit) == V01.ChildNeg_CutBit) && + ((negChild.pidcut() & V01.ChildNeg_TPCBit) == V01.ChildNeg_TPCBit) && + + ((posresoChild.cut() & Reso2.DaughPos_CutBit) == Reso2.DaughPos_CutBit) && + ((negresoChild.cut() & Reso2.DaughNeg_CutBit) == Reso2.DaughNeg_CutBit)) { + + if (Option.CPROn.value) { + if (pairCloseRejectionSE.isClosePair(p1, p2, parts, col.magField())) { + continue; + } + } + sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), Option.Use4D, Option.ExtendedPlots, Option.smearingByOrigin); + } + } + } + + template + void doMixedEvent(CollisionType const& cols, PartType const& parts, PartitionType& part1, PartitionType& part2, BinningType policy) + { + + if (Option.MixEventWithPairs.value) { + for (auto const& [collision1, collision2] : soa::selfCombinations(policy, Mixing.Depth.value, -1, cols, cols)) { + // make sure that tracks in same events are not mixed + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } + + auto SliceV01 = part1.sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); // maybe use . + auto SliceReso2 = part2.sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + + if (SliceV01.size() == 0 || SliceReso2.size() == 0) { + continue; + } + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceV01, SliceReso2))) { + + const auto& posChild = parts.iteratorAt(p1.index() - 2); + const auto& negChild = parts.iteratorAt(p1.index() - 1); + + const auto& posresoChild = parts.iteratorAt(p2.index() - 2); + const auto& negresoChild = parts.iteratorAt(p2.index() - 1); + + // why pass if fullfilled?? + if (((posChild.cut() & V01.ChildPos_CutBit) == V01.ChildPos_CutBit) && + ((posChild.pidcut() & V01.ChildPos_TPCBit) == V01.ChildPos_TPCBit) && + ((negChild.cut() & V01.ChildNeg_CutBit) == V01.ChildNeg_CutBit) && + ((negChild.pidcut() & V01.ChildNeg_TPCBit) == V01.ChildNeg_TPCBit) && + + ((posresoChild.cut() & Reso2.DaughPos_CutBit) == Reso2.DaughPos_CutBit) && + ((negresoChild.cut() & Reso2.DaughNeg_CutBit) == Reso2.DaughNeg_CutBit)) { + continue; + } + if (Option.CPROn.value) { + if (pairCloseRejectionME.isClosePair(p1, p2, parts, collision1.magField())) { + continue; + } + } + + mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), Option.Use4D, Option.ExtendedPlots, Option.smearingByOrigin); + } + } + } + } + + void processSameEvent(FilteredCollision& col, FDParticles& parts) // try this. + { + // fillCollision(col); + auto SliceV01 = PartitionV01.sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); // maybe use . + auto SliceReso2 = PartitionReso2.sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + if (SliceV01.size() == 0 && SliceReso2.size() == 0) { + return; + } + eventHisto.fillQA(col); + doSameEvent(SliceV01, SliceReso2, parts, col); + } + PROCESS_SWITCH(femtoDreamPairTaskV0Reso, processSameEvent, "Enable processing same event", true); + + void processMixedEvent(FilteredCollisions& cols, FDParticles const& parts) + { + + switch (Mixing.Policy.value) { + case femtodreamcollision::kMult: + doMixedEvent(cols, parts, PartitionV01, PartitionReso2, colBinningMult); + break; + case femtodreamcollision::kMultPercentile: + doMixedEvent(cols, parts, PartitionV01, PartitionReso2, colBinningMultPercentile); + break; + case femtodreamcollision::kMultMultPercentile: + doMixedEvent(cols, parts, PartitionV01, PartitionReso2, colBinningMultMultPercentile); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + PROCESS_SWITCH(femtoDreamPairTaskV0Reso, processMixedEvent, "Enable processing mixed event", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.cxx b/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.cxx index d6aa862851f..8650b744a05 100644 --- a/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.cxx +++ b/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.cxx @@ -13,13 +13,15 @@ /// \brief Executable that encodes physical selection criteria in a bit-wise /// selection \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -#include -#include -#include #include "PWGCF/FemtoDream/Utils/femtoDreamCutCulator.h" + +#include "PWGCF/DataModel/FemtoDerived.h" #include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" #include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" -#include "PWGCF/DataModel/FemtoDerived.h" + +#include +#include +#include using namespace o2::analysis::femtoDream; @@ -35,8 +37,7 @@ int main(int /*argc*/, char* argv[]) FemtoDreamCutculator cut; cut.init(argv[1]); - std::cout - << "Do you want to work with tracks or V0s or Cascades (T/V/C)? >"; + std::cout << "Do you want to work with tracks or V0s or Cascades or Resonances (T/V/C/R)? >"; std::string choice; std::cin >> choice; @@ -49,6 +50,12 @@ int main(int /*argc*/, char* argv[]) cut.setV0SelectionFromFile("ConfV0"); cut.setTrackSelectionFromFile("ConfChild"); cut.setPIDSelectionFromFile("ConfChild"); + } else if (choice == std::string("R")) { + std::cout << "Do you want to select Resos or one of its daughters (R/T)? >"; + std::cin >> choice; + cut.setResoSelectionFromFile("ConfReso"); + cut.setTrackSelectionFromFile("ConfDaughter"); + cut.setPIDSelectionFromFile("ConfDaughter"); } else if (choice == std::string("C")) { std::cout << "Do you want to select cascades, V0-Daughter tracks of the cascades or the Bachelor track (C/V/B)? >"; std::cin >> choice; diff --git a/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.h b/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.h index f54a9ff62a4..2e0272d684b 100644 --- a/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.h +++ b/PWGCF/FemtoDream/Utils/femtoDreamCutCulator.h @@ -18,21 +18,23 @@ #ifndef PWGCF_FEMTODREAM_UTILS_FEMTODREAMCUTCULATOR_H_ #define PWGCF_FEMTODREAM_UTILS_FEMTODREAMCUTCULATOR_H_ +#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamResoSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamV0Selection.h" + +#include +#include + +#include #include #include #include +#include #include #include #include -#include -#include -#include -#include - -#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamV0Selection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" namespace o2::analysis::femtoDream { @@ -116,18 +118,40 @@ class FemtoDreamCutculator for (const auto& sel : mConfigTree) { std::string sel_name = sel.first; femtoDreamTrackSelection::TrackSel obs; - if (sel_name.find(prefix) != std::string::npos) { - int index = FemtoDreamTrackSelection::findSelectionIndex( - std::string_view(sel_name), prefix); - if (index >= 0) { - obs = femtoDreamTrackSelection::TrackSel(index); - } else { - continue; + /// for Resonances and Tracks the Configs are placed in a struct + if (sel_name == "Track" || sel_name == "Resonance") { + for (const auto& subsel : sel.second) { + std::string subsel_name = subsel.first; + std::string newPrefix = sel_name + "." + prefix; /// adjust prefix, so setSelection can find those selections + const char* newPrefixChar = newPrefix.c_str(); + if (subsel_name.find(prefix) != std::string::npos) { + int index = FemtoDreamTrackSelection::findSelectionIndex( + std::string_view(subsel_name), prefix); + if (index >= 0) { + obs = femtoDreamTrackSelection::TrackSel(index); + } else { + continue; + } + if (obs == femtoDreamTrackSelection::TrackSel::kPIDnSigmaMax) + continue; // kPIDnSigmaMax is a special case + setTrackSelection(obs, FemtoDreamTrackSelection::getSelectionType(obs), + newPrefixChar); + } + } + } else { /// selections are not placed in a struct (V0 and Cascades) + if (sel_name.find(prefix) != std::string::npos) { + int index = FemtoDreamTrackSelection::findSelectionIndex( + std::string_view(sel_name), prefix); + if (index >= 0) { + obs = femtoDreamTrackSelection::TrackSel(index); + } else { + continue; + } + if (obs == femtoDreamTrackSelection::TrackSel::kPIDnSigmaMax) + continue; // kPIDnSigmaMax is a special case + setTrackSelection(obs, FemtoDreamTrackSelection::getSelectionType(obs), + prefix); } - if (obs == femtoDreamTrackSelection::TrackSel::kPIDnSigmaMax) - continue; // kPIDnSigmaMax is a special case - setTrackSelection(obs, FemtoDreamTrackSelection::getSelectionType(obs), - prefix); } } } @@ -139,20 +163,39 @@ class FemtoDreamCutculator std::string PIDnodeName = std::string(prefix) + "PIDspecies"; std::string PIDNsigmaNodeName = std::string(prefix) + "PIDnSigmaMax"; try { - boost::property_tree::ptree& pidNode = mConfigTree.get_child(PIDnodeName); - boost::property_tree::ptree& pidValues = pidNode.get_child("values"); - for (auto& val : pidValues) { - mPIDspecies.push_back( - static_cast(std::stoi(val.second.data()))); + loadPIDFromNode(PIDnodeName, PIDNsigmaNodeName); + } catch (const boost::property_tree::ptree_error& e) { + /// first try to search in structs + std::vector structs{"Track", "Resonance"}; /// Hard-coded number and names of structs + bool found = false; + for (auto& structname : structs) { + try { + std::string PIDnodeNameStruct = structname + "." + PIDnodeName; + std::string PIDNsigmaNodeNameStruct = structname + "." + PIDNsigmaNodeName; + loadPIDFromNode(PIDnodeNameStruct, PIDNsigmaNodeNameStruct); + found = true; + } catch (const boost::property_tree::ptree_error& e) { + // do nothing + } } - boost::property_tree::ptree& pidNsigmaNode = mConfigTree.get_child(PIDNsigmaNodeName); - boost::property_tree::ptree& pidNsigmaValues = pidNsigmaNode.get_child("values"); - for (auto& val : pidNsigmaValues) { - mPIDValues.push_back(std::stof(val.second.data())); + if (!found) { + std::cout << "PID selection not avalible for these skimmed data." << std::endl; } - } catch (const boost::property_tree::ptree_error& e) { - std::cout << "PID selection not avalible for these skimmed data." - << std::endl; + } + } + + void loadPIDFromNode(std::string PIDnodeName, std::string PIDNsigmaNodeName) + { + boost::property_tree::ptree& pidNode = mConfigTree.get_child(PIDnodeName); + boost::property_tree::ptree& pidValues = pidNode.get_child("values"); + for (auto& val : pidValues) { + mPIDspecies.push_back( + static_cast(std::stoi(val.second.data()))); + } + boost::property_tree::ptree& pidNsigmaNode = mConfigTree.get_child(PIDNsigmaNodeName); + boost::property_tree::ptree& pidNsigmaValues = pidNsigmaNode.get_child("values"); + for (auto& val : pidNsigmaValues) { + mPIDValues.push_back(std::stof(val.second.data())); } } @@ -194,6 +237,113 @@ class FemtoDreamCutculator } } + /// Specialization of the setSelection function for Reso + + /// The selection passed to the function is retrieved from the dpl-config.json + /// \param obs Observable of the track selection + /// \param type Type of the track selection + /// \param prefix Prefix which is added to the name of the Configurable + void setResoSelection(femtoDreamResoSelection::ResoSel obs, + femtoDreamSelection::SelectionType type, + const char* prefix) + { + auto tmpVec = + setSelection(FemtoDreamResoSelection::getSelectionName(obs, prefix)); + if (tmpVec.size() > 0) { + mResoSel.setSelection(tmpVec, obs, type); + } + } + + /// Automatically retrieves Reso selections from the dpl-config.json + /// \param prefix Prefix which is added to the name of the Configurable + void setResoSelectionFromFile(const char* prefix) + { + /// every Reso selection is placed in the struct + boost::property_tree::ptree& ResonanceStruct = mConfigTree.get_child("Resonance"); + for (const auto& sel : ResonanceStruct) { + std::string sel_name = sel.first; + femtoDreamResoSelection::ResoSel obs; + if (sel_name.find(prefix) != std::string::npos) { + int index = FemtoDreamResoSelection::findSelectionIndex( + std::string_view(sel_name), prefix); + if (index >= 0) { + obs = femtoDreamResoSelection::ResoSel(index); + } else { + continue; + } + std::string newPrefix = std::string("Resonance.") + prefix; /// adjust prefix, so setSelection can find those selections + const char* newPrefixChar = newPrefix.c_str(); + setResoSelection(obs, FemtoDreamResoSelection::getSelectionType(obs), + newPrefixChar); + } + } + } + + // Takes as input string of tokens sperated by a delimeter e.g a|b + // And fill a vector with the tokens as entry e.g {a,b} + std::vector Split(const std::string& s, const std::string& delimiter) + { + std::vector tokens; + size_t start = 0, end = 0; + while ((end = s.find(delimiter, start)) != std::string::npos) { + tokens.push_back(s.substr(start, end - start)); + start = end + delimiter.length(); + } + tokens.push_back(s.substr(start)); + return tokens; + } + + // finds the mostsignificant bit of a decimal value + // returns value for shifting + template + size_t numBitsUsed(V const& origvalue) + { + size_t bits = 0; + auto value = origvalue; + while (value != 0) { + ++bits; + value >>= 1; + } + return bits; + } + + // Takes as input string of decimal values and sign + // gives as pouput merged pid-cutbits for mother particle of the resonance + template + void Bitmerger(std::string value, V const& output) + { + + std::vector vec = Split(value, "|"); + + uint32_t pos_TPC = static_cast(std::stoul(vec[0])); + uint32_t neg_TPC = static_cast(std::stoul(vec[1])); + + uint32_t pos_TPCTOF = static_cast(std::stoul(vec[2])); + uint32_t neg_TPCTOF = static_cast(std::stoul(vec[3])); + + auto outputTPC = (pos_TPC << numBitsUsed(neg_TPC)) | neg_TPC; + auto outputTPC_TPC_final = (outputTPC << numBitsUsed(output)) | output; + + auto outputTPCTOF = (pos_TPCTOF << numBitsUsed(neg_TPCTOF)) | neg_TPCTOF; + auto outputTPCTOF_TPCTOF_final = (outputTPCTOF << numBitsUsed(output)) | output; + + auto outputTPC_TOF = (pos_TPC << numBitsUsed(neg_TPCTOF)) | neg_TPCTOF; + auto outputTPC_TPCTOF_final = (outputTPC_TOF << numBitsUsed(output)) | output; + + auto outputTPCTOF_TPC = (pos_TPCTOF << numBitsUsed(neg_TPC)) | neg_TPC; + auto outputTPCTOF_TPC_final = (outputTPCTOF_TPC << numBitsUsed(output)) | output; + + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + std::cout << "Bitstring for TPC_TPC: " << outputTPC_TPC_final << std::endl; + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + std::cout << "Bitstring for TPCTOF_TPCTOF: " << outputTPCTOF_TPCTOF_final << std::endl; + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + std::cout << "Bitstring for TPC_TPCTOF: " << outputTPC_TPCTOF_final << std::endl; + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + std::cout << "Bitstring for TPCTOF_TPC: " << outputTPCTOF_TPC_final << std::endl; + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + } + /// Specialization of the setSelection function for Cascades /// The selection passed to the function is retrieved from the dpl-config.json @@ -360,6 +510,14 @@ class FemtoDreamCutculator output = iterateSelection(mV0Sel, SysChecks, sign); } else if (choice == std::string("C")) { output = iterateSelection(mCascadeSel, SysChecks, sign); + } else if (choice == std::string("R")) { + output = iterateSelection(mResoSel, SysChecks, sign); + std::cout << "You are now using the bitmerger to create pid-cut for the Resonance" << std::endl; + std::cout << "Please provide the following: Nsigma-TPC_pos_daugh|Nsigma-TPC_neg_daugh|Nsigma-TPCTOF_pos_daugh|Nsigma-TPCTOF_neg_daugh as decimal values >" << std::endl; + std::string bitstring; + std::cin >> bitstring; + Bitmerger(bitstring, output); + return; } else { std::cout << "Option " << choice << " not recognized - available options are (T/V)" << std::endl; @@ -421,6 +579,7 @@ class FemtoDreamCutculator boost::property_tree::ptree mConfigTree; ///< the dpl-config.json buffered into a ptree FemtoDreamTrackSelection mTrackSel; ///< for setting up the bit-wise selection container for tracks FemtoDreamV0Selection mV0Sel; ///< for setting up the bit-wise selection container for V0s + FemtoDreamResoSelection mResoSel; ///< for setting up the bit-wise selection container for Resos FemtoDreamCascadeSelection mCascadeSel; ///< for setting up the bit-wise selection container for Cascades std::vector mPIDspecies; ///< list of particle species for which PID is stored std::vector mPIDValues; ///< list of nsigma values for which PID is stored