|
| 1 | +// Copyright 2019-2022 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +/// \file femtoUniverseEfficiencyBase.cxx |
| 13 | +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks |
| 14 | +/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch |
| 15 | + |
| 16 | +#include <vector> |
| 17 | +#include <random> |
| 18 | +#include "Framework/AnalysisTask.h" |
| 19 | +#include "Framework/runDataProcessing.h" |
| 20 | +#include "Framework/HistogramRegistry.h" |
| 21 | +#include "Framework/ASoAHelpers.h" |
| 22 | +#include "Framework/RunningWorkflowInfo.h" |
| 23 | +#include "Framework/StepTHn.h" |
| 24 | +#include "Framework/O2DatabasePDGPlugin.h" |
| 25 | +#include "TDatabasePDG.h" |
| 26 | + |
| 27 | +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" |
| 28 | +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" |
| 29 | +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" |
| 30 | +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" |
| 31 | +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" |
| 32 | +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" |
| 33 | +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" |
| 34 | + |
| 35 | +using namespace o2; |
| 36 | +using namespace o2::analysis::femtoUniverse; |
| 37 | +using namespace o2::framework; |
| 38 | +using namespace o2::framework::expressions; |
| 39 | +using namespace o2::soa; |
| 40 | + |
| 41 | +namespace |
| 42 | +{ |
| 43 | +static constexpr int nPart = 2; |
| 44 | +static constexpr int nCuts = 5; |
| 45 | +static const std::vector<std::string> partNames{"PartOne", "PartTwo"}; |
| 46 | +static const std::vector<std::string> cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; |
| 47 | +static const float cutsTable[nPart][nCuts]{ |
| 48 | + {4.05f, 1.f, 3.f, 3.f, 100.f}, |
| 49 | + {4.05f, 1.f, 3.f, 3.f, 100.f}}; |
| 50 | +} // namespace |
| 51 | + |
| 52 | +struct femtoUniverseEfficiencyBase { |
| 53 | + SliceCache cache; |
| 54 | + Preslice<aod::FDParticles> perCol = aod::femtouniverseparticle::fdCollisionId; |
| 55 | + |
| 56 | + /// Particle selection part |
| 57 | + /// Configurables for both particles |
| 58 | + Configurable<int> ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; |
| 59 | + Configurable<LabeledArray<float>> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; |
| 60 | + Configurable<bool> ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; |
| 61 | + Configurable<float> ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; |
| 62 | + |
| 63 | + /// Particle 1 |
| 64 | + Configurable<int32_t> ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; |
| 65 | + Configurable<bool> ConfNoPDGPartOne{"ConfNoPDGPartOne", false, "0: selecting part by PDG, 1: no PID selection"}; |
| 66 | + Configurable<float> ConfPtLowPart1{"ConfPtLowPart1", 0.2, "Lower limit for Pt for the first particle"}; |
| 67 | + Configurable<float> ConfPtHighPart1{"ConfPtHighPart1", 2.5, "Higher limit for Pt for the first particle"}; |
| 68 | + |
| 69 | + /// Partition for particle 1 |
| 70 | + Partition<aod::FDParticles> partsOneMCGen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartOne || aod::femtouniverseparticle::pidcut == uint32_t(ConfPDGCodePartOne)) && |
| 71 | + aod::femtouniverseparticle::pt < ConfPtHighPart1 && aod::femtouniverseparticle::pt > ConfPtLowPart1&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; |
| 72 | + |
| 73 | + Partition<aod::FDParticles> partsTrackOneMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); |
| 74 | + |
| 75 | + /// Histogramming for particle 1 |
| 76 | + FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kMCTruthTrack, 1> trackHistoPartOneGen; |
| 77 | + FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kTrack, 1> trackHistoPartOneRec; |
| 78 | + |
| 79 | + /// Particle 2 |
| 80 | + Configurable<bool> ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; |
| 81 | + Configurable<int32_t> ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 333, "Particle 2 - PDG code"}; |
| 82 | + Configurable<bool> ConfNoPDGPartTwo{"ConfNoPDGPartTwo", false, "0: selecting part by PDG, 1: no PID selection"}; |
| 83 | + Configurable<float> ConfPtLowPart2{"ConfPtLowPart2", 0.2, "Lower limit for Pt for the second particle"}; |
| 84 | + Configurable<float> ConfPtHighPart2{"ConfPtHighPart2", 2.5, "Higher limit for Pt for the second particle"}; |
| 85 | + |
| 86 | + /// Partition for particle 2 |
| 87 | + Partition<aod::FDParticles> partsTwoGen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartTwo || aod::femtouniverseparticle::pidcut == uint32_t(ConfPDGCodePartTwo)) && |
| 88 | + aod::femtouniverseparticle::pt < ConfPtHighPart2 && aod::femtouniverseparticle::pt > ConfPtLowPart2&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; |
| 89 | + |
| 90 | + Partition<aod::FDParticles> partsTrackTwoMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); |
| 91 | + |
| 92 | + /// Histogramming for particle 2 |
| 93 | + FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kMCTruthTrack, 2> trackHistoPartTwoGen; |
| 94 | + FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kTrack, 2> trackHistoPartTwoRec; |
| 95 | + |
| 96 | + /// Histogramming for Event |
| 97 | + FemtoUniverseEventHisto eventHisto; |
| 98 | + |
| 99 | + /// The configurables need to be passed to an std::vector |
| 100 | + int vPIDPartOne, vPIDPartTwo; |
| 101 | + std::vector<float> kNsigma; |
| 102 | + |
| 103 | + /// particle part |
| 104 | + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; |
| 105 | + ConfigurableAxis ConfTempFitVarPDGBins{"ConfDTempFitVarInvMassBins", {6000, -2300, 2300}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; |
| 106 | + |
| 107 | + /// Correlation part |
| 108 | + ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task |
| 109 | + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; |
| 110 | + |
| 111 | + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<ConfUse3D>> to true in order to use)"}; |
| 112 | + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <<ConfUse3D>> to true in order to use)"}; |
| 113 | + |
| 114 | + ColumnBinningPolicy<aod::collision::PosZ, aod::femtouniversecollision::MultNtr> colBinning{{ConfVtxBins, ConfMultBins}, true}; |
| 115 | + |
| 116 | + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; |
| 117 | + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; |
| 118 | + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; |
| 119 | + Configurable<int> ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; |
| 120 | + Configurable<bool> ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; |
| 121 | + Configurable<bool> ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; |
| 122 | + Configurable<int> ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; |
| 123 | + Configurable<int> ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; |
| 124 | + |
| 125 | + FemtoUniverseContainer<femtoUniverseContainer::EventType::same, femtoUniverseContainer::Observable::kstar> sameEventCont; |
| 126 | + // FemtoUniversePairCleaner<aod::femtouniverseparticle::ParticleType::kMCTruthTrack, aod::femtouniverseparticle::ParticleType::kMCTruthTrack> pairCleaner; |
| 127 | + /// Histogram output |
| 128 | + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 129 | + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 130 | + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 131 | + |
| 132 | + /// @brief Counter for particle swapping |
| 133 | + int fNeventsProcessed = 0; |
| 134 | + |
| 135 | + void init(InitContext&) |
| 136 | + { |
| 137 | + |
| 138 | + eventHisto.init(&qaRegistry); |
| 139 | + trackHistoPartOneGen.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartOne, false); |
| 140 | + trackHistoPartOneRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartOne, false); |
| 141 | + if (!ConfIsSame) { |
| 142 | + trackHistoPartTwoGen.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartTwo, false); |
| 143 | + trackHistoPartTwoRec.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartTwo, false); |
| 144 | + } |
| 145 | + |
| 146 | + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); |
| 147 | + |
| 148 | + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, 0, ConfUse3D); |
| 149 | + sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); |
| 150 | + // pairCleaner.init(&qaRegistry); |
| 151 | + } |
| 152 | + |
| 153 | + template <typename CollisionType> |
| 154 | + void fillCollision(CollisionType col) |
| 155 | + { |
| 156 | + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); |
| 157 | + eventHisto.fillQA(col); |
| 158 | + } |
| 159 | + |
| 160 | + /// This function processes the same event and takes care of all the histogramming |
| 161 | + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... |
| 162 | + /// @tparam PartitionType |
| 163 | + /// @tparam PartType |
| 164 | + /// @tparam isMC: enables Monte Carlo truth specific histograms |
| 165 | + /// @param grouppartsOneMCGen partition for the first particle passed by the process function |
| 166 | + /// @param grouppartsTwoGen partition for the second particle passed by the process function |
| 167 | + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) |
| 168 | + /// @param magFieldTesla magnetic field of the collision |
| 169 | + /// @param multCol multiplicity of the collision |
| 170 | + template <bool isMC, typename PartitionType> |
| 171 | + void doMCGen(PartitionType grouppartsOneMCGen, PartitionType grouppartsTwoGen, float /*magFieldTesla*/, int multCol) |
| 172 | + { |
| 173 | + bool swpart = fNeventsProcessed % 2; |
| 174 | + fNeventsProcessed++; |
| 175 | + |
| 176 | + /// Histogramming same event |
| 177 | + for (auto& part : grouppartsOneMCGen) { |
| 178 | + |
| 179 | + trackHistoPartOneGen.fillQA<isMC, false>(part); |
| 180 | + } |
| 181 | + |
| 182 | + if (!ConfIsSame) { |
| 183 | + for (auto& part : grouppartsTwoGen) { |
| 184 | + |
| 185 | + trackHistoPartTwoGen.fillQA<isMC, false>(part); |
| 186 | + } |
| 187 | + } |
| 188 | + /// Now build the combinations |
| 189 | + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(grouppartsOneMCGen, grouppartsTwoGen))) { |
| 190 | + // track cleaning |
| 191 | + // if (!pairCleaner.isCleanPair(p1, p2, parts)) { |
| 192 | + // continue; |
| 193 | + // } |
| 194 | + if (swpart) |
| 195 | + sameEventCont.setPair<isMC>(p1, p2, multCol, ConfUse3D); |
| 196 | + else |
| 197 | + sameEventCont.setPair<isMC>(p2, p1, multCol, ConfUse3D); |
| 198 | + |
| 199 | + swpart = !swpart; |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + /// This function processes the same event and takes care of all the histogramming |
| 204 | + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... |
| 205 | + /// @tparam PartitionType |
| 206 | + /// @tparam PartType |
| 207 | + /// @tparam isMC: enables Monte Carlo truth specific histograms |
| 208 | + /// @param grouppartsOneMCGen partition for the first particle passed by the process function |
| 209 | + /// @param grouppartsTwoGen partition for the second particle passed by the process function |
| 210 | + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) |
| 211 | + /// @param magFieldTesla magnetic field of the collision |
| 212 | + /// @param multCol multiplicity of the collision |
| 213 | + template <bool isMC, typename PartitionType> |
| 214 | + void doMCRec(PartitionType grouppartsOneMCGen, PartitionType grouppartsTwoGen, float /*magFieldTesla*/, int multCol) |
| 215 | + { |
| 216 | + bool swpart = fNeventsProcessed % 2; |
| 217 | + fNeventsProcessed++; |
| 218 | + |
| 219 | + /// Histogramming same event |
| 220 | + for (auto& part : grouppartsOneMCGen) { |
| 221 | + |
| 222 | + trackHistoPartOneRec.fillQA<isMC, false>(part); |
| 223 | + } |
| 224 | + |
| 225 | + if (!ConfIsSame) { |
| 226 | + for (auto& part : grouppartsTwoGen) { |
| 227 | + |
| 228 | + trackHistoPartTwoRec.fillQA<isMC, false>(part); |
| 229 | + } |
| 230 | + } |
| 231 | + /// Now build the combinations |
| 232 | + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(grouppartsOneMCGen, grouppartsTwoGen))) { |
| 233 | + // track cleaning |
| 234 | + // if (!pairCleaner.isCleanPair(p1, p2, parts)) { |
| 235 | + // continue; |
| 236 | + // } |
| 237 | + if (swpart) |
| 238 | + sameEventCont.setPair<isMC>(p1, p2, multCol, ConfUse3D); |
| 239 | + else |
| 240 | + sameEventCont.setPair<isMC>(p2, p1, multCol, ConfUse3D); |
| 241 | + |
| 242 | + swpart = !swpart; |
| 243 | + } |
| 244 | + } |
| 245 | + |
| 246 | + /// process function for to call doMCPlots with Data |
| 247 | + /// \param col subscribe to the collision table (Data) |
| 248 | + /// \param parts subscribe to the femtoUniverseParticleTable |
| 249 | + void processTrackTrack(o2::aod::FDCollision& col, |
| 250 | + o2::aod::FDParticles&) |
| 251 | + { |
| 252 | + fillCollision(col); |
| 253 | + // MCGen |
| 254 | + auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); |
| 255 | + auto thegrouppartsTwoGen = partsTwoGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); |
| 256 | + doMCGen<false>(thegrouppartsOneMCGen, thegrouppartsTwoGen, col.magField(), col.multNtr()); |
| 257 | + // MCRec |
| 258 | + auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); |
| 259 | + auto thegroupPartsTrackTwoReco = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); |
| 260 | + doMCRec<false>(thegroupPartsTrackOneRec, thegroupPartsTrackTwoReco, col.magField(), col.multNtr()); |
| 261 | + } |
| 262 | + PROCESS_SWITCH(femtoUniverseEfficiencyBase, processTrackTrack, "Enable processing track-track efficiency task", true); |
| 263 | +}; |
| 264 | + |
| 265 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
| 266 | +{ |
| 267 | + WorkflowSpec workflow{ |
| 268 | + adaptAnalysisTask<femtoUniverseEfficiencyBase>(cfgc), |
| 269 | + }; |
| 270 | + return workflow; |
| 271 | +} |
0 commit comments